From b71c42c25b3833d3df0e8b8ab949a13be118bcae Mon Sep 17 00:00:00 2001 From: bennybrainless <242895261+bennybrainless@users.noreply.github.com> Date: Thu, 20 Nov 2025 23:21:07 -0600 Subject: [PATCH] Add configurable notification toast duration --- discord/server/setupSettings.ts | 18 ++-- discord/shared/types/discord.ts | 137 ++++++++++++------------ discord/src/overlays/OverlayWrapper.tsx | 2 + discord/src/stores/uiStore.ts | 3 + discord/src/utils/settingValidator.ts | 1 + 5 files changed, 87 insertions(+), 74 deletions(-) diff --git a/discord/server/setupSettings.ts b/discord/server/setupSettings.ts index b69a8e0..dfc7ac5 100644 --- a/discord/server/setupSettings.ts +++ b/discord/server/setupSettings.ts @@ -179,14 +179,6 @@ export const setupSettings = () => { }, ], }, - [AppSettingIDs.NOTIFICATION_TOASTS]: { - id: AppSettingIDs.NOTIFICATION_TOASTS, - type: SETTING_TYPES.BOOLEAN, - version: "0.11.7", - description: "Show floating notification toasts on the dashboard", - label: "Notification Toasts", - value: true, - }, [AppSettingIDs.SCROLL_TO_BOTTOM]: { id: AppSettingIDs.SCROLL_TO_BOTTOM, type: SETTING_TYPES.BOOLEAN, @@ -213,6 +205,16 @@ export const setupSettings = () => { label: "Notification Toasts", value: true, }, + [AppSettingIDs.NOTIFICATION_TOAST_DURATION_SECONDS]: { + id: AppSettingIDs.NOTIFICATION_TOAST_DURATION_SECONDS, + type: SETTING_TYPES.NUMBER, + version: "0.11.14", + description: "How long notification toasts stay visible (in seconds)", + label: "Notification Toast Duration", + value: 10, + min: 1, + max: 60, + }, [AppSettingIDs.CONTROLS_ORDER]: { id: AppSettingIDs.CONTROLS_ORDER, type: SETTING_TYPES.RANKED, diff --git a/discord/shared/types/discord.ts b/discord/shared/types/discord.ts index 318c687..1a54bfc 100644 --- a/discord/shared/types/discord.ts +++ b/discord/shared/types/discord.ts @@ -1,4 +1,4 @@ -import { SETTING_TYPES, SettingsBoolean, SettingsColor, SettingsMultiSelect, SettingsRanked, SettingsSelect, SettingsString } from "@deskthing/types"; +import { SETTING_TYPES, SettingsBoolean, SettingsColor, SettingsMultiSelect, SettingsNumber, SettingsRanked, SettingsSelect, SettingsString } from "@deskthing/types"; export interface CallStatus { channelId: string | null; @@ -61,7 +61,7 @@ export interface NotificationStatus { } export interface Notification { id: string; - title: string + title: string; channelId: string; channelName?: string; guildName?: string; @@ -95,83 +95,84 @@ export interface GuildListStatus { } export type DMListStatus = { - selectedDMId: string | null - dms: DMStatus[] - channels: ChannelStatus[] -} + selectedDMId: string | null; + dms: DMStatus[]; + channels: ChannelStatus[]; +}; export type DMStatus = { - id: string -} + id: string; +}; export enum DISCORD_ACTIONS { - MUTE = 'mute', - DEAFEN = 'deafen', - DISCONNECT = 'disconnect', - REAUTH = 'reauth', - REPRESENCE = 'represence', - EXPAND_CHAT = 'expandChat', - COLLAPSE_CHAT = 'collapseChat', - SELECT_TEXT_CHANNEL = 'selectTextChannel', - MARK_NOTIFICATION_AS_READ = 'markNotificationAsRead', - MARK_ALL_NOTIFICATIONS_AS_READ = 'markAllNotificationsAsRead', - SEND_TEST_NOTIFICATION = 'sendTestNotification', + MUTE = "mute", + DEAFEN = "deafen", + DISCONNECT = "disconnect", + REAUTH = "reauth", + REPRESENCE = "represence", + EXPAND_CHAT = "expandChat", + COLLAPSE_CHAT = "collapseChat", + SELECT_TEXT_CHANNEL = "selectTextChannel", + MARK_NOTIFICATION_AS_READ = "markNotificationAsRead", + MARK_ALL_NOTIFICATIONS_AS_READ = "markAllNotificationsAsRead", + SEND_TEST_NOTIFICATION = "sendTestNotification", } export enum AppSettingIDs { - CLIENT_ID = 'client_id', - CLIENT_SECRET = 'client_secret', - REDIRECT_URL = 'redirect_url', - RICH_PRESENCE = 'rich_presence', - SET_MAIN_TEXT = 'set_main_text', - SET_SECONDARY_TEXT = 'set_secondary_text', - HAVE_TIMER = 'have_timer', - LEFT_DASHBOARD_PANEL = 'left_dashboard_panel', - RIGHT_DASHBOARD_PANEL = 'right_dashboard_panel', - DASHBOARD_ELEMENTS = 'dashboard_elements', - SCROLL_TO_BOTTOM = 'scroll_to_bottom', - NOTIFICATION_TOASTS = 'notification_toasts', - CONTROLS_ORDER = 'controls_order', - SPEAKING_COLOR = 'speaking_color', - CLOCK_OPTIONS = 'clock_options', - SONG_OPTIONS = 'song_options' + CLIENT_ID = "client_id", + CLIENT_SECRET = "client_secret", + REDIRECT_URL = "redirect_url", + RICH_PRESENCE = "rich_presence", + SET_MAIN_TEXT = "set_main_text", + SET_SECONDARY_TEXT = "set_secondary_text", + HAVE_TIMER = "have_timer", + LEFT_DASHBOARD_PANEL = "left_dashboard_panel", + RIGHT_DASHBOARD_PANEL = "right_dashboard_panel", + DASHBOARD_ELEMENTS = "dashboard_elements", + SCROLL_TO_BOTTOM = "scroll_to_bottom", + NOTIFICATION_TOASTS = "notification_toasts", + NOTIFICATION_TOAST_DURATION_SECONDS = "notification_toast_duration_seconds", + CONTROLS_ORDER = "controls_order", + SPEAKING_COLOR = "speaking_color", + CLOCK_OPTIONS = "clock_options", + SONG_OPTIONS = "song_options", } export enum PANEL_ELEMENTS { - CALL_STATUS = 'call_status', - GUILD_LIST = 'guild_list', - CHAT = 'chat', - SONG = 'song', - CLOCK = 'clock', - BLANK = 'blank' + CALL_STATUS = "call_status", + GUILD_LIST = "guild_list", + CHAT = "chat", + SONG = "song", + CLOCK = "clock", + BLANK = "blank", } export enum DASHBOARD_ELEMENTS { - MINI_CALL = 'mini_call', - CALL_CONTROLS = 'call_controls', - NOTIFICATIONS = 'notifications', - BG_ALBUM = 'bg_album' + MINI_CALL = "mini_call", + CALL_CONTROLS = "call_controls", + NOTIFICATIONS = "notifications", + BG_ALBUM = "bg_album", } export enum CONTROL_OPTIONS { - MUTE = 'mute', - DEAFEN = 'deafen', - DISCONNECT = 'disconnect' + MUTE = "mute", + DEAFEN = "deafen", + DISCONNECT = "disconnect", } export enum CLOCK_OPTIONS { - TOP_LEFT = 'top_left', - TOP_RIGHT = 'top_right', - TOP_CENTER = 'top_center', - CUSTOM = 'custom', - DISABLED = 'disabled' + TOP_LEFT = "top_left", + TOP_RIGHT = "top_right", + TOP_CENTER = "top_center", + CUSTOM = "custom", + DISABLED = "disabled", } export enum SONG_CONTROLS { - DISABLED = 'disabled', - FREE = 'free', - TOP = 'top', - BOTTOM = 'bottom', + DISABLED = "disabled", + FREE = "free", + TOP = "top", + BOTTOM = "bottom", } type SelectSetting = SettingsSelect & { @@ -191,17 +192,21 @@ type SelectClockOptions = SettingsSelect & { id: AppSettingIDs.CLOCK_OPTIONS; value: CLOCK_OPTIONS; options: { value: CLOCK_OPTIONS; label: string }[]; -} +}; type SelectSongOptions = SettingsSelect & { id: AppSettingIDs.SONG_OPTIONS; value: SONG_CONTROLS; options: { value: SONG_CONTROLS; label: string }[]; -} +}; type NotificationToastSetting = SettingsBoolean & { id: AppSettingIDs.NOTIFICATION_TOASTS; -} +}; + +type NotificationToastDurationSetting = SettingsNumber & { + id: AppSettingIDs.NOTIFICATION_TOAST_DURATION_SECONDS; +}; type OrderSettings = SettingsRanked & { id: AppSettingIDs.CONTROLS_ORDER; @@ -217,14 +222,14 @@ export type DiscordSettings = { // [AppSettingIDs.SET_MAIN_TEXT]: SettingsString & { id: AppSettingIDs.SET_MAIN_TEXT }; // [AppSettingIDs.SET_SECONDARY_TEXT]: SettingsString & { id: AppSettingIDs.SET_SECONDARY_TEXT }; // [AppSettingIDs.HAVE_TIMER]: SettingsBoolean & { id: AppSettingIDs.HAVE_TIMER }; - [AppSettingIDs.LEFT_DASHBOARD_PANEL]: SelectSetting & { id: AppSettingIDs.LEFT_DASHBOARD_PANEL, value: PANEL_ELEMENTS }; - [AppSettingIDs.RIGHT_DASHBOARD_PANEL]: SelectSetting & { id: AppSettingIDs.RIGHT_DASHBOARD_PANEL, value: PANEL_ELEMENTS }; - [AppSettingIDs.DASHBOARD_ELEMENTS]: MultiSelectSetting & { id: AppSettingIDs.DASHBOARD_ELEMENTS, value: DASHBOARD_ELEMENTS[] }; + [AppSettingIDs.LEFT_DASHBOARD_PANEL]: SelectSetting & { id: AppSettingIDs.LEFT_DASHBOARD_PANEL; value: PANEL_ELEMENTS }; + [AppSettingIDs.RIGHT_DASHBOARD_PANEL]: SelectSetting & { id: AppSettingIDs.RIGHT_DASHBOARD_PANEL; value: PANEL_ELEMENTS }; + [AppSettingIDs.DASHBOARD_ELEMENTS]: MultiSelectSetting & { id: AppSettingIDs.DASHBOARD_ELEMENTS; value: DASHBOARD_ELEMENTS[] }; [AppSettingIDs.SCROLL_TO_BOTTOM]: SettingsBoolean & { id: AppSettingIDs.SCROLL_TO_BOTTOM }; - [AppSettingIDs.NOTIFICATION_TOASTS]: SettingsBoolean & { id: AppSettingIDs.NOTIFICATION_TOASTS }; + [AppSettingIDs.NOTIFICATION_TOASTS]: NotificationToastSetting & { id: AppSettingIDs.NOTIFICATION_TOASTS }; + [AppSettingIDs.NOTIFICATION_TOAST_DURATION_SECONDS]: NotificationToastDurationSetting & { id: AppSettingIDs.NOTIFICATION_TOAST_DURATION_SECONDS }; [AppSettingIDs.CONTROLS_ORDER]: OrderSettings & { id: AppSettingIDs.CONTROLS_ORDER }; [AppSettingIDs.SPEAKING_COLOR]: SettingsColor & { id: AppSettingIDs.SPEAKING_COLOR }; [AppSettingIDs.CLOCK_OPTIONS]: SelectClockOptions & { id: AppSettingIDs.CLOCK_OPTIONS }; [AppSettingIDs.SONG_OPTIONS]: SelectSongOptions & { id: AppSettingIDs.SONG_OPTIONS }; - [AppSettingIDs.NOTIFICATION_TOASTS]: NotificationToastSetting & { id: AppSettingIDs.NOTIFICATION_TOASTS }; -}; \ No newline at end of file +}; diff --git a/discord/src/overlays/OverlayWrapper.tsx b/discord/src/overlays/OverlayWrapper.tsx index 2f6eec0..dba0450 100644 --- a/discord/src/overlays/OverlayWrapper.tsx +++ b/discord/src/overlays/OverlayWrapper.tsx @@ -7,6 +7,7 @@ export default function OverlayWrapper() { const markNotificationAsRead = useChatStore((state) => state.markNotificationAsRead) const notifications = useChatStore((state) => state.notificationStatus?.notifications) const toastsEnabled = useUIStore((state) => state.notification_toasts_enabled) + const toastDurationSeconds = useUIStore((state) => state.notification_toast_duration_seconds) const unreadNotifications = useMemo(() => { if (!notifications) return [] @@ -30,6 +31,7 @@ export default function OverlayWrapper() { key={notification.id} notification={notification} onClose={markNotificationAsRead} + autoHideDuration={toastDurationSeconds * 1000} /> ))} diff --git a/discord/src/stores/uiStore.ts b/discord/src/stores/uiStore.ts index 08b7a75..b4c5f7c 100644 --- a/discord/src/stores/uiStore.ts +++ b/discord/src/stores/uiStore.ts @@ -38,6 +38,7 @@ type UIStore = { widgets: DASHBOARD_ELEMENTS[] clock_options: CLOCK_OPTIONS notification_toasts_enabled: boolean + notification_toast_duration_seconds: number dimensions: { width: number; @@ -120,6 +121,7 @@ export const useUIStore = create((set, get) => ({ widgets: [...defaultWidgets], clock_options: CLOCK_OPTIONS.DISABLED, notification_toasts_enabled: true, + notification_toast_duration_seconds: 10, dimensions: getInitialDimensions(), initialize: () => { @@ -173,6 +175,7 @@ export const useUIStore = create((set, get) => ({ widgets: settings[AppSettingIDs.DASHBOARD_ELEMENTS].value, song_controls: settings[AppSettingIDs.SONG_OPTIONS].value, notification_toasts_enabled: settings[AppSettingIDs.NOTIFICATION_TOASTS].value, + notification_toast_duration_seconds: settings[AppSettingIDs.NOTIFICATION_TOAST_DURATION_SECONDS].value, settings: settings as DiscordSettings, }); } diff --git a/discord/src/utils/settingValidator.ts b/discord/src/utils/settingValidator.ts index b4bb668..6b2ae0a 100644 --- a/discord/src/utils/settingValidator.ts +++ b/discord/src/utils/settingValidator.ts @@ -9,6 +9,7 @@ export function validateDiscordSettings(obj: AppSettings): asserts obj is Discor AppSettingIDs.RIGHT_DASHBOARD_PANEL, AppSettingIDs.DASHBOARD_ELEMENTS, AppSettingIDs.NOTIFICATION_TOASTS, + AppSettingIDs.NOTIFICATION_TOAST_DURATION_SECONDS, ]; for (const id of requiredIds) {