mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-07-27 04:49:49 -07:00
bc8dce870b
Color known-word subtitle highlights by Anki card maturity (new, learning, young, mature) like asbplayer (#171). Notes are classified server-side with Anki search filters (prop:ivl, is:learn) during the known-word cache refresh, so no per-card data is fetched. A word's tier is its most mature matching card/note, with the same reading-aware matching as boolean known-word lookups. - known-word cache v4 state persists per-note tiers; lifecycle key only gains the maturity field while enabled so existing caches survive - ankiConnect.knownWords.maturityEnabled + matureThresholdDays (21) - subtitleStyle.knownWordMaturityColors with catppuccin defaults - word-maturity-<tier> class rides on word-known so hover/selection rules keep applying; falls back to knownWordColor without tier data - runtime toggle subtitle.annotation.knownWords.maturityEnabled
119 lines
2.7 KiB
TypeScript
119 lines
2.7 KiB
TypeScript
import type { AiFeatureConfig } from './integrations';
|
|
import type { NotificationType } from './notification';
|
|
import type { NPlusOneMatchMode } from './subtitle';
|
|
|
|
export interface NotificationOptions {
|
|
body?: string;
|
|
icon?: string;
|
|
}
|
|
|
|
export interface KikuDuplicateCardInfo {
|
|
noteId: number;
|
|
expression: string;
|
|
sentencePreview: string;
|
|
hasAudio: boolean;
|
|
hasImage: boolean;
|
|
isOriginal: boolean;
|
|
}
|
|
|
|
export interface KikuFieldGroupingRequestData {
|
|
original: KikuDuplicateCardInfo;
|
|
duplicate: KikuDuplicateCardInfo;
|
|
}
|
|
|
|
export interface KikuFieldGroupingChoice {
|
|
keepNoteId: number;
|
|
deleteNoteId: number;
|
|
deleteDuplicate: boolean;
|
|
cancelled: boolean;
|
|
}
|
|
|
|
export interface KikuMergePreviewRequest {
|
|
keepNoteId: number;
|
|
deleteNoteId: number;
|
|
deleteDuplicate: boolean;
|
|
}
|
|
|
|
export interface KikuMergePreviewResponse {
|
|
ok: boolean;
|
|
compact?: Record<string, unknown>;
|
|
full?: Record<string, unknown>;
|
|
error?: string;
|
|
}
|
|
|
|
export interface AnkiConnectConfig {
|
|
enabled?: boolean;
|
|
url?: string;
|
|
pollingRate?: number;
|
|
proxy?: {
|
|
enabled?: boolean;
|
|
host?: string;
|
|
port?: number;
|
|
upstreamUrl?: string;
|
|
};
|
|
tags?: string[];
|
|
fields?: {
|
|
word?: string;
|
|
audio?: string;
|
|
image?: string;
|
|
sentence?: string;
|
|
miscInfo?: string;
|
|
translation?: string;
|
|
};
|
|
ai?: boolean | AiFeatureConfig;
|
|
media?: {
|
|
generateAudio?: boolean;
|
|
generateImage?: boolean;
|
|
imageType?: 'static' | 'avif';
|
|
imageFormat?: 'jpg' | 'png' | 'webp';
|
|
imageQuality?: number;
|
|
imageMaxWidth?: number;
|
|
imageMaxHeight?: number;
|
|
animatedFps?: number;
|
|
animatedMaxWidth?: number;
|
|
animatedMaxHeight?: number;
|
|
animatedCrf?: number;
|
|
syncAnimatedImageToWordAudio?: boolean;
|
|
normalizeAudio?: boolean;
|
|
mirrorMpvVolume?: boolean;
|
|
audioPadding?: number;
|
|
fallbackDuration?: number;
|
|
maxMediaDuration?: number;
|
|
};
|
|
knownWords?: {
|
|
highlightEnabled?: boolean;
|
|
maturityEnabled?: boolean;
|
|
matureThresholdDays?: number;
|
|
refreshMinutes?: number;
|
|
addMinedWordsImmediately?: boolean;
|
|
matchMode?: NPlusOneMatchMode;
|
|
decks?: Record<string, string[]>;
|
|
color?: string;
|
|
};
|
|
nPlusOne?: {
|
|
enabled?: boolean;
|
|
minSentenceWords?: number;
|
|
};
|
|
behavior?: {
|
|
overwriteAudio?: boolean;
|
|
overwriteImage?: boolean;
|
|
mediaInsertMode?: 'append' | 'prepend';
|
|
highlightWord?: boolean;
|
|
notificationType?: NotificationType;
|
|
autoUpdateNewCards?: boolean;
|
|
};
|
|
metadata?: {
|
|
pattern?: string;
|
|
};
|
|
deck?: string;
|
|
isLapis?: {
|
|
enabled?: boolean;
|
|
sentenceCardModel?: string;
|
|
};
|
|
isKiku?: {
|
|
enabled?: boolean;
|
|
fieldGrouping?: 'auto' | 'manual' | 'disabled';
|
|
deleteDuplicateInAuto?: boolean;
|
|
};
|
|
}
|