mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-27 07:16:19 +09:00
46365726b9
* 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.
100 lines
3.2 KiB
TypeScript
100 lines
3.2 KiB
TypeScript
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
|
|
import vue from '@vitejs/plugin-vue'
|
|
import tailwindcss from '@tailwindcss/vite'
|
|
import { createRequire } from 'node:module'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { resolve } from 'node:path'
|
|
|
|
const require = createRequire(import.meta.url)
|
|
|
|
const defaultPort = 8082
|
|
const defaultHost = '127.0.0.1'
|
|
const defaultApiBaseUrl = process.env.VITE_API_URL ?? 'http://localhost:8080'
|
|
|
|
function resolveProxyTarget(command: 'build' | 'serve'): { port: number; host: string; baseUrl: string } {
|
|
const configuredProxyTarget = process.env.MEMOH_WEB_PROXY_TARGET?.trim()
|
|
const configuredPath = process.env.MEMOH_CONFIG_PATH?.trim() || process.env.CONFIG_PATH?.trim()
|
|
const configPath = configuredPath && configuredPath.length > 0 ? configuredPath : '../../config.toml'
|
|
|
|
let port = defaultPort
|
|
let host = defaultHost
|
|
let baseUrl = configuredProxyTarget || defaultApiBaseUrl
|
|
|
|
if (command !== 'build') {
|
|
try {
|
|
const { loadConfig, getBaseUrl } = require('@memohai/config') as {
|
|
loadConfig: (path: string) => { web?: { port?: number; host?: string } }
|
|
getBaseUrl: (config: unknown) => string
|
|
}
|
|
let config
|
|
try {
|
|
config = loadConfig(configPath)
|
|
} catch {
|
|
config = loadConfig('../../conf/app.docker.toml')
|
|
}
|
|
port = config.web?.port ?? defaultPort
|
|
host = config.web?.host ?? defaultHost
|
|
baseUrl = configuredProxyTarget || getBaseUrl(config)
|
|
} catch {
|
|
// fall back to env/default values when config.toml is unavailable.
|
|
}
|
|
}
|
|
|
|
return { port, host, baseUrl }
|
|
}
|
|
|
|
export default defineConfig(({ command }) => {
|
|
const { port, host, baseUrl } = resolveProxyTarget(command)
|
|
|
|
return {
|
|
main: {
|
|
plugins: [externalizeDepsPlugin()],
|
|
},
|
|
preload: {
|
|
plugins: [externalizeDepsPlugin()],
|
|
},
|
|
renderer: {
|
|
root: resolve(__dirname, 'src/renderer'),
|
|
// Reuse apps/web/public so absolute-path assets (e.g. /logo.svg) resolve
|
|
// when web modules are imported directly from the desktop renderer.
|
|
publicDir: resolve(__dirname, '../web/public'),
|
|
plugins: [vue(), tailwindcss()],
|
|
resolve: {
|
|
alias: {
|
|
'@renderer': fileURLToPath(new URL('./src/renderer/src', import.meta.url)),
|
|
// match apps/web/vite.config.ts aliases so imported web modules resolve correctly.
|
|
'@': fileURLToPath(new URL('../web/src', import.meta.url)),
|
|
'#': fileURLToPath(new URL('../../packages/ui/src', import.meta.url)),
|
|
},
|
|
},
|
|
optimizeDeps: {
|
|
entries: [
|
|
'src/renderer/src/main.ts',
|
|
'../web/src/main.ts',
|
|
'../web/src/pages/**/*.vue',
|
|
],
|
|
},
|
|
build: {
|
|
rollupOptions: {
|
|
input: {
|
|
index: resolve(__dirname, 'src/renderer/index.html'),
|
|
settings: resolve(__dirname, 'src/renderer/settings.html'),
|
|
},
|
|
},
|
|
},
|
|
server: {
|
|
port,
|
|
host,
|
|
proxy: {
|
|
'/api': {
|
|
target: baseUrl,
|
|
changeOrigin: true,
|
|
rewrite: (path: string) => path.replace(/^\/api/, ''),
|
|
ws: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
})
|