mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-26 12:55:16 -07:00
Fix macOS overlay foreground handling and character-dictionary cache reuse (#68)
This commit is contained in:
@@ -2,22 +2,30 @@ import { isYoutubeMediaPath } from './youtube-playback';
|
||||
|
||||
type AnilistGuess = {
|
||||
title: string;
|
||||
season: number | null;
|
||||
episode: number | null;
|
||||
};
|
||||
|
||||
type AnilistUpdateResult = {
|
||||
status: 'updated' | 'skipped' | 'error';
|
||||
message: string;
|
||||
retryable?: boolean;
|
||||
};
|
||||
|
||||
type RetryQueueItem = {
|
||||
key: string;
|
||||
title: string;
|
||||
season?: number | null;
|
||||
episode: number;
|
||||
};
|
||||
|
||||
type AnilistPostWatchRunOptions = {
|
||||
force?: boolean;
|
||||
watchedSeconds?: number;
|
||||
};
|
||||
|
||||
type AnilistDurationProbeOptions = {
|
||||
force?: boolean;
|
||||
};
|
||||
|
||||
export function buildAnilistAttemptKey(mediaKey: string, episode: number): string {
|
||||
@@ -49,6 +57,7 @@ export function createProcessNextAnilistRetryUpdateHandler(deps: {
|
||||
accessToken: string,
|
||||
title: string,
|
||||
episode: number,
|
||||
season?: number | null,
|
||||
) => Promise<AnilistUpdateResult>;
|
||||
markSuccess: (key: string) => void;
|
||||
rememberAttemptedUpdateKey: (key: string) => void;
|
||||
@@ -74,6 +83,7 @@ export function createProcessNextAnilistRetryUpdateHandler(deps: {
|
||||
accessToken,
|
||||
queued.title,
|
||||
queued.episode,
|
||||
queued.season ?? null,
|
||||
);
|
||||
if (result.status === 'updated' || result.status === 'skipped') {
|
||||
deps.markSuccess(queued.key);
|
||||
@@ -101,12 +111,15 @@ export function createMaybeRunAnilistPostWatchUpdateHandler(deps: {
|
||||
getTrackedMediaKey: () => string | null;
|
||||
resetTrackedMedia: (mediaKey: string | null) => void;
|
||||
getWatchedSeconds: () => number;
|
||||
maybeProbeAnilistDuration: (mediaKey: string) => Promise<number | null>;
|
||||
maybeProbeAnilistDuration: (
|
||||
mediaKey: string,
|
||||
options?: AnilistDurationProbeOptions,
|
||||
) => Promise<number | null>;
|
||||
ensureAnilistMediaGuess: (mediaKey: string) => Promise<AnilistGuess | null>;
|
||||
hasAttemptedUpdateKey: (key: string) => boolean;
|
||||
processNextAnilistRetryUpdate: () => Promise<{ ok: boolean; message: string }>;
|
||||
refreshAnilistClientSecretState: () => Promise<string | null>;
|
||||
enqueueRetry: (key: string, title: string, episode: number) => void;
|
||||
enqueueRetry: (key: string, title: string, episode: number, season?: number | null) => void;
|
||||
markRetryFailure: (key: string, message: string) => void;
|
||||
markRetrySuccess: (key: string) => void;
|
||||
refreshRetryQueueState: () => void;
|
||||
@@ -114,6 +127,7 @@ export function createMaybeRunAnilistPostWatchUpdateHandler(deps: {
|
||||
accessToken: string,
|
||||
title: string,
|
||||
episode: number,
|
||||
season?: number | null,
|
||||
) => Promise<AnilistUpdateResult>;
|
||||
rememberAttemptedUpdateKey: (key: string) => void;
|
||||
showMpvOsd: (message: string) => void;
|
||||
@@ -146,7 +160,10 @@ export function createMaybeRunAnilistPostWatchUpdateHandler(deps: {
|
||||
|
||||
let watchedSeconds = 0;
|
||||
if (!force) {
|
||||
watchedSeconds = deps.getWatchedSeconds();
|
||||
watchedSeconds =
|
||||
typeof options.watchedSeconds === 'number' && Number.isFinite(options.watchedSeconds)
|
||||
? options.watchedSeconds
|
||||
: deps.getWatchedSeconds();
|
||||
if (!Number.isFinite(watchedSeconds) || watchedSeconds < deps.minWatchSeconds) {
|
||||
return;
|
||||
}
|
||||
@@ -155,7 +172,10 @@ export function createMaybeRunAnilistPostWatchUpdateHandler(deps: {
|
||||
deps.setInFlight(true);
|
||||
try {
|
||||
if (!force) {
|
||||
const duration = await deps.maybeProbeAnilistDuration(mediaKey);
|
||||
const duration = await deps.maybeProbeAnilistDuration(mediaKey, {
|
||||
force:
|
||||
typeof options.watchedSeconds === 'number' && Number.isFinite(options.watchedSeconds),
|
||||
});
|
||||
if (!duration || duration <= 0) {
|
||||
return;
|
||||
}
|
||||
@@ -181,7 +201,7 @@ export function createMaybeRunAnilistPostWatchUpdateHandler(deps: {
|
||||
|
||||
const accessToken = await deps.refreshAnilistClientSecretState();
|
||||
if (!accessToken) {
|
||||
deps.enqueueRetry(attemptKey, guess.title, guess.episode);
|
||||
deps.enqueueRetry(attemptKey, guess.title, guess.episode, guess.season);
|
||||
deps.markRetryFailure(attemptKey, 'cannot authenticate without anilist.accessToken');
|
||||
deps.refreshRetryQueueState();
|
||||
deps.showMpvOsd('AniList: access token not configured');
|
||||
@@ -192,6 +212,7 @@ export function createMaybeRunAnilistPostWatchUpdateHandler(deps: {
|
||||
accessToken,
|
||||
guess.title,
|
||||
guess.episode,
|
||||
guess.season,
|
||||
);
|
||||
if (result.status === 'updated') {
|
||||
deps.rememberAttemptedUpdateKey(attemptKey);
|
||||
@@ -209,7 +230,15 @@ export function createMaybeRunAnilistPostWatchUpdateHandler(deps: {
|
||||
return;
|
||||
}
|
||||
|
||||
deps.enqueueRetry(attemptKey, guess.title, guess.episode);
|
||||
if (result.retryable === false) {
|
||||
deps.rememberAttemptedUpdateKey(attemptKey);
|
||||
deps.refreshRetryQueueState();
|
||||
deps.showMpvOsd(result.message);
|
||||
deps.logWarn(result.message);
|
||||
return;
|
||||
}
|
||||
|
||||
deps.enqueueRetry(attemptKey, guess.title, guess.episode, guess.season);
|
||||
deps.markRetryFailure(attemptKey, result.message);
|
||||
deps.refreshRetryQueueState();
|
||||
deps.showMpvOsd(`AniList: ${result.message}`);
|
||||
|
||||
Reference in New Issue
Block a user