From 8e499a880ae110f13060894f1b5659976ef12437 Mon Sep 17 00:00:00 2001 From: Makito Date: Sat, 29 Nov 2025 00:17:32 +0900 Subject: [PATCH] feat(stage-tamagotchi): background window for beat-sync --- apps/stage-tamagotchi/electron.vite.config.ts | 16 ++++++++++ apps/stage-tamagotchi/src/main/index.ts | 22 ++++++++++--- .../src/main/libs/electron/location.ts | 15 +++++++-- .../src/main/windows/beat-sync/index.ts | 18 +++++++++++ .../stage-tamagotchi/src/preload/beat-sync.ts | 2 ++ .../src/renderer/beat-sync.html | 31 +++++++++++++++++++ 6 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 apps/stage-tamagotchi/src/main/windows/beat-sync/index.ts create mode 100644 apps/stage-tamagotchi/src/preload/beat-sync.ts create mode 100644 apps/stage-tamagotchi/src/renderer/beat-sync.html diff --git a/apps/stage-tamagotchi/electron.vite.config.ts b/apps/stage-tamagotchi/electron.vite.config.ts index 6218870fd..e3294765a 100644 --- a/apps/stage-tamagotchi/electron.vite.config.ts +++ b/apps/stage-tamagotchi/electron.vite.config.ts @@ -23,12 +23,28 @@ export default defineConfig({ plugins: [externalizeDepsPlugin()], }, preload: { + build: { + lib: { + entry: { + 'index': resolve(join(import.meta.dirname, 'src', 'preload', 'index.ts')), + 'beat-sync': resolve(join(import.meta.dirname, 'src', 'preload', 'beat-sync.ts')), + }, + }, + }, plugins: [externalizeDepsPlugin()], }, renderer: { // Thanks to [@Maqsyo](https://github.com/Maqsyo) // https://github.com/alex8088/electron-vite/issues/99#issuecomment-1862671727 base: './', + build: { + rolldownOptions: { + input: { + 'main': resolve(join(import.meta.dirname, 'src', 'renderer', 'index.html')), + 'beat-sync': resolve(join(import.meta.dirname, 'src', 'renderer', 'beat-sync.html')), + }, + }, + }, optimizeDeps: { exclude: [ // Internal Packages diff --git a/apps/stage-tamagotchi/src/main/index.ts b/apps/stage-tamagotchi/src/main/index.ts index 516ca919d..f299f748a 100644 --- a/apps/stage-tamagotchi/src/main/index.ts +++ b/apps/stage-tamagotchi/src/main/index.ts @@ -4,7 +4,7 @@ import type { WidgetsWindowManager } from './windows/widgets' import { env, platform } from 'node:process' -import { electronApp, optimizer } from '@electron-toolkit/utils' +import { electronApp, is, optimizer } from '@electron-toolkit/utils' import { Format, LogLevel, setGlobalFormat, setGlobalLogLevel, useLogg } from '@guiiai/logg' import { app, ipcMain, Menu, nativeImage, Tray } from 'electron' import { noop, once } from 'es-toolkit' @@ -18,6 +18,7 @@ import { openDebugger, setupDebugger } from './app/debugger' import { emitAppBeforeQuit, emitAppReady, emitAppWindowAllClosed, onAppBeforeQuit } from './libs/bootkit/lifecycle' import { setElectronMainDirname } from './libs/electron/location' import { setupChannelServer } from './services/airi/channel-server' +import { setupBeatSyncBackgroundWindow } from './windows/beat-sync' import { setupCaptionWindowManager } from './windows/caption' import { setupChatWindowReusableFunc } from './windows/chat' import { setupInlayWindow } from './windows/inlay' @@ -73,6 +74,7 @@ function setupTray(params: { settingsWindow: () => Promise captionWindow: ReturnType widgetsWindow: WidgetsWindowManager + beatSyncBackgroundWindow: BrowserWindow }): void { once(() => { const trayImage = nativeImage.createFromPath(isMacOS ? macOSTrayIcon : icon).resize({ width: 16 }) @@ -97,6 +99,13 @@ function setupTray(params: { ]), }, { type: 'separator' }, + ...is.dev || env.MAIN_APP_DEBUG || env.APP_DEBUG + ? [ + { type: 'header', label: 'DevTools' }, + { label: 'Troubleshoot BeatSync...', click: () => params.beatSyncBackgroundWindow.webContents.openDevTools() }, + { type: 'separator' }, + ] as const // :( + : [], { label: 'Quit', click: () => app.quit() }, ]) @@ -118,12 +127,17 @@ app.whenReady().then(async () => { const widgetsManager = injeca.provide('windows:widgets', { build: () => setupWidgetsWindowManager() }) const noticeWindow = injeca.provide('windows:notice', { build: () => setupNoticeWindowManager() }) + // This is a background window + const beatSyncBackgroundWindow = injeca.provide('windows:beat-sync', { + build: () => setupBeatSyncBackgroundWindow(), + }) + const settingsWindow = injeca.provide('windows:settings', { - dependsOn: { widgetsManager }, + dependsOn: { widgetsManager, beatSyncBackgroundWindow }, build: ({ dependsOn }) => setupSettingsWindowReusableFunc(dependsOn), }) const mainWindow = injeca.provide('windows:main', { - dependsOn: { settingsWindow, chatWindow, widgetsManager, noticeWindow }, + dependsOn: { settingsWindow, chatWindow, widgetsManager, noticeWindow, beatSyncBackgroundWindow }, build: async ({ dependsOn }) => setupMainWindow(dependsOn), }) const captionWindow = injeca.provide('windows:caption', { @@ -131,7 +145,7 @@ app.whenReady().then(async () => { build: async ({ dependsOn }) => setupCaptionWindowManager(dependsOn), }) const tray = injeca.provide('app:tray', { - dependsOn: { mainWindow, settingsWindow, captionWindow, widgetsWindow: widgetsManager }, + dependsOn: { mainWindow, settingsWindow, captionWindow, widgetsWindow: widgetsManager, beatSyncBackgroundWindow }, build: async ({ dependsOn }) => setupTray(dependsOn), }) injeca.invoke({ diff --git a/apps/stage-tamagotchi/src/main/libs/electron/location.ts b/apps/stage-tamagotchi/src/main/libs/electron/location.ts index 85d965b08..444208c5b 100644 --- a/apps/stage-tamagotchi/src/main/libs/electron/location.ts +++ b/apps/stage-tamagotchi/src/main/libs/electron/location.ts @@ -15,12 +15,21 @@ export function getElectronMainDirname() { return electronMainDirname } -export function baseUrl(parentOfIndexHtml: string) { +export function baseUrl(parentOfIndexHtml: string, filename?: string) { if (is.dev && env.ELECTRON_RENDERER_URL) { - return { url: env.ELECTRON_RENDERER_URL } + if (!filename) { + return { url: env.ELECTRON_RENDERER_URL } + } + + const url = new URL(env.ELECTRON_RENDERER_URL) + const paths = url.pathname.split('/') + paths.pop() + paths.push(filename) + url.pathname = paths.join('/') + return { url: url.toString() } } else { - return { file: join(parentOfIndexHtml, 'index.html') } + return { file: join(parentOfIndexHtml, filename ?? 'index.html') } } } diff --git a/apps/stage-tamagotchi/src/main/windows/beat-sync/index.ts b/apps/stage-tamagotchi/src/main/windows/beat-sync/index.ts new file mode 100644 index 000000000..923a833a9 --- /dev/null +++ b/apps/stage-tamagotchi/src/main/windows/beat-sync/index.ts @@ -0,0 +1,18 @@ +import { dirname, join, resolve } from 'node:path' +import { fileURLToPath } from 'node:url' + +import { BrowserWindow } from 'electron' + +import { baseUrl, getElectronMainDirname, load } from '../../libs/electron/location' + +export async function setupBeatSyncBackgroundWindow() { + const window = new BrowserWindow({ + show: false, + webPreferences: { + preload: join(dirname(fileURLToPath(import.meta.url)), '../preload/beat-sync.mjs'), + sandbox: false, + }, + }) + await load(window, baseUrl(resolve(getElectronMainDirname(), '..', 'renderer'), 'beat-sync.html')) + return window +} diff --git a/apps/stage-tamagotchi/src/preload/beat-sync.ts b/apps/stage-tamagotchi/src/preload/beat-sync.ts new file mode 100644 index 000000000..56306163d --- /dev/null +++ b/apps/stage-tamagotchi/src/preload/beat-sync.ts @@ -0,0 +1,2 @@ +// eslint-disable-next-line no-console +console.log('beat-sync preload') diff --git a/apps/stage-tamagotchi/src/renderer/beat-sync.html b/apps/stage-tamagotchi/src/renderer/beat-sync.html new file mode 100644 index 000000000..ba0964b21 --- /dev/null +++ b/apps/stage-tamagotchi/src/renderer/beat-sync.html @@ -0,0 +1,31 @@ + + + + + + + BeatSync - AIRI + + + + + +
Open the DevTools to troubleshoot BeatSync
+ +