Skip to content

Commit

Permalink
Merge pull request #95 from SeanMcGrath/local-storage
Browse files Browse the repository at this point in the history
  • Loading branch information
SeanMcGrath authored May 9, 2020
2 parents 3b44e32 + 2bc5021 commit 49919a1
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 25 deletions.
52 changes: 52 additions & 0 deletions app/client/jsx/LocalStorage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const ttl = 10 * 60 * 1000 // 10 mins
const topLevelKey = "APP"

function getTopLevel() {
const topLevel = localStorage.getItem(topLevelKey)
return topLevel ? JSON.parse(topLevel) : null
}

export default class LocalStorage {

static set(key, value) {
const now = new Date()
const item = {
value,
expiry: now.getTime() + ttl
}

const current = getTopLevel() || {}
current[key] = item

localStorage.setItem(topLevelKey, JSON.stringify(current))
}

static get(key) {
let state = getTopLevel()
if (!state) {
return null
}

const item = state[key]
if (!item) {
return null
}

const now = new Date()
if (now.getTime() > item.expiry) {
delete state[key]
localStorage.setItem(topLevelKey, state)
return null
}

return item.value
}

// reset TTL
static touch(key) {
const currentValue = LocalStorage.get(key)
if (currentValue) {
LocalStorage.set(key, currentValue)
}
}
}
43 changes: 30 additions & 13 deletions app/client/jsx/Room.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Door from './Door.jsx'
import Adventure from './Adventure.jsx'
import Navigation from './Navigation.jsx'
import { WebSocketApi } from './WebAPI.jsx'
import LocalStorage from './LocalStorage.jsx'

class Room extends Component {
/*
Expand All @@ -27,6 +28,8 @@ class Room extends Component {
constructor(props) {
super(props)

const { room, entered } = this.props.currentRoom

// These are the room types for which we show the map button
this.roomTypesWithMap = {
jitsi: true,
Expand All @@ -40,14 +43,10 @@ class Room extends Component {
iframe: true
}

// Rooms that don't have doors are automatically "entered"
const { room, entered } = this.props.currentRoom
const { type } = this.props.rooms[this.props.currentRoom.room]

this.state = {
room,
entered: this.roomTypesWithDoors[type] ? entered : true,
showMap: false
entered: false,
users: []
}

this.socketApi = new WebSocketApi()
Expand Down Expand Up @@ -137,6 +136,7 @@ class Room extends Component {
setTimeout(this.updateRoom.bind(this, room), 500)
} else {
this.updateRoom(room)
document.activeElement.blur()
}
this.setState({ showMap: false })
}
Expand Down Expand Up @@ -165,7 +165,27 @@ class Room extends Component {
this.setState({ showMap: false })
}

computeMapState(room) {
const mapAlreadyUnlocked = LocalStorage.get("MAP_UNLOCKED")
const mapUnlockThreshold = 3
const visitedRooms = Object.values(this.props.visited).filter(x => x).length
const isMapUnlocked = mapAlreadyUnlocked ||
(_.has(this.roomTypesWithMap, room.type) && (visitedRooms >= mapUnlockThreshold))
const showMapTooltip = !mapAlreadyUnlocked && isMapUnlocked
LocalStorage.set("MAP_UNLOCKED", isMapUnlocked)
return {
mapVisible: isMapUnlocked,
showMapTooltip: showMapTooltip
}
}

render() {
if (Object.keys(this.props.rooms).length === 0) {
// room config not loaded yet
return null
}

LocalStorage.touch("USER") // keep session alive
const room = this.props.rooms[this.state.room]

if (room.type === 'redirect') {
Expand All @@ -179,11 +199,7 @@ class Room extends Component {
<Door room={room} users={userList} tintColor={room.doorTint} onClick={this.onEnterRoom.bind(this)}></Door>

const roomClass = this.state.entered ? "room entered" : "room"

const mapUnlockThreshold = 3
const visitedRooms = Object.values(this.props.visited).filter(x => x).length
const isMapUnlocked = _.has(this.roomTypesWithMap, room.type) && (visitedRooms >= mapUnlockThreshold)
const showMapTooltip = isMapUnlocked && visitedRooms == mapUnlockThreshold
const mapState = this.computeMapState(room)

// Allows modal to have access to react components and state
Modal.setAppElement('.app')
Expand All @@ -198,8 +214,8 @@ class Room extends Component {
<Navigation
directions={room.directions}
onClick={this.onSwitchRoom.bind(this)}
showMapButton={isMapUnlocked}
showMapTooltip={showMapTooltip}
showMapButton={mapState.mapVisible}
showMapTooltip={mapState.showMapTooltip}
handleOpenMap={this.handleOpenMap.bind(this)}></Navigation>
<Beforeunload onBeforeunload={this.handleBeforeUnload.bind(this)} />
<Modal
Expand All @@ -214,6 +230,7 @@ class Room extends Component {
}

export default connect(state => state, {
addRooms: reducers.addRoomsActionCreator,
updateUsers: reducers.updateUsersActionCreator,
updateCurrentRoom: reducers.updateCurrentRoomActionCreator
})(Room)
44 changes: 32 additions & 12 deletions app/client/jsx/Welcome.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,29 @@ import reducers from './reducers.jsx'
import { Redirect } from 'react-router-dom'
import PuckSelect from './PuckSelect.jsx'
import { HttpApi } from './WebAPI.jsx'
import LocalStorage from './LocalStorage.jsx'

class Welcome extends Component {
constructor(props) {
super(props)
this.state = {
username: null,
avatar: null,
redirect: null
}

this.httpApi = new HttpApi()

let user = LocalStorage.get("USER")
if (user) {
this.state = {
username: user.username,
avatar: user.avatar,
redirect: "/party"
}
this.handleUserSelected(user)
} else {
this.state = {
username: null,
avatar: null,
redirect: null
}
}
}

async fetchRooms() {
Expand Down Expand Up @@ -54,19 +67,26 @@ class Welcome extends Component {
const response = await this.httpApi.join(this.state.username, this.state.avatar)
if (response.success) {
const { username, avatar } = this.state
this.props.updateUser({
const user = {
username,
avatar,
userId: response.userId
})
this.props.updateCurrentRoom({
room: 'vestibule',
entered: false
})
this.setState({ redirect: '/party' })
}
this.props.updateUser(user)
this.handleUserSelected(user)
this.setState({redirect: '/party'})
}
}

handleUserSelected(user) {
LocalStorage.set("USER", user)
this.props.updateUser(user)
this.props.updateCurrentRoom({
room: 'vestibule',
entered: false
})
}

render() {
if (this.state.redirect) {
return <Redirect to={this.state.redirect}/>
Expand Down

0 comments on commit 49919a1

Please sign in to comment.