1
0
Fork 0
forked from TWS/kalkutago
kalkutago/client/src/state.ts

105 lines
3.4 KiB
TypeScript

import { reactive } from "vue"
import { Track } from "./track"
import { Tick } from './ticks'
import { error } from "./error"
import { getCookie } from "./util";
import router from './router'
enum State {
Unfetched,
Fetching,
Fetched,
}
interface LoggedInUser {
name: string
}
class AppState {
tracks: Array<Track>
state: State
user?: LoggedInUser
source?: EventSource
constructor() {
this.tracks = new Array<Track>
this.state = State.Unfetched
const name = getCookie("name")
if (name) this.user = { name }
}
streamUpdatesFromServer() {
const source = new EventSource("/api/v1/updates")
source.addEventListener("open", () => console.debug("opened event source"))
source.addEventListener('message', event => console.log(event))
source.addEventListener('TickAdded', event => {
const tick: Tick = Tick.fromJSON(JSON.parse(event.data))
const tracks = this.tracks.map(track => {
if (track.id === tick.track_id) {
const ticks = track.ticks ?? []
ticks.push(tick)
track.ticks = ticks
}
return track
})
this.tracks = tracks
})
source.addEventListener('TrackAdded', ({ data }) => {
const track: Track = Track.fromJSON(JSON.parse(data))
this.tracks = [track, ...this.tracks]
})
source.addEventListener('TickDropped', event => {
const tick: Tick = Tick.fromJSON(JSON.parse(event.data))
const tracks = this.tracks.map(track => {
if (track.id === tick.track_id) {
track.ticks = track.ticks?.filter($tick => $tick.id !== tick.id)
}
return track
})
this.tracks = tracks
})
source.addEventListener('TrackDropped', ({ data }) => {
const track: Track = Track.fromJSON(JSON.parse(data))
this.tracks = this.tracks.filter($track => $track.id !== track.id)
})
source.addEventListener('TrackChanged', ({ data }) => {
const track: Track = Track.fromJSON(JSON.parse(data))
this.tracks = this.tracks.map($track => $track.id === track.id ? track : $track)
})
source.addEventListener('Lagged', event => {
console.log(event)
// Refresh the page, refetching the list of tracks and ticks
window.location = window.location
})
source.addEventListener('error', event => {
error(event)
window.location = window.location
})
window.addEventListener('beforeunload', () => source.close())
this.source = source
}
async repopulate() {
if (!this.user) {
this.tracks = []
return
}
this.state = State.Fetching
this.tracks = await Track.fetchAll()
this.source?.close()
this.streamUpdatesFromServer()
this.state = State.Fetched
}
async populate() {
if (this.state != State.Unfetched) return
await this.repopulate()
}
async logOut() {
const result = await fetch('/api/v1/auth', {method: 'DELETE'})
if(!result.ok) return error('failed to log out')
this.user = undefined
router.push('/login')
}
}
export const state = reactive(new AppState)