mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-06-10 15:13:32 -07:00
feat(notifications): add overlay notifications with position config
- Add Catppuccin Macchiato overlay notification stack with 3s transient timeout - Add `notifications.overlayPosition` config (top-left | top | top-right) - Route startup tokenization and subtitle annotation status through configured surfaces - Deduplicate rapid subtitle mode toggle notifications - Change `both` to mean overlay + system; add `osd-system` as legacy alias for old behavior - Keep `osd`/`osd-system` as config-file-only legacy values; Settings UI offers overlay/system/both/none
This commit is contained in:
+2
-1
@@ -1,4 +1,5 @@
|
||||
import type { AiFeatureConfig } from './integrations';
|
||||
import type { NotificationType } from './notification';
|
||||
import type { NPlusOneMatchMode } from './subtitle';
|
||||
|
||||
export interface NotificationOptions {
|
||||
@@ -94,7 +95,7 @@ export interface AnkiConnectConfig {
|
||||
overwriteImage?: boolean;
|
||||
mediaInsertMode?: 'append' | 'prepend';
|
||||
highlightWord?: boolean;
|
||||
notificationType?: 'osd' | 'system' | 'both' | 'none';
|
||||
notificationType?: NotificationType;
|
||||
autoUpdateNewCards?: boolean;
|
||||
};
|
||||
metadata?: {
|
||||
|
||||
+9
-2
@@ -36,6 +36,7 @@ import type {
|
||||
SubtitleSidebarConfig,
|
||||
SubtitleStyleConfig,
|
||||
} from './subtitle';
|
||||
import type { NotificationType, OverlayNotificationPosition } from './notification';
|
||||
|
||||
export interface WebSocketConfig {
|
||||
enabled?: boolean | 'auto';
|
||||
@@ -83,7 +84,7 @@ export interface StartupWarmupsConfig {
|
||||
jellyfinRemoteSession?: boolean;
|
||||
}
|
||||
|
||||
export type UpdateNotificationType = 'system' | 'osd' | 'both' | 'none';
|
||||
export type UpdateNotificationType = NotificationType;
|
||||
export type UpdateChannel = 'stable' | 'prerelease';
|
||||
|
||||
export interface UpdatesConfig {
|
||||
@@ -93,6 +94,10 @@ export interface UpdatesConfig {
|
||||
channel?: UpdateChannel;
|
||||
}
|
||||
|
||||
export interface NotificationsConfig {
|
||||
overlayPosition?: OverlayNotificationPosition;
|
||||
}
|
||||
|
||||
export type LogRotation = number;
|
||||
|
||||
export interface LogFilesConfig {
|
||||
@@ -149,6 +154,7 @@ export interface Config {
|
||||
immersionTracking?: ImmersionTrackingConfig;
|
||||
stats?: StatsConfig;
|
||||
updates?: UpdatesConfig;
|
||||
notifications?: NotificationsConfig;
|
||||
logging?: {
|
||||
level?: 'debug' | 'info' | 'warn' | 'error';
|
||||
rotation?: LogRotation;
|
||||
@@ -247,7 +253,7 @@ export interface ResolvedConfig {
|
||||
overwriteImage: boolean;
|
||||
mediaInsertMode: 'append' | 'prepend';
|
||||
highlightWord: boolean;
|
||||
notificationType: 'osd' | 'system' | 'both' | 'none';
|
||||
notificationType: NotificationType;
|
||||
autoUpdateNewCards: boolean;
|
||||
};
|
||||
metadata: {
|
||||
@@ -379,6 +385,7 @@ export interface ResolvedConfig {
|
||||
autoOpenBrowser: boolean;
|
||||
};
|
||||
updates: Required<UpdatesConfig>;
|
||||
notifications: Required<NotificationsConfig>;
|
||||
logging: {
|
||||
level: 'debug' | 'info' | 'warn' | 'error';
|
||||
rotation: LogRotation;
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
export const SETTINGS_NOTIFICATION_TYPE_VALUES = ['overlay', 'system', 'both', 'none'] as const;
|
||||
|
||||
export const NOTIFICATION_TYPE_VALUES = [
|
||||
...SETTINGS_NOTIFICATION_TYPE_VALUES,
|
||||
'osd',
|
||||
'osd-system',
|
||||
] as const;
|
||||
|
||||
export const OVERLAY_NOTIFICATION_POSITION_VALUES = ['top-left', 'top', 'top-right'] as const;
|
||||
|
||||
export type SettingsNotificationType = (typeof SETTINGS_NOTIFICATION_TYPE_VALUES)[number];
|
||||
export type NotificationType = (typeof NOTIFICATION_TYPE_VALUES)[number];
|
||||
export type OverlayNotificationPosition = (typeof OVERLAY_NOTIFICATION_POSITION_VALUES)[number];
|
||||
|
||||
export type OverlayNotificationVariant = 'info' | 'success' | 'warning' | 'error' | 'progress';
|
||||
|
||||
export interface OverlayNotificationAction {
|
||||
id: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface OverlayNotificationPayload {
|
||||
id?: string;
|
||||
title: string;
|
||||
body?: string;
|
||||
variant?: OverlayNotificationVariant;
|
||||
position?: OverlayNotificationPosition;
|
||||
persistent?: boolean;
|
||||
timeoutMs?: number;
|
||||
actions?: OverlayNotificationAction[];
|
||||
}
|
||||
|
||||
export interface OverlayNotificationDismissPayload {
|
||||
id: string;
|
||||
dismiss: true;
|
||||
}
|
||||
|
||||
export type OverlayNotificationEventPayload =
|
||||
| OverlayNotificationPayload
|
||||
| OverlayNotificationDismissPayload;
|
||||
|
||||
export function isNotificationType(value: unknown): value is NotificationType {
|
||||
return typeof value === 'string' && NOTIFICATION_TYPE_VALUES.includes(value as NotificationType);
|
||||
}
|
||||
|
||||
export function isOverlayNotificationPosition(
|
||||
value: unknown,
|
||||
): value is OverlayNotificationPosition {
|
||||
return (
|
||||
typeof value === 'string' &&
|
||||
OVERLAY_NOTIFICATION_POSITION_VALUES.includes(value as OverlayNotificationPosition)
|
||||
);
|
||||
}
|
||||
@@ -41,6 +41,7 @@ import type {
|
||||
RuntimeOptionState,
|
||||
RuntimeOptionValue,
|
||||
} from './runtime-options';
|
||||
import type { OverlayNotificationEventPayload } from './notification';
|
||||
|
||||
export interface WindowGeometry {
|
||||
x: number;
|
||||
@@ -405,6 +406,8 @@ export interface ElectronAPI {
|
||||
getOverlayLayer: () => 'visible' | 'modal' | null;
|
||||
onSubtitle: (callback: (data: SubtitleData) => void) => void;
|
||||
onOverlayPointerRecoveryRequested: (callback: () => void) => void;
|
||||
onOverlayNotification: (callback: (payload: OverlayNotificationEventPayload) => void) => void;
|
||||
sendOverlayNotificationAction?: (notificationId: string, actionId: string) => void;
|
||||
onVisibility: (callback: (visible: boolean) => void) => void;
|
||||
onSubtitlePosition: (callback: (position: SubtitlePosition | null) => void) => void;
|
||||
getOverlayVisibility: () => Promise<boolean>;
|
||||
|
||||
Reference in New Issue
Block a user