mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-09-22 05:16:22 -07:00
feat(anki): add media timing review before card creation (#203)
This commit is contained in:
@@ -11,6 +11,78 @@ export type CardKind = 'sentence' | 'audio' | 'word-and-sentence' | 'click';
|
||||
/** Card kind SubMiner flags on word cards; 'none' leaves the flag fields untouched. */
|
||||
export type WordCardKind = CardKind | 'none';
|
||||
|
||||
export type MediaTimingReviewKind = 'word' | 'sentence' | 'audio';
|
||||
|
||||
export interface MediaTimingReviewRequest {
|
||||
kind: MediaTimingReviewKind;
|
||||
text: string;
|
||||
startTime: number;
|
||||
endTime: number;
|
||||
noteId?: number;
|
||||
audioPadding: number;
|
||||
maxMediaDuration: number;
|
||||
}
|
||||
|
||||
/** A subtitle line adjacent to the mined one that the review can pull onto the card. */
|
||||
export interface MediaTimingReviewContextLine {
|
||||
text: string;
|
||||
startTime: number;
|
||||
endTime: number;
|
||||
}
|
||||
|
||||
export type MediaTimingReviewDecision =
|
||||
/** `text` is set when the review combined adjacent lines into the card sentence. */
|
||||
| { action: 'confirm'; startTime: number; endTime: number; text?: string }
|
||||
| { action: 'use-original' }
|
||||
| { action: 'skip-media' }
|
||||
| { action: 'discard' };
|
||||
|
||||
export interface MediaTimingReviewOpenPayload {
|
||||
reviewId: string;
|
||||
kind: MediaTimingReviewKind;
|
||||
text: string;
|
||||
/** Lines before/after the mined one, both chronological: nearest previous line is last, nearest next line is first. */
|
||||
previousLines: MediaTimingReviewContextLine[];
|
||||
nextLines: MediaTimingReviewContextLine[];
|
||||
noteId?: number;
|
||||
originalStartTime: number;
|
||||
originalEndTime: number;
|
||||
selectionStartTime: number;
|
||||
selectionEndTime: number;
|
||||
timelineStartTime: number;
|
||||
timelineEndTime: number;
|
||||
mediaDuration?: number;
|
||||
maxMediaDuration: number;
|
||||
}
|
||||
|
||||
export interface MediaTimingReviewPreviewRequest {
|
||||
reviewId: string;
|
||||
startTime: number;
|
||||
endTime: number;
|
||||
}
|
||||
|
||||
export interface MediaTimingReviewWaveformRequest {
|
||||
reviewId: string;
|
||||
startTime: number;
|
||||
endTime: number;
|
||||
}
|
||||
|
||||
export interface MediaTimingReviewWaveformResult extends MediaTimingReviewActionResult {
|
||||
peaks?: number[];
|
||||
}
|
||||
|
||||
export interface MediaTimingReviewResolveRequest {
|
||||
reviewId: string;
|
||||
decision: MediaTimingReviewDecision;
|
||||
}
|
||||
|
||||
export interface MediaTimingReviewActionResult {
|
||||
ok: boolean;
|
||||
message?: string;
|
||||
/** The review this request targeted has already ended; the renderer should close. */
|
||||
stale?: boolean;
|
||||
}
|
||||
|
||||
export interface NotificationOptions {
|
||||
body?: string;
|
||||
icon?: string;
|
||||
@@ -85,6 +157,7 @@ export interface AnkiConnectConfig {
|
||||
syncAnimatedImageToWordAudio?: boolean;
|
||||
normalizeAudio?: boolean;
|
||||
mirrorMpvVolume?: boolean;
|
||||
reviewTiming?: boolean;
|
||||
audioPadding?: number;
|
||||
fallbackDuration?: number;
|
||||
maxMediaDuration?: number;
|
||||
|
||||
@@ -248,6 +248,7 @@ export interface ResolvedConfig {
|
||||
syncAnimatedImageToWordAudio: boolean;
|
||||
normalizeAudio: boolean;
|
||||
mirrorMpvVolume: boolean;
|
||||
reviewTiming: boolean;
|
||||
audioPadding: number;
|
||||
fallbackDuration: number;
|
||||
maxMediaDuration: number;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export type RuntimeOptionId =
|
||||
| 'anki.autoUpdateNewCards'
|
||||
| 'anki.mediaReviewTiming'
|
||||
| 'subtitle.annotation.knownWords.highlightEnabled'
|
||||
| 'subtitle.annotation.knownWords.maturityEnabled'
|
||||
| 'subtitle.annotation.nPlusOne'
|
||||
|
||||
@@ -3,6 +3,12 @@ import type {
|
||||
KikuFieldGroupingRequestData,
|
||||
KikuMergePreviewRequest,
|
||||
KikuMergePreviewResponse,
|
||||
MediaTimingReviewActionResult,
|
||||
MediaTimingReviewOpenPayload,
|
||||
MediaTimingReviewPreviewRequest,
|
||||
MediaTimingReviewResolveRequest,
|
||||
MediaTimingReviewWaveformRequest,
|
||||
MediaTimingReviewWaveformResult,
|
||||
} from './anki';
|
||||
import type { ChangelogSnapshot } from './changelog';
|
||||
import type { ResolvedConfig, ShortcutsConfig } from './config';
|
||||
@@ -516,6 +522,18 @@ export interface ElectronAPI {
|
||||
onOpenJimaku: (callback: () => void) => void;
|
||||
onOpenTsukihime: (callback: () => void) => void;
|
||||
onOpenYoutubeTrackPicker: (callback: (payload: YoutubePickerOpenPayload) => void) => void;
|
||||
onOpenMediaTimingReview: (callback: (payload: MediaTimingReviewOpenPayload) => void) => void;
|
||||
onMediaTimingReviewPreviewEnded: (callback: (reviewId: string) => void) => void;
|
||||
previewMediaTimingReview: (
|
||||
request: MediaTimingReviewPreviewRequest,
|
||||
) => Promise<MediaTimingReviewActionResult>;
|
||||
getMediaTimingReviewWaveform: (
|
||||
request: MediaTimingReviewWaveformRequest,
|
||||
) => Promise<MediaTimingReviewWaveformResult>;
|
||||
stopMediaTimingReviewPreview: (reviewId: string) => Promise<MediaTimingReviewActionResult>;
|
||||
resolveMediaTimingReview: (
|
||||
request: MediaTimingReviewResolveRequest,
|
||||
) => Promise<MediaTimingReviewActionResult>;
|
||||
onOpenPlaylistBrowser: (callback: () => void) => void;
|
||||
onOpenCharacterDictionaryManager: (callback: () => void) => void;
|
||||
onSubtitleSidebarToggle: (callback: () => void) => void;
|
||||
@@ -561,6 +579,7 @@ export interface ElectronAPI {
|
||||
| 'jimaku'
|
||||
| 'tsukihime'
|
||||
| 'youtube-track-picker'
|
||||
| 'media-timing-review'
|
||||
| 'playlist-browser'
|
||||
| 'kiku'
|
||||
| 'controller-select'
|
||||
@@ -577,6 +596,7 @@ export interface ElectronAPI {
|
||||
| 'jimaku'
|
||||
| 'tsukihime'
|
||||
| 'youtube-track-picker'
|
||||
| 'media-timing-review'
|
||||
| 'playlist-browser'
|
||||
| 'kiku'
|
||||
| 'controller-select'
|
||||
|
||||
@@ -243,6 +243,8 @@ export interface SubtitleMiningContext {
|
||||
startTime: number;
|
||||
endTime: number;
|
||||
capturedAtMs?: number;
|
||||
/** Explicit generator padding. Confirmed timing-review ranges set this to zero. */
|
||||
mediaPaddingSeconds?: number;
|
||||
}
|
||||
|
||||
export interface SubtitleHoverTokenPayload {
|
||||
|
||||
Reference in New Issue
Block a user