toes/src/client/index.tsx
2026-03-04 19:03:29 -08:00

67 lines
2.0 KiB
TypeScript

import { render as renderApp } from 'hono/jsx/dom'
import { Dashboard } from './components'
import { initRouter, navigate } from './router'
import { apps, dashboardTab, getSelectedTab, selectedApp, setApps, setIsNarrow } from './state'
import { initToolIframes, updateToolIframes } from './tool-iframes'
import { initUpdate } from './update'
const render = () => {
renderApp(<Dashboard render={render} />, document.getElementById('app')!)
// Update tool iframes after DOM settles
requestAnimationFrame(() => {
if (selectedApp) {
const tools = apps.filter(a => a.tool && a.apps !== false)
updateToolIframes(getSelectedTab(selectedApp), tools, selectedApp)
} else {
const tools = apps.filter(a => a.tool && a.dashboard)
updateToolIframes(dashboardTab, tools, null)
}
})
}
// Initialize render functions
initUpdate(render)
initToolIframes()
// Set theme based on localStorage preference or system preference
export const setTheme = () => {
const stored = localStorage.getItem('theme')
if (stored === 'light' || stored === 'dark') {
document.documentElement.setAttribute('data-theme', stored)
return
}
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
document.documentElement.setAttribute('data-theme', prefersDark ? 'dark' : 'light')
}
// Listen for system theme changes (only applies when using system theme)
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
setTheme()
render()
})
// Set initial theme
setTheme()
// Listen for narrow screen changes
const narrowQuery = window.matchMedia('(max-width: 768px)')
narrowQuery.addEventListener('change', e => {
setIsNarrow(e.matches)
render()
})
// Initialize router (sets initial state from URL and renders)
initRouter(render)
// SSE connection
const events = new EventSource('/api/apps/stream')
events.onmessage = e => {
setApps(JSON.parse(e.data))
if (selectedApp && !apps.some(a => a.name === selectedApp)) {
navigate('/')
}
render()
}