@deskthing/cli
Version:
An emulator for the DeskThing Server
118 lines (97 loc) • 3.81 kB
text/typescript
import { create } from 'zustand'
import { ClientToDeviceData, DeviceToClientCore, DEVICE_CLIENT, AppManifest } from '@deskthing/types'
import { ClientService } from '../services/clientService'
import { ClientLogger } from '../services/clientLogger'
import { useClientStore } from './clientStore'
interface MessageState {
// Message queue for debugging
messageHistory: Array<{ timestamp: number; type: string; data: any }>
// Actions
handleIframeMessage: (data: ClientToDeviceData, origin: string) => void
sendToIframe: (data: DeviceToClientCore) => void
addToHistory: (type: string, data: any) => void
clearHistory: () => void
}
export const useMessageStore = create<MessageState>()((set, get) => ({
messageHistory: [],
addToHistory: (type, data) =>
set((state) => ({
messageHistory: [
...state.messageHistory.slice(-99), // Keep last 100 messages
{ timestamp: Date.now(), type, data }
]
})),
clearHistory: () => set({ messageHistory: [] }),
sendToIframe: (data) => {
const iframe = document.querySelector('#app') as HTMLIFrameElement
if (iframe?.contentWindow) {
const augmentedData = { ...data, source: "deskthing" }
iframe.contentWindow.postMessage(augmentedData, "*")
get().addToHistory('SENT_TO_IFRAME', augmentedData)
}
},
handleIframeMessage: (data, origin) => {
const { addToHistory } = get()
const { appManifest, setSongData } = useClientStore.getState()
addToHistory('RECEIVED_FROM_IFRAME', data)
if (data.app === "client") {
handleClientMessage(data)
} else {
handleAppMessage(data, appManifest)
}
}
}))
// Helper functions
const handleClientMessage = (data: ClientToDeviceData) => {
const { sendToIframe } = useMessageStore.getState()
const { songData, settings, apps, clientManifest } = useClientStore.getState()
switch (data.type) {
case "get":
switch (data.request) {
case "song":
ClientLogger.debug("Get request for music, Sending music", songData)
sendToIframe({ type: DEVICE_CLIENT.MUSIC, app: "client", payload: songData })
break
case "settings":
ClientLogger.debug("Get request for settings, Sending settings")
sendToIframe({ type: DEVICE_CLIENT.SETTINGS, app: "client", payload: settings })
break
case "apps":
ClientLogger.debug("Get request for apps, Sending apps", apps)
sendToIframe({ type: DEVICE_CLIENT.APPS, app: "client", payload: apps })
break
case "manifest":
ClientLogger.debug("Get request for manifest, Sending manifest")
sendToIframe({ type: DEVICE_CLIENT.MANIFEST, app: "client", payload: clientManifest })
break
}
break
case "log":
ClientLogger.clientLog(data.request as any, data.payload.message, ...(data.payload.data || []))
break
case "key":
case "action":
handleActionMessage(data)
break
}
}
const handleAppMessage = (data: ClientToDeviceData, appManifest: AppManifest | null) => {
ClientLogger.debug('Sending data to server', data)
const clientId = useClientStore.getState().clientId
const appId = data.app || appManifest?.id || "unknownId"
ClientService.sendToApp({
...data,
app: appId,
clientId: clientId
})
}
const handleActionMessage = (data: Extract<ClientToDeviceData, { type: 'action' | 'key' }>) => {
const { appManifest, clientId } = useClientStore.getState()
ClientLogger.debug('Handling action', data)
const appId = data.app || appManifest?.id || "unknownId"
ClientService.sendToApp({
...data,
app: appId,
clientId: clientId
})
}