Files
Acbox 46365726b9 feat: introduce electron desktop app (#405)
* refactor: use Electron instead of Tauri

* feat: two level windows and self-managed vite project

* feat(desktop): macOS hidden-inset chrome and floating chat title

Apply hiddenInset titleBarStyle on darwin so the system titlebar is hidden
but native traffic lights remain. Reusable web sidebars inject a new
DesktopShellKey to reserve a 36px TopBar that holds the traffic-light
inset (drag region + right border) without colliding with the bot list,
and the sidebar stays pinned open in the Electron shell so window resize
doesn't fight the layout.

Overlay a centered "Title - BotName" header above the chat content with a
bottom shadow gradient that obscures scrolling messages, and reserve top
padding so the first message stays visible when content fits the viewport.
Route the sidebar + action by path (/settings/bots) so the chat router's
/settings/* interception forwards it to the settings window cleanly while
remaining a normal navigation in web.

* docs(desktop): add AGENTS.md for Electron shell

Document the multi-window architecture, web reuse strategy, type-stubbing
trick, macOS chrome, IPC surface, routing, icons, and packaging — captures
the non-obvious bits that bit us during the Tauri → Electron refactor so
future agents don't relearn them.
2026-04-25 12:16:23 +08:00

2.1 KiB
Raw Permalink Blame History

@memohai/desktop

Memoh desktop application built with electron-vite.

The renderer owns its own src/renderer/src/main.ts — it imports the reusable building blocks from @memohai/web (App.vue, router, i18n, api-client, style.css) but assembles the Vue app locally. Desktop-only customization (extra Pinia plugins, Electron-specific stores / providers, alternate routers, etc.) belongs in this main.ts, not in @memohai/web.

How the reuse is wired

  • @memohai/web/package.json exposes App.vue, router, i18n, api-client, and style.css through its exports field.
  • Vite (via electron.vite.config.ts) resolves those subpaths to the real files in apps/web/src/ at bundle time.
  • vue-tsc is pointed at local type stubs in src/renderer/types/web-stubs.d.ts via tsconfig paths, so desktop's typecheck does not descend into apps/web/src/ or packages/ui/src/ (those have their own CI).

Development

# from repo root
pnpm --filter @memohai/desktop dev
# or via mise
mise run desktop:dev

MEMOH_WEB_PROXY_TARGET overrides the backend that the renderer's /api proxy points at (defaults to whatever config.toml / conf/app.docker.toml declares).

Build

pnpm --filter @memohai/desktop build           # full platform installer
pnpm --filter @memohai/desktop build:dir       # unpacked app dir (CI smoke test)

Output goes to apps/desktop/dist/.

Icons

All app icons are generated from apps/web/public/logo.svg (the brand mark) by scripts/build-icons.mjs. Re-run after the logo changes:

pnpm --filter @memohai/desktop icons

Outputs:

File Purpose
build/icon.icns macOS bundle icon (16…1024 + @2x) — packaged into .app/Contents/Resources/
build/icon.ico Windows installer / .exe icon (16/24/32/48/64/128/256)
build/icon.png Linux .deb/.rpm/.AppImage icon (1024×1024)
resources/icon.png Runtime BrowserWindow.icon + macOS dev app.dock.setIcon (512×512); bundled via asarUnpack

build/icon.icns requires macOS (iconutil); the script skips it on other platforms.