mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-04-11 04:19:26 -07:00
459 lines
14 KiB
TypeScript
459 lines
14 KiB
TypeScript
import type {
|
|
KikuFieldGroupingChoice,
|
|
KikuFieldGroupingRequestData,
|
|
KikuMergePreviewRequest,
|
|
KikuMergePreviewResponse,
|
|
} from './anki';
|
|
import type { ResolvedConfig, ShortcutsConfig } from './config';
|
|
import type {
|
|
CompiledSessionBinding,
|
|
SessionActionId,
|
|
SessionActionPayload,
|
|
} from './session-bindings';
|
|
import type {
|
|
JimakuApiResponse,
|
|
JimakuDownloadQuery,
|
|
JimakuDownloadResult,
|
|
JimakuEntry,
|
|
JimakuFileEntry,
|
|
JimakuFilesQuery,
|
|
JimakuMediaInfo,
|
|
JimakuSearchQuery,
|
|
YoutubePickerOpenPayload,
|
|
YoutubePickerResolveRequest,
|
|
YoutubePickerResolveResult,
|
|
} from './integrations';
|
|
import type {
|
|
SecondarySubMode,
|
|
SubtitleData,
|
|
SubtitlePosition,
|
|
SubtitleSidebarConfig,
|
|
SubtitleSidebarSnapshot,
|
|
SubtitleStyleConfig,
|
|
} from './subtitle';
|
|
import type {
|
|
RuntimeOptionApplyResult,
|
|
RuntimeOptionId,
|
|
RuntimeOptionState,
|
|
RuntimeOptionValue,
|
|
} from './runtime-options';
|
|
|
|
export interface WindowGeometry {
|
|
x: number;
|
|
y: number;
|
|
width: number;
|
|
height: number;
|
|
}
|
|
|
|
export interface Keybinding {
|
|
key: string;
|
|
command: (string | number)[] | null;
|
|
}
|
|
|
|
export interface MpvClient {
|
|
currentSubText: string;
|
|
currentVideoPath: string;
|
|
currentMediaTitle?: string | null;
|
|
currentTimePos: number;
|
|
currentSubStart: number;
|
|
currentSubEnd: number;
|
|
currentAudioStreamIndex: number | null;
|
|
requestProperty?: (name: string) => Promise<unknown>;
|
|
send(command: { command: unknown[]; request_id?: number }): boolean;
|
|
}
|
|
|
|
export interface SubsyncSourceTrack {
|
|
id: number;
|
|
label: string;
|
|
}
|
|
|
|
export interface SubsyncManualPayload {
|
|
sourceTracks: SubsyncSourceTrack[];
|
|
}
|
|
|
|
export interface SubsyncManualRunRequest {
|
|
engine: 'alass' | 'ffsubsync';
|
|
sourceTrackId?: number | null;
|
|
}
|
|
|
|
export interface SubsyncResult {
|
|
ok: boolean;
|
|
message: string;
|
|
}
|
|
|
|
export interface PlaylistBrowserDirectoryItem {
|
|
path: string;
|
|
basename: string;
|
|
episodeLabel?: string | null;
|
|
isCurrentFile: boolean;
|
|
}
|
|
|
|
export interface PlaylistBrowserQueueItem {
|
|
index: number;
|
|
id: number | null;
|
|
filename: string;
|
|
title: string | null;
|
|
displayLabel: string;
|
|
current: boolean;
|
|
playing: boolean;
|
|
path: string | null;
|
|
}
|
|
|
|
export interface PlaylistBrowserSnapshot {
|
|
directoryPath: string | null;
|
|
directoryAvailable: boolean;
|
|
directoryStatus: string;
|
|
directoryItems: PlaylistBrowserDirectoryItem[];
|
|
playlistItems: PlaylistBrowserQueueItem[];
|
|
playingIndex: number | null;
|
|
currentFilePath: string | null;
|
|
}
|
|
|
|
export interface PlaylistBrowserMutationResult {
|
|
ok: boolean;
|
|
message: string;
|
|
snapshot?: PlaylistBrowserSnapshot;
|
|
}
|
|
|
|
export type ControllerButtonBinding =
|
|
| 'none'
|
|
| 'select'
|
|
| 'buttonSouth'
|
|
| 'buttonEast'
|
|
| 'buttonNorth'
|
|
| 'buttonWest'
|
|
| 'leftShoulder'
|
|
| 'rightShoulder'
|
|
| 'leftStickPress'
|
|
| 'rightStickPress'
|
|
| 'leftTrigger'
|
|
| 'rightTrigger';
|
|
|
|
export type ControllerAxisBinding = 'leftStickX' | 'leftStickY' | 'rightStickX' | 'rightStickY';
|
|
export type ControllerTriggerInputMode = 'auto' | 'digital' | 'analog';
|
|
export type ControllerAxisDirection = 'negative' | 'positive';
|
|
export type ControllerDpadFallback = 'none' | 'horizontal' | 'vertical';
|
|
|
|
export interface ControllerNoneBinding {
|
|
kind: 'none';
|
|
}
|
|
|
|
export interface ControllerButtonInputBinding {
|
|
kind: 'button';
|
|
buttonIndex: number;
|
|
}
|
|
|
|
export interface ControllerAxisDirectionInputBinding {
|
|
kind: 'axis';
|
|
axisIndex: number;
|
|
direction: ControllerAxisDirection;
|
|
}
|
|
|
|
export interface ControllerAxisInputBinding {
|
|
kind: 'axis';
|
|
axisIndex: number;
|
|
dpadFallback?: ControllerDpadFallback;
|
|
}
|
|
|
|
export type ControllerDiscreteBindingConfig =
|
|
| ControllerButtonBinding
|
|
| ControllerNoneBinding
|
|
| ControllerButtonInputBinding
|
|
| ControllerAxisDirectionInputBinding;
|
|
|
|
export type ResolvedControllerDiscreteBinding =
|
|
| ControllerNoneBinding
|
|
| ControllerButtonInputBinding
|
|
| ControllerAxisDirectionInputBinding;
|
|
|
|
export type ControllerAxisBindingConfig =
|
|
| ControllerAxisBinding
|
|
| ControllerNoneBinding
|
|
| ControllerAxisInputBinding;
|
|
|
|
export type ResolvedControllerAxisBinding =
|
|
| ControllerNoneBinding
|
|
| {
|
|
kind: 'axis';
|
|
axisIndex: number;
|
|
dpadFallback: ControllerDpadFallback;
|
|
};
|
|
|
|
export interface ControllerBindingsConfig {
|
|
toggleLookup?: ControllerDiscreteBindingConfig;
|
|
closeLookup?: ControllerDiscreteBindingConfig;
|
|
toggleKeyboardOnlyMode?: ControllerDiscreteBindingConfig;
|
|
mineCard?: ControllerDiscreteBindingConfig;
|
|
quitMpv?: ControllerDiscreteBindingConfig;
|
|
previousAudio?: ControllerDiscreteBindingConfig;
|
|
nextAudio?: ControllerDiscreteBindingConfig;
|
|
playCurrentAudio?: ControllerDiscreteBindingConfig;
|
|
toggleMpvPause?: ControllerDiscreteBindingConfig;
|
|
leftStickHorizontal?: ControllerAxisBindingConfig;
|
|
leftStickVertical?: ControllerAxisBindingConfig;
|
|
rightStickHorizontal?: ControllerAxisBindingConfig;
|
|
rightStickVertical?: ControllerAxisBindingConfig;
|
|
}
|
|
|
|
export interface ResolvedControllerBindingsConfig {
|
|
toggleLookup?: ResolvedControllerDiscreteBinding;
|
|
closeLookup?: ResolvedControllerDiscreteBinding;
|
|
toggleKeyboardOnlyMode?: ResolvedControllerDiscreteBinding;
|
|
mineCard?: ResolvedControllerDiscreteBinding;
|
|
quitMpv?: ResolvedControllerDiscreteBinding;
|
|
previousAudio?: ResolvedControllerDiscreteBinding;
|
|
nextAudio?: ResolvedControllerDiscreteBinding;
|
|
playCurrentAudio?: ResolvedControllerDiscreteBinding;
|
|
toggleMpvPause?: ResolvedControllerDiscreteBinding;
|
|
leftStickHorizontal?: ResolvedControllerAxisBinding;
|
|
leftStickVertical?: ResolvedControllerAxisBinding;
|
|
rightStickHorizontal?: ResolvedControllerAxisBinding;
|
|
rightStickVertical?: ResolvedControllerAxisBinding;
|
|
}
|
|
|
|
export interface ControllerButtonIndicesConfig {
|
|
select?: number;
|
|
buttonSouth?: number;
|
|
buttonEast?: number;
|
|
buttonNorth?: number;
|
|
buttonWest?: number;
|
|
leftShoulder?: number;
|
|
rightShoulder?: number;
|
|
leftStickPress?: number;
|
|
rightStickPress?: number;
|
|
leftTrigger?: number;
|
|
rightTrigger?: number;
|
|
}
|
|
|
|
export interface ControllerConfig {
|
|
enabled?: boolean;
|
|
preferredGamepadId?: string;
|
|
preferredGamepadLabel?: string;
|
|
smoothScroll?: boolean;
|
|
scrollPixelsPerSecond?: number;
|
|
horizontalJumpPixels?: number;
|
|
stickDeadzone?: number;
|
|
triggerInputMode?: ControllerTriggerInputMode;
|
|
triggerDeadzone?: number;
|
|
repeatDelayMs?: number;
|
|
repeatIntervalMs?: number;
|
|
buttonIndices?: ControllerButtonIndicesConfig;
|
|
bindings?: ControllerBindingsConfig;
|
|
}
|
|
|
|
export interface ControllerPreferenceUpdate {
|
|
preferredGamepadId: string;
|
|
preferredGamepadLabel: string;
|
|
}
|
|
|
|
export type ControllerConfigUpdate = ControllerConfig;
|
|
|
|
export interface ControllerDeviceInfo {
|
|
id: string;
|
|
index: number;
|
|
mapping: string;
|
|
connected: boolean;
|
|
}
|
|
|
|
export interface ControllerButtonSnapshot {
|
|
value: number;
|
|
pressed: boolean;
|
|
touched?: boolean;
|
|
}
|
|
|
|
export interface ControllerRuntimeSnapshot {
|
|
connectedGamepads: ControllerDeviceInfo[];
|
|
activeGamepadId: string | null;
|
|
rawAxes: number[];
|
|
rawButtons: ControllerButtonSnapshot[];
|
|
}
|
|
|
|
export interface MpvSubtitleRenderMetrics {
|
|
subPos: number;
|
|
subFontSize: number;
|
|
subScale: number;
|
|
subMarginY: number;
|
|
subMarginX: number;
|
|
subFont: string;
|
|
subSpacing: number;
|
|
subBold: boolean;
|
|
subItalic: boolean;
|
|
subBorderSize: number;
|
|
subShadowOffset: number;
|
|
subAssOverride: string;
|
|
subScaleByWindow: boolean;
|
|
subUseMargins: boolean;
|
|
osdHeight: number;
|
|
osdDimensions: {
|
|
w: number;
|
|
h: number;
|
|
ml: number;
|
|
mr: number;
|
|
mt: number;
|
|
mb: number;
|
|
} | null;
|
|
}
|
|
|
|
export type OverlayLayer = 'visible';
|
|
|
|
export interface OverlayContentRect {
|
|
x: number;
|
|
y: number;
|
|
width: number;
|
|
height: number;
|
|
}
|
|
|
|
export interface OverlayContentMeasurement {
|
|
layer: OverlayLayer;
|
|
measuredAtMs: number;
|
|
viewport: {
|
|
width: number;
|
|
height: number;
|
|
};
|
|
contentRect: OverlayContentRect | null;
|
|
}
|
|
|
|
export interface MecabStatus {
|
|
available: boolean;
|
|
enabled: boolean;
|
|
path: string | null;
|
|
}
|
|
|
|
export interface ClipboardAppendResult {
|
|
ok: boolean;
|
|
message: string;
|
|
}
|
|
|
|
export interface ConfigHotReloadPayload {
|
|
keybindings: Keybinding[];
|
|
sessionBindings: CompiledSessionBinding[];
|
|
subtitleStyle: SubtitleStyleConfig | null;
|
|
subtitleSidebar: Required<SubtitleSidebarConfig>;
|
|
secondarySubMode: SecondarySubMode;
|
|
}
|
|
|
|
export interface SessionActionDispatchRequest {
|
|
actionId: SessionActionId;
|
|
payload?: SessionActionPayload;
|
|
}
|
|
|
|
export type ResolvedControllerConfig = ResolvedConfig['controller'];
|
|
|
|
export interface ElectronAPI {
|
|
getOverlayLayer: () => 'visible' | 'modal' | null;
|
|
onSubtitle: (callback: (data: SubtitleData) => void) => void;
|
|
onVisibility: (callback: (visible: boolean) => void) => void;
|
|
onSubtitlePosition: (callback: (position: SubtitlePosition | null) => void) => void;
|
|
getOverlayVisibility: () => Promise<boolean>;
|
|
getCurrentSubtitle: () => Promise<SubtitleData>;
|
|
getCurrentSubtitleRaw: () => Promise<string>;
|
|
getCurrentSubtitleAss: () => Promise<string>;
|
|
getSubtitleSidebarSnapshot: () => Promise<SubtitleSidebarSnapshot>;
|
|
getPlaybackPaused: () => Promise<boolean | null>;
|
|
onSubtitleAss: (callback: (assText: string) => void) => void;
|
|
setIgnoreMouseEvents: (ignore: boolean, options?: { forward?: boolean }) => void;
|
|
openYomitanSettings: () => void;
|
|
recordYomitanLookup: () => void;
|
|
getSubtitlePosition: () => Promise<SubtitlePosition | null>;
|
|
saveSubtitlePosition: (position: SubtitlePosition) => void;
|
|
getMecabStatus: () => Promise<MecabStatus>;
|
|
setMecabEnabled: (enabled: boolean) => void;
|
|
sendMpvCommand: (command: (string | number)[]) => void;
|
|
getKeybindings: () => Promise<Keybinding[]>;
|
|
getSessionBindings: () => Promise<CompiledSessionBinding[]>;
|
|
getConfiguredShortcuts: () => Promise<Required<ShortcutsConfig>>;
|
|
dispatchSessionAction: (actionId: SessionActionId, payload?: SessionActionPayload) => Promise<void>;
|
|
getStatsToggleKey: () => Promise<string>;
|
|
getMarkWatchedKey: () => Promise<string>;
|
|
markActiveVideoWatched: () => Promise<boolean>;
|
|
getControllerConfig: () => Promise<ResolvedControllerConfig>;
|
|
saveControllerConfig: (update: ControllerConfigUpdate) => Promise<void>;
|
|
saveControllerPreference: (update: ControllerPreferenceUpdate) => Promise<void>;
|
|
getJimakuMediaInfo: () => Promise<JimakuMediaInfo>;
|
|
jimakuSearchEntries: (query: JimakuSearchQuery) => Promise<JimakuApiResponse<JimakuEntry[]>>;
|
|
jimakuListFiles: (query: JimakuFilesQuery) => Promise<JimakuApiResponse<JimakuFileEntry[]>>;
|
|
jimakuDownloadFile: (query: JimakuDownloadQuery) => Promise<JimakuDownloadResult>;
|
|
quitApp: () => void;
|
|
toggleDevTools: () => void;
|
|
toggleOverlay: () => void;
|
|
toggleStatsOverlay: () => void;
|
|
getAnkiConnectStatus: () => Promise<boolean>;
|
|
setAnkiConnectEnabled: (enabled: boolean) => void;
|
|
clearAnkiConnectHistory: () => void;
|
|
onSecondarySub: (callback: (text: string) => void) => void;
|
|
onSecondarySubMode: (callback: (mode: SecondarySubMode) => void) => void;
|
|
getSecondarySubMode: () => Promise<SecondarySubMode>;
|
|
getCurrentSecondarySub: () => Promise<string>;
|
|
focusMainWindow: () => Promise<void>;
|
|
getSubtitleStyle: () => Promise<SubtitleStyleConfig | null>;
|
|
onSubsyncManualOpen: (callback: (payload: SubsyncManualPayload) => void) => void;
|
|
runSubsyncManual: (request: SubsyncManualRunRequest) => Promise<SubsyncResult>;
|
|
onKikuFieldGroupingRequest: (callback: (data: KikuFieldGroupingRequestData) => void) => void;
|
|
kikuBuildMergePreview: (request: KikuMergePreviewRequest) => Promise<KikuMergePreviewResponse>;
|
|
kikuFieldGroupingRespond: (choice: KikuFieldGroupingChoice) => void;
|
|
getRuntimeOptions: () => Promise<RuntimeOptionState[]>;
|
|
setRuntimeOptionValue: (
|
|
id: RuntimeOptionId,
|
|
value: RuntimeOptionValue,
|
|
) => Promise<RuntimeOptionApplyResult>;
|
|
cycleRuntimeOption: (id: RuntimeOptionId, direction: 1 | -1) => Promise<RuntimeOptionApplyResult>;
|
|
onRuntimeOptionsChanged: (callback: (options: RuntimeOptionState[]) => void) => void;
|
|
onOpenRuntimeOptions: (callback: () => void) => void;
|
|
onOpenSessionHelp: (callback: () => void) => void;
|
|
onOpenControllerSelect: (callback: () => void) => void;
|
|
onOpenControllerDebug: (callback: () => void) => void;
|
|
onOpenJimaku: (callback: () => void) => void;
|
|
onOpenYoutubeTrackPicker: (callback: (payload: YoutubePickerOpenPayload) => void) => void;
|
|
onOpenPlaylistBrowser: (callback: () => void) => void;
|
|
onSubtitleSidebarToggle: (callback: () => void) => void;
|
|
onCancelYoutubeTrackPicker: (callback: () => void) => void;
|
|
onKeyboardModeToggleRequested: (callback: () => void) => void;
|
|
onLookupWindowToggleRequested: (callback: () => void) => void;
|
|
appendClipboardVideoToQueue: () => Promise<ClipboardAppendResult>;
|
|
getPlaylistBrowserSnapshot: () => Promise<PlaylistBrowserSnapshot>;
|
|
appendPlaylistBrowserFile: (path: string) => Promise<PlaylistBrowserMutationResult>;
|
|
playPlaylistBrowserIndex: (index: number) => Promise<PlaylistBrowserMutationResult>;
|
|
removePlaylistBrowserIndex: (index: number) => Promise<PlaylistBrowserMutationResult>;
|
|
movePlaylistBrowserIndex: (
|
|
index: number,
|
|
direction: 1 | -1,
|
|
) => Promise<PlaylistBrowserMutationResult>;
|
|
youtubePickerResolve: (
|
|
request: YoutubePickerResolveRequest,
|
|
) => Promise<YoutubePickerResolveResult>;
|
|
notifyOverlayModalClosed: (
|
|
modal:
|
|
| 'runtime-options'
|
|
| 'subsync'
|
|
| 'jimaku'
|
|
| 'youtube-track-picker'
|
|
| 'playlist-browser'
|
|
| 'kiku'
|
|
| 'controller-select'
|
|
| 'controller-debug'
|
|
| 'subtitle-sidebar'
|
|
| 'session-help',
|
|
) => void;
|
|
notifyOverlayModalOpened: (
|
|
modal:
|
|
| 'runtime-options'
|
|
| 'subsync'
|
|
| 'jimaku'
|
|
| 'youtube-track-picker'
|
|
| 'playlist-browser'
|
|
| 'kiku'
|
|
| 'controller-select'
|
|
| 'controller-debug'
|
|
| 'subtitle-sidebar'
|
|
| 'session-help',
|
|
) => void;
|
|
reportOverlayContentBounds: (measurement: OverlayContentMeasurement) => void;
|
|
onConfigHotReload: (callback: (payload: ConfigHotReloadPayload) => void) => void;
|
|
}
|
|
|
|
declare global {
|
|
interface Window {
|
|
electronAPI: ElectronAPI;
|
|
}
|
|
}
|