mirror of
https://github.com/Melorise/TamaASR.git
synced 2026-11-07 14:39:32 +00:00
refactor: 移除悬浮球交互模式
AI-assisted-by: Codex AI-model: gpt-5.6-sol AI-reasoning-effort: medium Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
### 变更
|
### 变更
|
||||||
|
|
||||||
- 切换后端时销毁非当前后端的网页窗口,保留登录会话但不再保活其 renderer。
|
- 切换后端时销毁非当前后端的网页窗口,保留登录会话但不再保活其 renderer。
|
||||||
|
- 移除悬浮球点击录音和常驻显示功能,悬浮球仅用于显示语音会话状态。
|
||||||
|
|
||||||
## [0.1.10] - 2026-08-23
|
## [0.1.10] - 2026-08-23
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ tar -C %{buildroot} -xzf %{SOURCE0}
|
|||||||
%changelog
|
%changelog
|
||||||
* Sun Aug 23 2026 MeloASR contributors - 0.1.11-1
|
* Sun Aug 23 2026 MeloASR contributors - 0.1.11-1
|
||||||
- Release only the selected speech backend renderer.
|
- Release only the selected speech backend renderer.
|
||||||
|
- Keep the overlay as a non-interactive session status indicator.
|
||||||
|
|
||||||
* Sun Aug 23 2026 MeloASR contributors - 0.1.10-1
|
* Sun Aug 23 2026 MeloASR contributors - 0.1.10-1
|
||||||
- Restore the Nix npm configuration hook before building the application.
|
- Restore the Nix npm configuration hook before building the application.
|
||||||
|
|||||||
@@ -88,9 +88,6 @@ function registerIpc(services: Services): void {
|
|||||||
const { settings, autoStart, bridge, backends, overlay, sessions, settingsWindow } = services;
|
const { settings, autoStart, bridge, backends, overlay, sessions, settingsWindow } = services;
|
||||||
const settingsSender = (senderId: number): boolean =>
|
const settingsSender = (senderId: number): boolean =>
|
||||||
Boolean(settingsWindow.window && !settingsWindow.window.isDestroyed() && settingsWindow.window.webContents.id === senderId);
|
Boolean(settingsWindow.window && !settingsWindow.window.isDestroyed() && settingsWindow.window.webContents.id === senderId);
|
||||||
const overlaySender = (senderId: number): boolean =>
|
|
||||||
Boolean(overlay.window && !overlay.window.isDestroyed() && overlay.window.webContents.id === senderId);
|
|
||||||
|
|
||||||
ipcMain.handle('settings:get-state', (event) => {
|
ipcMain.handle('settings:get-state', (event) => {
|
||||||
if (!settingsSender(event.sender.id)) throw new Error('拒绝未授权的设置请求');
|
if (!settingsSender(event.sender.id)) throw new Error('拒绝未授权的设置请求');
|
||||||
return settingsWindow.state();
|
return settingsWindow.state();
|
||||||
@@ -115,10 +112,6 @@ function registerIpc(services: Services): void {
|
|||||||
overlay.applyPreset(preset, displayId);
|
overlay.applyPreset(preset, displayId);
|
||||||
return settingsWindow.state();
|
return settingsWindow.state();
|
||||||
});
|
});
|
||||||
ipcMain.handle('settings:preview-overlay', (event) => {
|
|
||||||
if (!settingsSender(event.sender.id)) throw new Error('拒绝未授权的预览请求');
|
|
||||||
overlay.preview();
|
|
||||||
});
|
|
||||||
ipcMain.handle('settings:begin-positioning', (event) => {
|
ipcMain.handle('settings:begin-positioning', (event) => {
|
||||||
if (!settingsSender(event.sender.id)) throw new Error('拒绝未授权的位置调整请求');
|
if (!settingsSender(event.sender.id)) throw new Error('拒绝未授权的位置调整请求');
|
||||||
overlay.beginPositioning();
|
overlay.beginPositioning();
|
||||||
@@ -141,12 +134,6 @@ function registerIpc(services: Services): void {
|
|||||||
settings.update({ autoStart: enabled });
|
settings.update({ autoStart: enabled });
|
||||||
return settingsWindow.state();
|
return settingsWindow.state();
|
||||||
});
|
});
|
||||||
ipcMain.handle('settings:set-overlay-persistent', (event, enabled: unknown) => {
|
|
||||||
if (!settingsSender(event.sender.id) || typeof enabled !== 'boolean') throw new Error('无效的悬浮球设置');
|
|
||||||
settings.update({ overlayPersistent: enabled });
|
|
||||||
overlay.reconcilePersistent();
|
|
||||||
return settingsWindow.state();
|
|
||||||
});
|
|
||||||
ipcMain.handle('settings:set-diagnostic-logging', (event, enabled: unknown) => {
|
ipcMain.handle('settings:set-diagnostic-logging', (event, enabled: unknown) => {
|
||||||
if (!settingsSender(event.sender.id) || typeof enabled !== 'boolean') throw new Error('无效的日志设置');
|
if (!settingsSender(event.sender.id) || typeof enabled !== 'boolean') throw new Error('无效的日志设置');
|
||||||
settings.update({ diagnosticLogging: enabled });
|
settings.update({ diagnosticLogging: enabled });
|
||||||
@@ -157,9 +144,6 @@ function registerIpc(services: Services): void {
|
|||||||
if (!settingsSender(event.sender.id)) throw new Error('拒绝未授权的外部链接请求');
|
if (!settingsSender(event.sender.id)) throw new Error('拒绝未授权的外部链接请求');
|
||||||
await settingsWindow.openRepository();
|
await settingsWindow.openRepository();
|
||||||
});
|
});
|
||||||
ipcMain.on('overlay:toggle-recording', (event) => {
|
|
||||||
if (overlaySender(event.sender.id)) sessions.requestStartFromOverlay();
|
|
||||||
});
|
|
||||||
ipcMain.on('backend-status', (event, payload: BackendStatusPayload) => backends.handleStatus(event, payload));
|
ipcMain.on('backend-status', (event, payload: BackendStatusPayload) => backends.handleStatus(event, payload));
|
||||||
ipcMain.on('backend-transcript', (event, payload: { backend?: string; text?: string }) => {
|
ipcMain.on('backend-transcript', (event, payload: { backend?: string; text?: string }) => {
|
||||||
if (typeof payload?.backend === 'string' && typeof payload.text === 'string' && backends.senderIsActive(event, payload.backend)) {
|
if (typeof payload?.backend === 'string' && typeof payload.text === 'string' && backends.senderIsActive(event, payload.backend)) {
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ export class OverlayController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.window.setAlwaysOnTop(true, 'floating');
|
this.window.setAlwaysOnTop(true, 'floating');
|
||||||
|
this.window.setIgnoreMouseEvents(true);
|
||||||
await this.window.loadFile(path.join(__dirname, '..', 'renderer', 'overlay.html'));
|
await this.window.loadFile(path.join(__dirname, '..', 'renderer', 'overlay.html'));
|
||||||
this.position();
|
this.position();
|
||||||
this.reconcilePersistent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
position(point = this.settings.get().overlayPosition): Point {
|
position(point = this.settings.get().overlayPosition): Point {
|
||||||
@@ -68,7 +68,6 @@ export class OverlayController {
|
|||||||
if (!this.window || this.window.isDestroyed()) return;
|
if (!this.window || this.window.isDestroyed()) return;
|
||||||
this.positioning = true;
|
this.positioning = true;
|
||||||
this.clearHideTimer();
|
this.clearHideTimer();
|
||||||
this.window.setIgnoreMouseEvents(true);
|
|
||||||
this.window.webContents.send('overlay-state', { state: 'idle' });
|
this.window.webContents.send('overlay-state', { state: 'idle' });
|
||||||
this.window.showInactive();
|
this.window.showInactive();
|
||||||
}
|
}
|
||||||
@@ -77,8 +76,7 @@ export class OverlayController {
|
|||||||
if (!this.positioning) return;
|
if (!this.positioning) return;
|
||||||
this.positioning = false;
|
this.positioning = false;
|
||||||
if (!this.window || this.window.isDestroyed()) return;
|
if (!this.window || this.window.isDestroyed()) return;
|
||||||
this.window.setIgnoreMouseEvents(false);
|
this.window.hide();
|
||||||
this.reconcilePersistent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
showState(state: SessionState | 'done' | 'error'): void {
|
showState(state: SessionState | 'done' | 'error'): void {
|
||||||
@@ -90,26 +88,9 @@ export class OverlayController {
|
|||||||
|
|
||||||
hideLater(delay = 900): void {
|
hideLater(delay = 900): void {
|
||||||
this.clearHideTimer();
|
this.clearHideTimer();
|
||||||
if (this.settings.get().overlayPersistent) return;
|
|
||||||
this.hideTimer = setTimeout(() => this.window?.hide(), delay);
|
this.hideTimer = setTimeout(() => this.window?.hide(), delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
preview(): void {
|
|
||||||
this.position();
|
|
||||||
this.showState('recording');
|
|
||||||
this.hideLater(1800);
|
|
||||||
}
|
|
||||||
|
|
||||||
reconcilePersistent(): void {
|
|
||||||
if (!this.window || this.window.isDestroyed()) return;
|
|
||||||
if (this.positioning) return;
|
|
||||||
if (this.settings.get().overlayPersistent) {
|
|
||||||
this.showState('idle');
|
|
||||||
} else {
|
|
||||||
this.window.hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private clearHideTimer(): void {
|
private clearHideTimer(): void {
|
||||||
if (this.hideTimer) clearTimeout(this.hideTimer);
|
if (this.hideTimer) clearTimeout(this.hideTimer);
|
||||||
this.hideTimer = null;
|
this.hideTimer = null;
|
||||||
|
|||||||
@@ -54,14 +54,6 @@ export class SessionController extends EventEmitter {
|
|||||||
if (this.stopRequestedDuringStart) this.stop();
|
if (this.stopRequestedDuringStart) this.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
requestStartFromOverlay(): void {
|
|
||||||
if (this.state === 'recording' || this.state === 'starting') {
|
|
||||||
this.stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this.bridge.ready || !this.bridge.requestInputStart()) this.reject('Fcitx5 插件尚未连接');
|
|
||||||
}
|
|
||||||
|
|
||||||
stop(): void {
|
stop(): void {
|
||||||
if (this.state === 'starting') {
|
if (this.state === 'starting') {
|
||||||
this.stopRequestedDuringStart = true;
|
this.stopRequestedDuringStart = true;
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ const DEFAULT_SETTINGS: AppSettings = {
|
|||||||
backendId: 'qianwen',
|
backendId: 'qianwen',
|
||||||
shortcut: 'Control+Shift+space',
|
shortcut: 'Control+Shift+space',
|
||||||
autoStart: true,
|
autoStart: true,
|
||||||
overlayPersistent: false,
|
|
||||||
diagnosticLogging: false,
|
diagnosticLogging: false,
|
||||||
overlayPosition: null,
|
overlayPosition: null,
|
||||||
loginNoticeShown: {}
|
loginNoticeShown: {}
|
||||||
@@ -22,10 +21,12 @@ export class SettingsStore extends EventEmitter {
|
|||||||
try {
|
try {
|
||||||
const parsed = JSON.parse(fs.readFileSync(this.filePath, 'utf8')) as Partial<AppSettings> & {
|
const parsed = JSON.parse(fs.readFileSync(this.filePath, 'utf8')) as Partial<AppSettings> & {
|
||||||
backend?: string;
|
backend?: string;
|
||||||
|
overlayPersistent?: unknown;
|
||||||
};
|
};
|
||||||
|
const { overlayPersistent: _obsoleteOverlayPersistent, ...saved } = parsed;
|
||||||
this.value = {
|
this.value = {
|
||||||
...DEFAULT_SETTINGS,
|
...DEFAULT_SETTINGS,
|
||||||
...parsed,
|
...saved,
|
||||||
backendId: parsed.backendId ?? parsed.backend ?? DEFAULT_SETTINGS.backendId,
|
backendId: parsed.backendId ?? parsed.backend ?? DEFAULT_SETTINGS.backendId,
|
||||||
overlayPosition: this.isPoint(parsed.overlayPosition) ? {
|
overlayPosition: this.isPoint(parsed.overlayPosition) ? {
|
||||||
x: Math.round(parsed.overlayPosition.x), y: Math.round(parsed.overlayPosition.y)
|
x: Math.round(parsed.overlayPosition.x), y: Math.round(parsed.overlayPosition.y)
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ export class SettingsWindow {
|
|||||||
sessionState: this.sessions.state,
|
sessionState: this.sessions.state,
|
||||||
shortcut: current.shortcut,
|
shortcut: current.shortcut,
|
||||||
autoStart: current.autoStart,
|
autoStart: current.autoStart,
|
||||||
overlayPersistent: current.overlayPersistent,
|
|
||||||
diagnosticLogging: current.diagnosticLogging,
|
diagnosticLogging: current.diagnosticLogging,
|
||||||
overlayPosition: position,
|
overlayPosition: position,
|
||||||
displays: screen.getAllDisplays().map((display, index) => ({
|
displays: screen.getAllDisplays().map((display, index) => ({
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { contextBridge, ipcRenderer } from 'electron';
|
import { contextBridge, ipcRenderer } from 'electron';
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('meloOverlay', {
|
contextBridge.exposeInMainWorld('meloOverlay', {
|
||||||
toggleRecording: (): void => ipcRenderer.send('overlay:toggle-recording'),
|
|
||||||
onState: (listener: (state: string) => void): void => {
|
onState: (listener: (state: string) => void): void => {
|
||||||
ipcRenderer.on('overlay-state', (_event, payload: { state: string }) => listener(payload.state));
|
ipcRenderer.on('overlay-state', (_event, payload: { state: string }) => listener(payload.state));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,10 @@ contextBridge.exposeInMainWorld('meloSettings', {
|
|||||||
ipcRenderer.invoke('settings:set-position', position, displayId),
|
ipcRenderer.invoke('settings:set-position', position, displayId),
|
||||||
setPreset: (preset: string, displayId: string): Promise<SettingsViewState> =>
|
setPreset: (preset: string, displayId: string): Promise<SettingsViewState> =>
|
||||||
ipcRenderer.invoke('settings:set-preset', preset, displayId),
|
ipcRenderer.invoke('settings:set-preset', preset, displayId),
|
||||||
previewOverlay: (): Promise<void> => ipcRenderer.invoke('settings:preview-overlay'),
|
|
||||||
beginPositioning: (): Promise<void> => ipcRenderer.invoke('settings:begin-positioning'),
|
beginPositioning: (): Promise<void> => ipcRenderer.invoke('settings:begin-positioning'),
|
||||||
endPositioning: (): Promise<void> => ipcRenderer.invoke('settings:end-positioning'),
|
endPositioning: (): Promise<void> => ipcRenderer.invoke('settings:end-positioning'),
|
||||||
setShortcut: (shortcut: string): Promise<SettingsViewState> => ipcRenderer.invoke('settings:set-shortcut', shortcut),
|
setShortcut: (shortcut: string): Promise<SettingsViewState> => ipcRenderer.invoke('settings:set-shortcut', shortcut),
|
||||||
setAutoStart: (enabled: boolean): Promise<SettingsViewState> => ipcRenderer.invoke('settings:set-auto-start', enabled),
|
setAutoStart: (enabled: boolean): Promise<SettingsViewState> => ipcRenderer.invoke('settings:set-auto-start', enabled),
|
||||||
setOverlayPersistent: (enabled: boolean): Promise<SettingsViewState> =>
|
|
||||||
ipcRenderer.invoke('settings:set-overlay-persistent', enabled),
|
|
||||||
setDiagnosticLogging: (enabled: boolean): Promise<SettingsViewState> =>
|
setDiagnosticLogging: (enabled: boolean): Promise<SettingsViewState> =>
|
||||||
ipcRenderer.invoke('settings:set-diagnostic-logging', enabled),
|
ipcRenderer.invoke('settings:set-diagnostic-logging', enabled),
|
||||||
openRepository: (): Promise<void> => ipcRenderer.invoke('settings:open-repository'),
|
openRepository: (): Promise<void> => ipcRenderer.invoke('settings:open-repository'),
|
||||||
|
|||||||
Vendored
-3
@@ -8,19 +8,16 @@ declare global {
|
|||||||
openDebug(confirmed?: boolean): Promise<void>;
|
openDebug(confirmed?: boolean): Promise<void>;
|
||||||
setPosition(position: Point, displayId: string): Promise<SettingsViewState>;
|
setPosition(position: Point, displayId: string): Promise<SettingsViewState>;
|
||||||
setPreset(preset: string, displayId: string): Promise<SettingsViewState>;
|
setPreset(preset: string, displayId: string): Promise<SettingsViewState>;
|
||||||
previewOverlay(): Promise<void>;
|
|
||||||
beginPositioning(): Promise<void>;
|
beginPositioning(): Promise<void>;
|
||||||
endPositioning(): Promise<void>;
|
endPositioning(): Promise<void>;
|
||||||
setShortcut(shortcut: string): Promise<SettingsViewState>;
|
setShortcut(shortcut: string): Promise<SettingsViewState>;
|
||||||
setAutoStart(enabled: boolean): Promise<SettingsViewState>;
|
setAutoStart(enabled: boolean): Promise<SettingsViewState>;
|
||||||
setOverlayPersistent(enabled: boolean): Promise<SettingsViewState>;
|
|
||||||
setDiagnosticLogging(enabled: boolean): Promise<SettingsViewState>;
|
setDiagnosticLogging(enabled: boolean): Promise<SettingsViewState>;
|
||||||
openRepository(): Promise<void>;
|
openRepository(): Promise<void>;
|
||||||
onState(listener: (state: SettingsViewState) => void): void;
|
onState(listener: (state: SettingsViewState) => void): void;
|
||||||
onLoginNotice(listener: (backendLabel: string) => void): void;
|
onLoginNotice(listener: (backendLabel: string) => void): void;
|
||||||
};
|
};
|
||||||
meloOverlay: {
|
meloOverlay: {
|
||||||
toggleRecording(): void;
|
|
||||||
onState(listener: (state: string) => void): void;
|
onState(listener: (state: string) => void): void;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
html, body { width: 100%; height: 100%; margin: 0; overflow: hidden; background: transparent; }
|
html, body { width: 100%; height: 100%; margin: 0; overflow: hidden; background: transparent; }
|
||||||
body { display: grid; place-items: center; }
|
body { display: grid; place-items: center; }
|
||||||
.voice-overlay { position: relative; display: grid; place-items: center; width: 68px; height: 68px; padding: 0; border: 0; border-radius: 50%; background: radial-gradient(circle at 35% 28%, #71aaff, #2568de 70%); box-shadow: 0 8px 24px rgba(23,79,177,.35); cursor: pointer; }
|
.voice-overlay { position: relative; display: grid; place-items: center; width: 68px; height: 68px; border-radius: 50%; background: radial-gradient(circle at 35% 28%, #71aaff, #2568de 70%); box-shadow: 0 8px 24px rgba(23,79,177,.35); }
|
||||||
.ring { position: absolute; inset: 0; border: 2px solid rgba(69,136,245,.45); border-radius: 50%; opacity: 0; }
|
.ring { position: absolute; inset: 0; border: 2px solid rgba(69,136,245,.45); border-radius: 50%; opacity: 0; }
|
||||||
.voice-overlay[data-state="recording"] .ring { animation: ripple 1.7s ease-out infinite; }
|
.voice-overlay[data-state="recording"] .ring { animation: ripple 1.7s ease-out infinite; }
|
||||||
.voice-overlay[data-state="recording"] .ring.two { animation-delay: .55s; }
|
.voice-overlay[data-state="recording"] .ring.two { animation-delay: .55s; }
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
<link rel="stylesheet" href="overlay.css">
|
<link rel="stylesheet" href="overlay.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<button class="voice-overlay" data-state="idle" aria-label="开始或停止语音输入">
|
<div class="voice-overlay" data-state="idle" aria-hidden="true">
|
||||||
<span class="ring one"></span><span class="ring two"></span>
|
<span class="ring one"></span><span class="ring two"></span>
|
||||||
<span class="bars"><i></i><i></i><i></i><i></i></span>
|
<span class="bars"><i></i><i></i><i></i><i></i></span>
|
||||||
</button>
|
</div>
|
||||||
<script src="overlay.js"></script>
|
<script src="overlay.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
const root = document.querySelector<HTMLElement>('.voice-overlay')!;
|
const root = document.querySelector<HTMLElement>('.voice-overlay')!;
|
||||||
|
|
||||||
root.addEventListener('click', () => window.meloOverlay.toggleRecording());
|
|
||||||
root.addEventListener('keydown', (event) => {
|
|
||||||
if (event.key === 'Enter' || event.key === ' ') window.meloOverlay.toggleRecording();
|
|
||||||
});
|
|
||||||
window.meloOverlay.onState((state) => { root.dataset.state = state; });
|
window.meloOverlay.onState((state) => { root.dataset.state = state; });
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h2>悬浮球</h2>
|
<h2>悬浮球</h2>
|
||||||
<label class="switch"><input id="overlay-persistent" type="checkbox"><span>始终显示悬浮球</span></label>
|
|
||||||
<button id="open-position">调整悬浮球位置</button>
|
<button id="open-position">调整悬浮球位置</button>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ interface SettingsViewState {
|
|||||||
sessionState: 'idle' | 'starting' | 'recording' | 'stopping';
|
sessionState: 'idle' | 'starting' | 'recording' | 'stopping';
|
||||||
shortcut: string;
|
shortcut: string;
|
||||||
autoStart: boolean;
|
autoStart: boolean;
|
||||||
overlayPersistent: boolean;
|
|
||||||
diagnosticLogging: boolean;
|
diagnosticLogging: boolean;
|
||||||
overlayPosition: { x: number; y: number };
|
overlayPosition: { x: number; y: number };
|
||||||
displays: Array<{ id: string; label: string; workArea: { x: number; y: number; width: number; height: number } }>;
|
displays: Array<{ id: string; label: string; workArea: { x: number; y: number; width: number; height: number } }>;
|
||||||
@@ -26,7 +25,6 @@ const x = document.querySelector<HTMLInputElement>('#position-x')!;
|
|||||||
const y = document.querySelector<HTMLInputElement>('#position-y')!;
|
const y = document.querySelector<HTMLInputElement>('#position-y')!;
|
||||||
const shortcut = document.querySelector<HTMLButtonElement>('#shortcut')!;
|
const shortcut = document.querySelector<HTMLButtonElement>('#shortcut')!;
|
||||||
const autoStart = document.querySelector<HTMLInputElement>('#auto-start')!;
|
const autoStart = document.querySelector<HTMLInputElement>('#auto-start')!;
|
||||||
const overlayPersistent = document.querySelector<HTMLInputElement>('#overlay-persistent')!;
|
|
||||||
const diagnosticLogging = document.querySelector<HTMLInputElement>('#diagnostic-logging')!;
|
const diagnosticLogging = document.querySelector<HTMLInputElement>('#diagnostic-logging')!;
|
||||||
const version = document.querySelector<HTMLElement>('#version')!;
|
const version = document.querySelector<HTMLElement>('#version')!;
|
||||||
const repository = document.querySelector<HTMLButtonElement>('#repository')!;
|
const repository = document.querySelector<HTMLButtonElement>('#repository')!;
|
||||||
@@ -71,7 +69,6 @@ function render(next: SettingsViewState): void {
|
|||||||
renderPositionPreview(next);
|
renderPositionPreview(next);
|
||||||
shortcut.textContent = capturingShortcut ? '请按下新快捷键…' : displayShortcut(next.shortcut);
|
shortcut.textContent = capturingShortcut ? '请按下新快捷键…' : displayShortcut(next.shortcut);
|
||||||
autoStart.checked = next.autoStart;
|
autoStart.checked = next.autoStart;
|
||||||
overlayPersistent.checked = next.overlayPersistent;
|
|
||||||
diagnosticLogging.checked = next.diagnosticLogging;
|
diagnosticLogging.checked = next.diagnosticLogging;
|
||||||
version.textContent = next.version;
|
version.textContent = next.version;
|
||||||
repository.textContent = next.repositoryUrl ?? '尚未配置';
|
repository.textContent = next.repositoryUrl ?? '尚未配置';
|
||||||
@@ -197,9 +194,6 @@ shortcut.addEventListener('click', () => {
|
|||||||
shortcut.focus();
|
shortcut.focus();
|
||||||
});
|
});
|
||||||
autoStart.addEventListener('change', () => void apply(() => window.meloSettings.setAutoStart(autoStart.checked)));
|
autoStart.addEventListener('change', () => void apply(() => window.meloSettings.setAutoStart(autoStart.checked)));
|
||||||
overlayPersistent.addEventListener('change', () => void apply(
|
|
||||||
() => window.meloSettings.setOverlayPersistent(overlayPersistent.checked)
|
|
||||||
));
|
|
||||||
diagnosticLogging.addEventListener('change', () => void apply(
|
diagnosticLogging.addEventListener('change', () => void apply(
|
||||||
() => window.meloSettings.setDiagnosticLogging(diagnosticLogging.checked)
|
() => window.meloSettings.setDiagnosticLogging(diagnosticLogging.checked)
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ export interface AppSettings {
|
|||||||
backendId: string;
|
backendId: string;
|
||||||
shortcut: string;
|
shortcut: string;
|
||||||
autoStart: boolean;
|
autoStart: boolean;
|
||||||
overlayPersistent: boolean;
|
|
||||||
diagnosticLogging: boolean;
|
diagnosticLogging: boolean;
|
||||||
overlayPosition: Point | null;
|
overlayPosition: Point | null;
|
||||||
loginNoticeShown: Record<string, boolean>;
|
loginNoticeShown: Record<string, boolean>;
|
||||||
@@ -43,7 +42,6 @@ export interface SettingsViewState {
|
|||||||
sessionState: SessionState;
|
sessionState: SessionState;
|
||||||
shortcut: string;
|
shortcut: string;
|
||||||
autoStart: boolean;
|
autoStart: boolean;
|
||||||
overlayPersistent: boolean;
|
|
||||||
diagnosticLogging: boolean;
|
diagnosticLogging: boolean;
|
||||||
overlayPosition: Point;
|
overlayPosition: Point;
|
||||||
displays: DisplayInfo[];
|
displays: DisplayInfo[];
|
||||||
|
|||||||
Reference in New Issue
Block a user