feat(accessibility): harden chat and keyboard interactions

Stream capability-authorized chat reads with cancellation, virtualize viewer rendering, centralize modal focus management, and add keyboard-accessible queue and VOD menus. Expose command palette combobox state and keep the document language synchronized with the selected locale.
This commit is contained in:
Sucukdeluxe
2026-08-12 01:42:42 +02:00
parent aa06d486be
commit 9c17269a54
16 changed files with 790 additions and 190 deletions
+13 -4
View File
@@ -1,6 +1,8 @@
import { contextBridge, ipcRenderer, webUtils } from 'electron';
import { CustomClip, MergeGroupItem, MergeGroup, QueueItem, DownloadProgress } from './types';
let chatReadSequence = 0;
// Types
interface RuntimeMetricsSnapshot {
cacheHits: number;
@@ -164,11 +166,18 @@ contextBridge.exposeInMainWorld('api', {
},
searchArchive: (filter: Record<string, unknown>) => ipcRenderer.invoke('search-archive', filter),
runStorageCleanup: (options?: { dryRun?: boolean }) => ipcRenderer.invoke('run-storage-cleanup', options),
readChatFile: async (filePath: string) => {
readChatFile: async (filePath: string, signal?: AbortSignal) => {
const capability = await ipcRenderer.invoke('authorize-managed-path', 'chat-input', filePath);
return capability
? ipcRenderer.invoke('read-chat-file', capability.token)
: { success: false, error: 'File access denied' };
if (!capability) return { success: false, error: 'File access denied' };
if (signal?.aborted) return { success: false, cancelled: true };
const requestId = `chat-${Date.now()}-${++chatReadSequence}`;
const cancel = () => ipcRenderer.send('cancel-chat-read', requestId);
signal?.addEventListener('abort', cancel, { once: true });
try {
return await ipcRenderer.invoke('read-chat-file', capability.token, requestId);
} finally {
signal?.removeEventListener('abort', cancel);
}
},
getAutomationStatus: () => ipcRenderer.invoke('get-automation-status'),
triggerAutoVodScan: () => ipcRenderer.invoke('trigger-auto-vod-scan'),