diff --git a/src/client/index.tsx b/src/client/index.tsx index 41e8a67..206ce7b 100644 --- a/src/client/index.tsx +++ b/src/client/index.tsx @@ -340,10 +340,14 @@ const toggleSidebar = () => { const OpenEmojiPicker = define('OpenEmojiPicker', { cursor: 'pointer', - render({ props, parts: { Root } }) { + render({ props: { app, children }, parts: { Root } }) { return openEmojiPicker((emoji) => { - console.log('Selected:', emoji) - })}>{props.children} + if (!app) return + + fetch(`/api/apps/${app.name}/icon?icon=${emoji}`, { method: 'POST' }) + app.icon = emoji + render() + })}>{children} } }) @@ -351,7 +355,7 @@ const AppDetail = ({ app }: { app: App }) => ( <> - {app.icon ?? } + {app.icon ?? }   {app.name} diff --git a/src/server/apps.ts b/src/server/apps.ts index f47585d..9c8e4ef 100644 --- a/src/server/apps.ts +++ b/src/server/apps.ts @@ -1,5 +1,5 @@ import type { Subprocess } from 'bun' -import { existsSync, readdirSync, readFileSync, watch } from 'fs' +import { existsSync, readdirSync, readFileSync, writeFileSync, watch } from 'fs' import { join } from 'path' import type { App as SharedApp, AppState, LogLine } from '../shared/types' @@ -91,6 +91,20 @@ const loadApp = (dir: string): LoadResult => { } } +const saveApp = (dir: string, pkg: any) => { + const path = join(APPS_DIR, dir, 'package.json') + writeFileSync(path, JSON.stringify(pkg, null, 2) + '\n') +} + +export const updateAppIcon = (dir: string, icon: string) => { + const { pkg, error } = loadApp(dir) + if (error) throw new Error(error) + + pkg.toes ??= {} + pkg.toes.icon = icon + saveApp(dir, pkg) +} + const isApp = (dir: string): boolean => !loadApp(dir).error diff --git a/src/server/index.tsx b/src/server/index.tsx index 032eb32..3e2ff4f 100644 --- a/src/server/index.tsx +++ b/src/server/index.tsx @@ -1,5 +1,5 @@ import { Hype } from 'hype' -import { allApps, initApps, onChange, startApp, stopApp } from './apps' +import { allApps, initApps, onChange, startApp, stopApp, updateAppIcon } from './apps' import type { App as SharedApp } from '../shared/types' const app = new Hype({ layout: false }) @@ -75,4 +75,17 @@ app.post('/api/apps/:app/stop', c => { return c.json({ ok: true }) }) +app.post('/api/apps/:app/icon', c => { + const appName = c.req.param('app') + const icon = c.req.query('icon') ?? '' + if (!icon) return c.json({ error: 'No icon query param provided' }) + + try { + updateAppIcon(appName, icon) + return c.json({ ok: true }) + } catch (error) { + return c.json({ error }) + } +}) + export default app.defaults