diff --git a/src/main/index.ts b/src/main/index.ts index f64ee99..2f0e13a 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -22,7 +22,7 @@ import { createInboxWindow, getInboxWindow } from './windows/inboxWindow.js'; import { createQuickCaptureWindow, showQuickCapture, getQuickCaptureWindow } from './windows/quickCaptureWindow.js'; -import { createTray, refreshTray, refreshTrayOllama } from './tray.js'; +import { createTray, refreshTray, refreshTrayOllama, refreshTrayFailedCount } from './tray.js'; import { MediaGc } from './services/MediaGc.js'; import { BackupService } from './services/BackupService.js'; import { ExportService } from './services/ExportService.js'; @@ -92,6 +92,7 @@ app.whenReady().then(async () => { pushNoteUpdated(getInboxWindow, note); // F4-C: AI 처리 완료 = 새 캡처가 inbox 에 합류한 시점, tray 도 즉시 갱신. refreshTray(repo.countToday()); + refreshTrayFailedCount(repo.countFailed()); }, logger, telemetry @@ -343,13 +344,15 @@ app.whenReady().then(async () => { }).show(); } }, - /* runOllamaRecheck */ () => { void health.runOnce({ manual: true }); } + /* runOllamaRecheck */ () => { void health.runOnce({ manual: true }); }, + /* runRetryAllFailed */ () => { void capture.retryAllFailed(); } ); // F4-C 환경 앵커 — tray tooltip + 메뉴 첫 항목을 오늘 KST 캡처 수로 갱신. // 초기 1회 + 60s interval. AiWorker.onUpdate 도 별도 갱신 트리거. // cleanup 은 위 통합 before-quit 핸들러에서 처리. refreshTray(repo.countToday()); + refreshTrayFailedCount(repo.countFailed()); trayInterval = setInterval(() => { refreshTray(repo.countToday()); }, 60_000); diff --git a/src/main/tray.ts b/src/main/tray.ts index d905436..9d7e8bc 100644 --- a/src/main/tray.ts +++ b/src/main/tray.ts @@ -13,6 +13,8 @@ let _runExportTelemetry: () => void = () => {}; let _runOllamaRecheck: () => void = () => {}; let _ollamaOk = true; let _todayCount = 0; +let _runRetryAllFailed: () => void = () => {}; +let _failedCount = 0; function buildMenu() { const items: MenuItemConstructorOptions[] = []; @@ -34,6 +36,11 @@ function buildMenu() { enabled: !_ollamaOk, click: _runOllamaRecheck }); + items.push({ + label: `지금 AI 처리 (실패 ${_failedCount}건)`, + enabled: _failedCount > 0, + click: _runRetryAllFailed + }); if (app.isPackaged) { const { openAtLogin } = app.getLoginItemSettings(); items.push({ @@ -63,7 +70,8 @@ export function createTray( runImport: () => void, runSync: () => void, runExportTelemetry: () => void, - runOllamaRecheck: () => void + runOllamaRecheck: () => void, + runRetryAllFailed: () => void ): TrayType { _showInbox = showInbox; _showCapture = showCapture; @@ -73,6 +81,7 @@ export function createTray( _runSync = runSync; _runExportTelemetry = runExportTelemetry; _runOllamaRecheck = runOllamaRecheck; + _runRetryAllFailed = runRetryAllFailed; const icon = nativeImage.createEmpty(); tray = new Tray(icon); tray.setToolTip(`Inkling — 오늘 ${_todayCount}`); @@ -101,3 +110,12 @@ export function refreshTrayOllama(ok: boolean): void { if (tray === null) return; tray.setContextMenu(buildMenu()); } + +/** + * v0.2.3 #2 — AiWorker.onUpdate 시 실패 카운트 변하면 메뉴 라벨 + enabled 갱신. + */ +export function refreshTrayFailedCount(count: number): void { + _failedCount = count; + if (tray === null) return; + tray.setContextMenu(buildMenu()); +}