Add global field to filter tool tabs

This commit is contained in:
Chris Wanstrath 2026-03-01 09:35:05 -08:00
parent 2046af1407
commit c7f8f09ba9
6 changed files with 12 additions and 9 deletions

View File

@ -45,8 +45,8 @@ const OpenEmojiPicker = define('OpenEmojiPicker', {
}) })
export function AppDetail({ app, render }: { app: App, render: () => void }) { export function AppDetail({ app, render }: { app: App, render: () => void }) {
// Find all tools // Find global tools (shown as tabs on every app)
const tools = apps.filter(a => a.tool) const tools = apps.filter(a => a.tool && a.global)
const selectedTab = getSelectedTab(app.name) const selectedTab = getSelectedTab(app.name)
return ( return (

View File

@ -16,8 +16,8 @@ export function Nav({ app, render }: { app: App; render: () => void }) {
navigate(tab === 'overview' ? `/app/${app.name}` : `/app/${app.name}/${tab}`) navigate(tab === 'overview' ? `/app/${app.name}` : `/app/${app.name}/${tab}`)
} }
// Find all tools // Find global tools (shown as tabs on every app)
const tools = apps.filter(a => a.tool) const tools = apps.filter(a => a.tool && a.global)
const titlecase = (s: string) => s.split(' ').map(part => part[0]?.toUpperCase() + part.slice(1)) const titlecase = (s: string) => s.split(' ').map(part => part[0]?.toUpperCase() + part.slice(1))
return ( return (

View File

@ -10,7 +10,7 @@ const render = () => {
renderApp(<Dashboard render={render} />, document.getElementById('app')!) renderApp(<Dashboard render={render} />, document.getElementById('app')!)
// Update tool iframes after DOM settles // Update tool iframes after DOM settles
requestAnimationFrame(() => { requestAnimationFrame(() => {
const tools = apps.filter(a => a.tool) const tools = apps.filter(a => a.tool && a.global)
updateToolIframes(getSelectedTab(selectedApp), tools, selectedApp) updateToolIframes(getSelectedTab(selectedApp), tools, selectedApp)
}) })
} }

View File

@ -26,9 +26,9 @@ function convert(app: BackendApp): SharedApp {
router.sse('/stream', (send) => { router.sse('/stream', (send) => {
const broadcast = () => { const broadcast = () => {
const apps: SharedApp[] = allApps().map(({ const apps: SharedApp[] = allApps().map(({
name, state, icon, error, port, started, logs, tool, tunnelEnabled, tunnelUrl name, state, icon, error, port, started, logs, tool, global: global_, tunnelEnabled, tunnelUrl
}) => ({ }) => ({
name, state, icon, error, port, started, logs, tool, tunnelEnabled, tunnelUrl, name, state, icon, error, port, started, logs, tool, global: global_, tunnelEnabled, tunnelUrl,
})) }))
send(apps) send(apps)
} }

View File

@ -159,7 +159,8 @@ export function registerApp(dir: string) {
const state: AppState = error ? 'invalid' : 'stopped' const state: AppState = error ? 'invalid' : 'stopped'
const icon = pkg.toes?.icon ?? DEFAULT_EMOJI const icon = pkg.toes?.icon ?? DEFAULT_EMOJI
const tool = pkg.toes?.tool const tool = pkg.toes?.tool
_apps.set(dir, { name: dir, state, icon, error, tool }) const global_ = pkg.toes?.global
_apps.set(dir, { name: dir, state, icon, error, tool, global: global_ })
update() update()
emit({ type: 'app:create', app: dir }) emit({ type: 'app:create', app: dir })
if (!error) { if (!error) {
@ -379,7 +380,8 @@ function discoverApps() {
const state: AppState = error ? 'invalid' : 'stopped' const state: AppState = error ? 'invalid' : 'stopped'
const icon = pkg.toes?.icon ?? DEFAULT_EMOJI const icon = pkg.toes?.icon ?? DEFAULT_EMOJI
const tool = pkg.toes?.tool const tool = pkg.toes?.tool
_apps.set(dir, { name: dir, state, icon, error, tool }) const global_ = pkg.toes?.global
_apps.set(dir, { name: dir, state, icon, error, tool, global: global_ })
} }
update() update()
} }

View File

@ -28,6 +28,7 @@ export type App = {
started?: number started?: number
logs?: LogLine[] logs?: LogLine[]
tool?: boolean | string tool?: boolean | string
global?: boolean
tunnelEnabled?: boolean tunnelEnabled?: boolean
tunnelUrl?: string tunnelUrl?: string
} }