mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-07-07 13:08:54 -07:00
feat(notifications): add overlay notifications with position config (#110)
This commit is contained in:
@@ -53,6 +53,11 @@ export interface IpcServiceDeps {
|
||||
interactive: boolean,
|
||||
senderWindow: ElectronBrowserWindow | null,
|
||||
) => void;
|
||||
handleOverlayNotificationAction?: (
|
||||
notificationId: string,
|
||||
actionId: string,
|
||||
noteId?: number,
|
||||
) => void | Promise<void>;
|
||||
openYomitanSettings: () => void;
|
||||
quitApp: () => void;
|
||||
toggleDevTools: () => void;
|
||||
@@ -80,6 +85,7 @@ export interface IpcServiceDeps {
|
||||
dispatchSessionAction?: (request: SessionActionDispatchRequest) => void | Promise<void>;
|
||||
getStatsToggleKey: () => string;
|
||||
getMarkWatchedKey: () => string;
|
||||
getOverlayNotificationPosition: () => string;
|
||||
getControllerConfig: () => ResolvedControllerConfig;
|
||||
saveControllerConfig: (update: ControllerConfigUpdate) => void | Promise<void>;
|
||||
saveControllerPreference: (update: ControllerPreferenceUpdate) => void | Promise<void>;
|
||||
@@ -223,6 +229,25 @@ function parseSubtitleMiningContext(payload: unknown): SubtitleMiningContext | n
|
||||
return parsed;
|
||||
}
|
||||
|
||||
function parseOverlayNotificationActionPayload(
|
||||
payload: unknown,
|
||||
): { notificationId: string; actionId: string; noteId?: number } | null {
|
||||
if (!payload || typeof payload !== 'object') return null;
|
||||
const record = payload as Record<string, unknown>;
|
||||
const notificationId = record.notificationId;
|
||||
const actionId = record.actionId;
|
||||
const noteId = record.noteId;
|
||||
if (typeof notificationId !== 'string' || notificationId.trim().length === 0) return null;
|
||||
if (typeof actionId !== 'string' || actionId.trim().length === 0) return null;
|
||||
if (
|
||||
noteId !== undefined &&
|
||||
(typeof noteId !== 'number' || !Number.isInteger(noteId) || noteId <= 0)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return { notificationId, actionId, ...(typeof noteId === 'number' ? { noteId } : {}) };
|
||||
}
|
||||
|
||||
export interface IpcDepsRuntimeOptions {
|
||||
getMainWindow: () => WindowLike | null;
|
||||
getVisibleOverlayVisibility: () => boolean;
|
||||
@@ -242,6 +267,11 @@ export interface IpcDepsRuntimeOptions {
|
||||
interactive: boolean,
|
||||
senderWindow: ElectronBrowserWindow | null,
|
||||
) => void;
|
||||
handleOverlayNotificationAction?: (
|
||||
notificationId: string,
|
||||
actionId: string,
|
||||
noteId?: number,
|
||||
) => void | Promise<void>;
|
||||
openYomitanSettings: () => void;
|
||||
quitApp: () => void;
|
||||
toggleVisibleOverlay: () => void;
|
||||
@@ -262,6 +292,7 @@ export interface IpcDepsRuntimeOptions {
|
||||
dispatchSessionAction?: (request: SessionActionDispatchRequest) => void | Promise<void>;
|
||||
getStatsToggleKey: () => string;
|
||||
getMarkWatchedKey: () => string;
|
||||
getOverlayNotificationPosition: () => string;
|
||||
getControllerConfig: () => ResolvedControllerConfig;
|
||||
saveControllerConfig: (update: ControllerConfigUpdate) => void | Promise<void>;
|
||||
saveControllerPreference: (update: ControllerPreferenceUpdate) => void | Promise<void>;
|
||||
@@ -312,6 +343,7 @@ export function createIpcDepsRuntime(options: IpcDepsRuntimeOptions): IpcService
|
||||
onOverlayModalOpened: options.onOverlayModalOpened,
|
||||
onOverlayMouseInteractionChanged: options.onOverlayMouseInteractionChanged,
|
||||
onOverlayInteractiveHint: options.onOverlayInteractiveHint,
|
||||
handleOverlayNotificationAction: options.handleOverlayNotificationAction,
|
||||
openYomitanSettings: options.openYomitanSettings,
|
||||
recordSubtitleMiningContext: options.recordSubtitleMiningContext,
|
||||
quitApp: options.quitApp,
|
||||
@@ -349,6 +381,7 @@ export function createIpcDepsRuntime(options: IpcDepsRuntimeOptions): IpcService
|
||||
dispatchSessionAction: options.dispatchSessionAction ?? (async () => {}),
|
||||
getStatsToggleKey: options.getStatsToggleKey,
|
||||
getMarkWatchedKey: options.getMarkWatchedKey,
|
||||
getOverlayNotificationPosition: options.getOverlayNotificationPosition,
|
||||
getControllerConfig: options.getControllerConfig,
|
||||
saveControllerConfig: options.saveControllerConfig,
|
||||
saveControllerPreference: options.saveControllerPreference,
|
||||
@@ -473,6 +506,22 @@ export function registerIpcHandlers(deps: IpcServiceDeps, ipc: IpcMainRegistrar
|
||||
electron.BrowserWindow?.fromWebContents((event as IpcMainEvent).sender) ?? null;
|
||||
deps.onOverlayModalOpened(parsedModal, senderWindow);
|
||||
});
|
||||
ipc.on(IPC_CHANNELS.command.overlayNotificationAction, (_event: unknown, payload: unknown) => {
|
||||
const parsedPayload = parseOverlayNotificationActionPayload(payload);
|
||||
if (!parsedPayload) return;
|
||||
void Promise.resolve(
|
||||
deps.handleOverlayNotificationAction?.(
|
||||
parsedPayload.notificationId,
|
||||
parsedPayload.actionId,
|
||||
parsedPayload.noteId,
|
||||
),
|
||||
).catch((error) => {
|
||||
console.warn(
|
||||
'Failed to handle overlay notification action:',
|
||||
error instanceof Error ? error.message : String(error),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
ipc.handle(
|
||||
IPC_CHANNELS.request.youtubePickerResolve,
|
||||
@@ -641,6 +690,10 @@ export function registerIpcHandlers(deps: IpcServiceDeps, ipc: IpcMainRegistrar
|
||||
return deps.getMarkWatchedKey();
|
||||
});
|
||||
|
||||
ipc.handle(IPC_CHANNELS.request.getOverlayNotificationPosition, () => {
|
||||
return deps.getOverlayNotificationPosition();
|
||||
});
|
||||
|
||||
ipc.handle(IPC_CHANNELS.request.getControllerConfig, () => {
|
||||
return deps.getControllerConfig();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user