mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-06-09 15:13:32 -07:00
9d77907877
- Show mpv OSD spinner from start-file until subminer-overlay-loading-ready; force-shown for visible-overlay startup regardless of osd_messages setting - Gate non-macOS overlay visibility on content-ready so first subtitle line is immediately hoverable and clickable - Queue startup notifications in main process until overlay window finishes loading; upsert progress cards by id to avoid cold-start floods - Defer background warmups until after overlay runtime init so queued notifications can deliver promptly - Preserve character dictionary checking/building/importing/ready phases as distinct history entries; route building and importing to system notifications when notificationType is both
217 lines
7.2 KiB
TypeScript
217 lines
7.2 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import {
|
|
notifyCharacterDictionaryAutoSyncStatus,
|
|
type CharacterDictionaryAutoSyncNotificationEvent,
|
|
} from './character-dictionary-auto-sync-notifications';
|
|
import { createStartupOsdSequencer } from './startup-osd-sequencer';
|
|
|
|
function makeEvent(
|
|
phase: CharacterDictionaryAutoSyncNotificationEvent['phase'],
|
|
message: string,
|
|
): CharacterDictionaryAutoSyncNotificationEvent {
|
|
return {
|
|
phase,
|
|
mediaId: 101291,
|
|
mediaTitle: 'Rascal Does Not Dream of Bunny Girl Senpai',
|
|
message,
|
|
};
|
|
}
|
|
|
|
test('auto sync notifications send osd updates for progress phases', () => {
|
|
const calls: string[] = [];
|
|
|
|
notifyCharacterDictionaryAutoSyncStatus(makeEvent('checking', 'checking'), {
|
|
getNotificationType: () => 'osd',
|
|
showOsd: (message) => {
|
|
calls.push(`osd:${message}`);
|
|
},
|
|
showDesktopNotification: (title, options) =>
|
|
calls.push(`desktop:${title}:${options.body ?? ''}`),
|
|
});
|
|
notifyCharacterDictionaryAutoSyncStatus(makeEvent('generating', 'generating'), {
|
|
getNotificationType: () => 'osd',
|
|
showOsd: (message) => {
|
|
calls.push(`osd:${message}`);
|
|
},
|
|
showDesktopNotification: (title, options) =>
|
|
calls.push(`desktop:${title}:${options.body ?? ''}`),
|
|
});
|
|
notifyCharacterDictionaryAutoSyncStatus(makeEvent('syncing', 'syncing'), {
|
|
getNotificationType: () => 'osd',
|
|
showOsd: (message) => {
|
|
calls.push(`osd:${message}`);
|
|
},
|
|
showDesktopNotification: (title, options) =>
|
|
calls.push(`desktop:${title}:${options.body ?? ''}`),
|
|
});
|
|
notifyCharacterDictionaryAutoSyncStatus(makeEvent('importing', 'importing'), {
|
|
getNotificationType: () => 'osd',
|
|
showOsd: (message) => {
|
|
calls.push(`osd:${message}`);
|
|
},
|
|
showDesktopNotification: (title, options) =>
|
|
calls.push(`desktop:${title}:${options.body ?? ''}`),
|
|
});
|
|
notifyCharacterDictionaryAutoSyncStatus(makeEvent('ready', 'ready'), {
|
|
getNotificationType: () => 'osd',
|
|
showOsd: (message) => {
|
|
calls.push(`osd:${message}`);
|
|
},
|
|
showDesktopNotification: (title, options) =>
|
|
calls.push(`desktop:${title}:${options.body ?? ''}`),
|
|
});
|
|
|
|
assert.deepEqual(calls, [
|
|
'osd:checking',
|
|
'osd:generating',
|
|
'osd:syncing',
|
|
'osd:importing',
|
|
'osd:ready',
|
|
]);
|
|
});
|
|
|
|
test('auto sync notifications send overlay and desktop delivery for both', () => {
|
|
const calls: string[] = [];
|
|
|
|
notifyCharacterDictionaryAutoSyncStatus(makeEvent('syncing', 'syncing'), {
|
|
getNotificationType: () => 'both',
|
|
showOsd: (message) => {
|
|
calls.push(`osd:${message}`);
|
|
},
|
|
showDesktopNotification: (title, options) =>
|
|
calls.push(`desktop:${title}:${options.body ?? ''}`),
|
|
showOverlayNotification: (payload) =>
|
|
calls.push(
|
|
`overlay:${payload.id}:${payload.historyId}:${payload.title}:${payload.body}:${payload.persistent ? 'pin' : 'auto'}`,
|
|
),
|
|
});
|
|
notifyCharacterDictionaryAutoSyncStatus(makeEvent('ready', 'ready'), {
|
|
getNotificationType: () => 'both',
|
|
showOsd: (message) => {
|
|
calls.push(`osd:${message}`);
|
|
},
|
|
showDesktopNotification: (title, options) =>
|
|
calls.push(`desktop:${title}:${options.body ?? ''}`),
|
|
showOverlayNotification: (payload) =>
|
|
calls.push(
|
|
`overlay:${payload.id}:${payload.historyId}:${payload.title}:${payload.body}:${payload.persistent ? 'pin' : 'auto'}`,
|
|
),
|
|
});
|
|
|
|
assert.deepEqual(calls, [
|
|
'overlay:character-dictionary-auto-sync:character-dictionary-auto-sync-101291-syncing:Character dictionary:syncing:pin',
|
|
'desktop:SubMiner:syncing',
|
|
'overlay:character-dictionary-auto-sync:character-dictionary-auto-sync-101291-ready:Character dictionary:ready:auto',
|
|
'desktop:SubMiner:ready',
|
|
]);
|
|
});
|
|
|
|
test('auto sync notifications fall back to desktop when overlay routing is unavailable', () => {
|
|
const calls: string[] = [];
|
|
|
|
notifyCharacterDictionaryAutoSyncStatus(makeEvent('building', 'building'), {
|
|
getNotificationType: () => undefined,
|
|
showOsd: (message) => {
|
|
calls.push(`osd:${message}`);
|
|
},
|
|
showDesktopNotification: (title, options) =>
|
|
calls.push(`desktop:${title}:${options.body ?? ''}`),
|
|
});
|
|
|
|
assert.deepEqual(calls, ['desktop:SubMiner:building']);
|
|
});
|
|
|
|
test('auto sync notifications keep osd-system on legacy surfaces', () => {
|
|
const calls: string[] = [];
|
|
|
|
notifyCharacterDictionaryAutoSyncStatus(makeEvent('syncing', 'syncing'), {
|
|
getNotificationType: () => 'osd-system',
|
|
showOsd: (message) => {
|
|
calls.push(`osd:${message}`);
|
|
},
|
|
showDesktopNotification: (title, options) =>
|
|
calls.push(`desktop:${title}:${options.body ?? ''}`),
|
|
showOverlayNotification: (payload) => calls.push(`overlay:${payload.body}`),
|
|
});
|
|
|
|
assert.deepEqual(calls, ['osd:syncing', 'desktop:SubMiner:syncing']);
|
|
});
|
|
|
|
test('auto sync notifications keep osd-system desktop delivery even when osd is unavailable', () => {
|
|
const calls: string[] = [];
|
|
|
|
notifyCharacterDictionaryAutoSyncStatus(makeEvent('generating', 'generating'), {
|
|
getNotificationType: () => 'osd-system',
|
|
showOsd: (message) => {
|
|
calls.push(`osd:${message}`);
|
|
return false;
|
|
},
|
|
showDesktopNotification: (title, options) =>
|
|
calls.push(`desktop:${title}:${options.body ?? ''}`),
|
|
});
|
|
notifyCharacterDictionaryAutoSyncStatus(makeEvent('ready', 'ready'), {
|
|
getNotificationType: () => 'osd-system',
|
|
showOsd: (message) => {
|
|
calls.push(`osd:${message}`);
|
|
return false;
|
|
},
|
|
showDesktopNotification: (title, options) =>
|
|
calls.push(`desktop:${title}:${options.body ?? ''}`),
|
|
});
|
|
|
|
assert.deepEqual(calls, [
|
|
'osd:generating',
|
|
'desktop:SubMiner:generating',
|
|
'osd:ready',
|
|
'desktop:SubMiner:ready',
|
|
]);
|
|
});
|
|
|
|
test('auto sync notifications send osd-system desktop updates with startup sequencer', () => {
|
|
const calls: string[] = [];
|
|
|
|
notifyCharacterDictionaryAutoSyncStatus(makeEvent('importing', 'importing'), {
|
|
getNotificationType: () => 'osd-system',
|
|
showOsd: (message) => {
|
|
calls.push(`osd:${message}`);
|
|
},
|
|
showDesktopNotification: (title, options) =>
|
|
calls.push(`desktop:${title}:${options.body ?? ''}`),
|
|
startupOsdSequencer: {
|
|
notifyCharacterDictionaryStatus: (event) => {
|
|
calls.push(`sequencer:${event.phase}:${event.message}`);
|
|
return false;
|
|
},
|
|
},
|
|
});
|
|
|
|
assert.deepEqual(calls, ['sequencer:importing:importing', 'desktop:SubMiner:importing']);
|
|
});
|
|
|
|
test('auto sync notifications let startup sequencer own osd-system desktop delivery', () => {
|
|
const calls: string[] = [];
|
|
const startupOsdSequencer = createStartupOsdSequencer({
|
|
getNotificationType: () => 'osd-system',
|
|
showOsd: (message) => {
|
|
calls.push(`osd:${message}`);
|
|
},
|
|
showDesktopNotification: (title, options) => {
|
|
calls.push(`desktop:${title}:${options.body ?? ''}`);
|
|
},
|
|
});
|
|
startupOsdSequencer.markTokenizationReady();
|
|
|
|
notifyCharacterDictionaryAutoSyncStatus(makeEvent('importing', 'importing'), {
|
|
getNotificationType: () => 'osd-system',
|
|
showOsd: (message) => {
|
|
calls.push(`direct-osd:${message}`);
|
|
},
|
|
showDesktopNotification: (title, options) =>
|
|
calls.push(`direct-desktop:${title}:${options.body ?? ''}`),
|
|
startupOsdSequencer,
|
|
});
|
|
|
|
assert.deepEqual(calls, ['osd:importing', 'desktop:SubMiner:importing']);
|
|
});
|