Files
TamaASR/src/main/settings-window.ts
T
MeloriseandCodex 5a3aa9cfcb feat: 完成托盘设置页和悬浮球交互
实现隐藏启动、就绪状态托盘、登录提醒、后端切换、快捷键与自启动设置、九宫格和坐标微调,以及常驻悬浮球点击录音。

AI-assisted-by: Codex
AI-model: gpt-5.6-sol
AI-reasoning-effort: medium
Co-authored-by: Codex <codex@openai.com>
2026-08-23 02:34:38 +08:00

82 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { app, BrowserWindow, screen, shell } from 'electron';
import path from 'node:path';
import type { SettingsViewState } from '../shared/contracts';
import type { BackendManager } from './backend-manager';
import type { OverlayController } from './overlay-controller';
import type { SessionController } from './session-controller';
import type { SettingsStore } from './settings-store';
export class SettingsWindow {
window: BrowserWindow | null = null;
constructor(
private readonly settings: SettingsStore,
private readonly backends: BackendManager,
private readonly overlay: OverlayController,
private readonly sessions: SessionController,
private readonly repositoryUrl: string | null
) {}
async create(): Promise<void> {
this.window = new BrowserWindow({
width: 720,
height: 820,
minWidth: 640,
minHeight: 680,
show: false,
title: 'MeloASR 设置',
autoHideMenuBar: true,
icon: path.join(app.getAppPath(), 'dist', 'assets', 'logo.png'),
webPreferences: {
preload: path.join(__dirname, '..', 'preload', 'settings.js'),
nodeIntegration: false,
contextIsolation: true,
sandbox: true
}
});
this.window.on('close', (event) => {
if ((app as typeof app & { isQuitting?: boolean }).isQuitting) return;
event.preventDefault();
this.window?.hide();
});
await this.window.loadFile(path.join(__dirname, '..', 'renderer', 'settings.html'));
}
show(): void {
this.window?.show();
this.window?.focus();
this.publish();
}
publish(): void {
if (!this.window || this.window.isDestroyed()) return;
this.window.webContents.send('settings:state', this.state());
}
state(): SettingsViewState {
const current = this.settings.get();
const position = this.overlay.position(current.overlayPosition);
return {
backendId: current.backendId,
backends: this.backends.definitions().map(({ id, label }) => ({ id, label, status: this.backends.status(id) })),
sessionState: this.sessions.state,
shortcut: current.shortcut,
autoStart: current.autoStart,
overlayPersistent: current.overlayPersistent,
overlayPosition: position,
displays: screen.getAllDisplays().map((display, index) => ({
id: String(display.id),
label: `屏幕 ${index + 1}(${display.workArea.width} × ${display.workArea.height})`,
workArea: display.workArea
})),
version: app.getVersion(),
repositoryUrl: this.repositoryUrl
};
}
async openRepository(): Promise<void> {
if (!this.repositoryUrl) throw new Error('尚未配置项目仓库地址');
await shell.openExternal(this.repositoryUrl);
}
}