mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-13 20:12:54 -07:00
fix: sync AniList after seeked completion
This commit is contained in:
@@ -302,6 +302,54 @@ test('createIpcDepsRuntime wires AniList handlers', async () => {
|
||||
assert.equal(deps.getPlaybackPaused(), true);
|
||||
});
|
||||
|
||||
test('registerIpcHandlers runs AniList update after manual mark watched succeeds', async () => {
|
||||
const { registrar, handlers } = createFakeIpcRegistrar();
|
||||
const calls: string[] = [];
|
||||
registerIpcHandlers(
|
||||
createRegisterIpcDeps({
|
||||
immersionTracker: createFakeImmersionTracker({
|
||||
markActiveVideoWatched: async () => {
|
||||
calls.push('mark');
|
||||
return true;
|
||||
},
|
||||
}),
|
||||
runAnilistPostWatchUpdateOnManualMark: async () => {
|
||||
calls.push('anilist');
|
||||
},
|
||||
}),
|
||||
registrar,
|
||||
);
|
||||
|
||||
const result = await handlers.handle.get(IPC_CHANNELS.command.markActiveVideoWatched)?.({});
|
||||
|
||||
assert.equal(result, true);
|
||||
assert.deepEqual(calls, ['mark', 'anilist']);
|
||||
});
|
||||
|
||||
test('registerIpcHandlers skips AniList update when manual mark watched has no active session', async () => {
|
||||
const { registrar, handlers } = createFakeIpcRegistrar();
|
||||
const calls: string[] = [];
|
||||
registerIpcHandlers(
|
||||
createRegisterIpcDeps({
|
||||
immersionTracker: createFakeImmersionTracker({
|
||||
markActiveVideoWatched: async () => {
|
||||
calls.push('mark');
|
||||
return false;
|
||||
},
|
||||
}),
|
||||
runAnilistPostWatchUpdateOnManualMark: async () => {
|
||||
calls.push('anilist');
|
||||
},
|
||||
}),
|
||||
registrar,
|
||||
);
|
||||
|
||||
const result = await handlers.handle.get(IPC_CHANNELS.command.markActiveVideoWatched)?.({});
|
||||
|
||||
assert.equal(result, false);
|
||||
assert.deepEqual(calls, ['mark']);
|
||||
});
|
||||
|
||||
test('registerIpcHandlers exposes playlist browser snapshot and mutations', async () => {
|
||||
const { registrar, handlers } = createFakeIpcRegistrar();
|
||||
const calls: Array<[string, unknown[]]> = [];
|
||||
|
||||
@@ -90,6 +90,7 @@ export interface IpcServiceDeps {
|
||||
openAnilistSetup: () => void;
|
||||
getAnilistQueueStatus: () => unknown;
|
||||
retryAnilistQueueNow: () => Promise<{ ok: boolean; message: string }>;
|
||||
runAnilistPostWatchUpdateOnManualMark?: () => Promise<void>;
|
||||
getCharacterDictionarySelection?: () => Promise<unknown>;
|
||||
setCharacterDictionarySelection?: (mediaId: number) => Promise<unknown>;
|
||||
appendClipboardVideoToQueue: () => { ok: boolean; message: string };
|
||||
@@ -213,6 +214,7 @@ export interface IpcDepsRuntimeOptions {
|
||||
openAnilistSetup: () => void;
|
||||
getAnilistQueueStatus: () => unknown;
|
||||
retryAnilistQueueNow: () => Promise<{ ok: boolean; message: string }>;
|
||||
runAnilistPostWatchUpdateOnManualMark?: () => Promise<void>;
|
||||
getCharacterDictionarySelection?: () => Promise<unknown>;
|
||||
setCharacterDictionarySelection?: (mediaId: number) => Promise<unknown>;
|
||||
appendClipboardVideoToQueue: () => { ok: boolean; message: string };
|
||||
@@ -288,6 +290,7 @@ export function createIpcDepsRuntime(options: IpcDepsRuntimeOptions): IpcService
|
||||
openAnilistSetup: options.openAnilistSetup,
|
||||
getAnilistQueueStatus: options.getAnilistQueueStatus,
|
||||
retryAnilistQueueNow: options.retryAnilistQueueNow,
|
||||
runAnilistPostWatchUpdateOnManualMark: options.runAnilistPostWatchUpdateOnManualMark,
|
||||
getCharacterDictionarySelection:
|
||||
options.getCharacterDictionarySelection ??
|
||||
(async () => ({
|
||||
@@ -385,7 +388,11 @@ export function registerIpcHandlers(deps: IpcServiceDeps, ipc: IpcMainRegistrar
|
||||
});
|
||||
|
||||
ipc.handle(IPC_CHANNELS.command.markActiveVideoWatched, async () => {
|
||||
return (await deps.immersionTracker?.markActiveVideoWatched()) ?? false;
|
||||
const marked = (await deps.immersionTracker?.markActiveVideoWatched()) ?? false;
|
||||
if (marked) {
|
||||
await deps.runAnilistPostWatchUpdateOnManualMark?.();
|
||||
}
|
||||
return marked;
|
||||
});
|
||||
|
||||
ipc.on(IPC_CHANNELS.command.quitApp, () => {
|
||||
|
||||
@@ -281,6 +281,25 @@ test('dispatchMpvProtocolMessage pauses on sub-end when pendingPauseAtSubEnd is
|
||||
});
|
||||
});
|
||||
|
||||
test('dispatchMpvProtocolMessage updates current time before emitting time-pos change', async () => {
|
||||
const calls: string[] = [];
|
||||
let currentTimePos = 0;
|
||||
const { deps } = createDeps({
|
||||
setCurrentTimePos: (time) => {
|
||||
currentTimePos = time;
|
||||
calls.push(`set:${time}`);
|
||||
},
|
||||
getCurrentTimePos: () => currentTimePos,
|
||||
emitTimePosChange: ({ time }) => {
|
||||
calls.push(`emit:${time}:current=${currentTimePos}`);
|
||||
},
|
||||
});
|
||||
|
||||
await dispatchMpvProtocolMessage({ event: 'property-change', name: 'time-pos', data: 90 }, deps);
|
||||
|
||||
assert.deepEqual(calls, ['set:90', 'emit:90:current=90']);
|
||||
});
|
||||
|
||||
test('splitMpvMessagesFromBuffer parses complete lines and preserves partial buffer', () => {
|
||||
const parsed = splitMpvMessagesFromBuffer(
|
||||
'{"event":"shutdown"}\n{"event":"property-change","name":"media-title","data":"x"}\n{"partial"',
|
||||
|
||||
@@ -276,8 +276,9 @@ export async function dispatchMpvProtocolMessage(
|
||||
deps.setCurrentAudioTrackId(typeof msg.data === 'number' ? (msg.data as number) : null);
|
||||
deps.syncCurrentAudioStreamIndex();
|
||||
} else if (msg.name === 'time-pos') {
|
||||
deps.emitTimePosChange({ time: (msg.data as number) || 0 });
|
||||
deps.setCurrentTimePos((msg.data as number) || 0);
|
||||
const timePos = (msg.data as number) || 0;
|
||||
deps.setCurrentTimePos(timePos);
|
||||
deps.emitTimePosChange({ time: timePos });
|
||||
if (
|
||||
deps.getPauseAtTime() !== null &&
|
||||
deps.getCurrentTimePos() >= (deps.getPauseAtTime() as number)
|
||||
|
||||
Reference in New Issue
Block a user