From 35460ce2f4a38a400e6edf32a2c8d7387675fd1f Mon Sep 17 00:00:00 2001 From: "Grigorii K. Shartsev" Date: Mon, 3 Mar 2025 15:26:07 +0100 Subject: [PATCH 1/2] chore: fix TS errors Signed-off-by: Grigorii K. Shartsev --- src/talk/renderer/TitleBar/components/DevMenu.vue | 1 + src/talk/renderer/talk.main.ts | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/talk/renderer/TitleBar/components/DevMenu.vue b/src/talk/renderer/TitleBar/components/DevMenu.vue index 3cc4c1de9..b9b1fb3fc 100644 --- a/src/talk/renderer/TitleBar/components/DevMenu.vue +++ b/src/talk/renderer/TitleBar/components/DevMenu.vue @@ -21,6 +21,7 @@ import IconMessageBadgeOutline from 'vue-material-design-icons/MessageBadgeOutli import IconConsole from 'vue-material-design-icons/Console.vue' import { appData } from '../../../../app/AppData.js' +// @ts-expect-error appData is not typed yet const supportsTestAdminNotification = appData.capabilities?.notifications?.['admin-notifications']?.includes('ocs') && appData.userMetadata?.groups.includes('admin') const supportsTestPushNotification = appData.capabilities?.notifications?.['ocs-endpoints']?.includes('test-push') const supportsTestNotification = supportsTestPushNotification || supportsTestAdminNotification diff --git a/src/talk/renderer/talk.main.ts b/src/talk/renderer/talk.main.ts index 5ab0fa614..2cf4c7301 100644 --- a/src/talk/renderer/talk.main.ts +++ b/src/talk/renderer/talk.main.ts @@ -12,7 +12,6 @@ import 'regenerator-runtime' // TODO: Why isn't it added on bundling import { setupWebPage } from '../../shared/setupWebPage.js' import { createTalkDesktopApp } from './TalkDesktop.app.ts' -// Initially open the Welcome page, if not specified -await setupWebPage({ routeHash: '#/apps/spreed' }) +await setupWebPage() await createTalkDesktopApp() From 4ab29255a807a453d510d4ccbb73b3a151dd2cdb Mon Sep 17 00:00:00 2001 From: "Grigorii K. Shartsev" Date: Tue, 4 Mar 2025 20:45:49 +0100 Subject: [PATCH 2/2] fix(config): remove notification on dnd Signed-off-by: Grigorii K. Shartsev --- src/app/AppConfig.ts | 61 +++++++++++++------ .../Settings/DesktopSettingsSection.vue | 5 +- src/talk/renderer/Settings/appConfig.store.ts | 8 +-- .../notifications/notifications.store.js | 12 ++-- 4 files changed, 54 insertions(+), 32 deletions(-) diff --git a/src/app/AppConfig.ts b/src/app/AppConfig.ts index 97022f1c4..c58ae1e44 100644 --- a/src/app/AppConfig.ts +++ b/src/app/AppConfig.ts @@ -78,27 +78,19 @@ export type AppConfig = { /** * Whether to play a sound when a chat notification is received. - * Same as notifications.sound_notification initial state. - * - 'always': always play sound - * - 'respect-dnd': play sound only if user status is not Do-Not-Disturb [default] - * - 'never': disable notification sound + * Default: true, but ignored on Do-Not-Disturb. */ - playSoundChat: 'always' | 'respect-dnd' | 'never' + playSoundChat: boolean /** * Whether to play a sound when a call notification is received. - * Same as notifications.sound_talk initial state. - * - 'always': always play sound - * - 'respect-dnd': play sound only if user status is not Do-Not-Disturb [default] - * - 'never': disable notification sound + * Default: true, but ignored on Do-Not-Disturb. */ - playSoundCall: 'always' | 'respect-dnd' | 'never' + playSoundCall: boolean /** * Whether to show a popup when a call notification is received. - * - 'always': always show the popup - * - 'respect-dnd': show the popup only if user status is not Do-Not-Disturb [default] - * - 'never': disable the call popup + * Default: true, but ignored on Do-Not-Disturb. */ - enableCallbox: 'always' | 'respect-dnd' | 'never' + enableCallbox: boolean /** * Whether to play ring sound on secondary speaker when a call notification is received. */ @@ -120,9 +112,9 @@ const defaultAppConfig: AppConfig = { systemTitleBar: isLinux, monochromeTrayIcon: isMac, zoomFactor: 1, - playSoundChat: 'respect-dnd', - playSoundCall: 'respect-dnd', - enableCallbox: 'respect-dnd', + playSoundChat: true, + playSoundCall: true, + enableCallbox: true, secondarySpeaker: false, secondarySpeakerDevice: null, } @@ -167,11 +159,44 @@ async function writeAppConfigFile(config: Partial) { } } +/** + * Validate the application config by removing unknown properties and properties with invalid values + * @param config - Config to validate + */ +function validateAppConfig(config: unknown): Partial { + if (typeof config !== 'object' || config === null) { + return {} + } + // Remove unknown keys + for (const key in config) { + if (!(key in defaultAppConfig)) { + delete config[key as keyof typeof config] + } + } + // Validate values + const booleanProperties: AppConfigKey[] = ['launchAtStartup', 'systemTitleBar', 'monochromeTrayIcon', 'playSoundChat', 'playSoundCall', 'enableCallbox', 'secondarySpeaker'] + for (const key of booleanProperties) { + if (typeof config[key as keyof typeof config] !== 'boolean') { + delete config[key as keyof typeof config] + } + } + if ('zoomFactor' in config && typeof config.zoomFactor !== 'number') { + delete config.zoomFactor + } + if ('theme' in config && !['default', 'dark', 'light'].includes(config.theme as AppConfig['theme'])) { + delete config.theme + } + if ('secondarySpeakerDevice' in config && typeof config.secondarySpeakerDevice !== 'string' && config.secondarySpeakerDevice !== null) { + delete config.secondarySpeakerDevice + } + return config +} + /** * Load the application config into the application memory */ export async function loadAppConfig() { - const config = await readAppConfigFile() + const config = validateAppConfig(await readAppConfigFile()) Object.assign(appConfig, config) initialized = true } diff --git a/src/talk/renderer/Settings/DesktopSettingsSection.vue b/src/talk/renderer/Settings/DesktopSettingsSection.vue index 312456053..639cd303e 100644 --- a/src/talk/renderer/Settings/DesktopSettingsSection.vue +++ b/src/talk/renderer/Settings/DesktopSettingsSection.vue @@ -67,9 +67,8 @@ const zoomHint = t('talk_desktop', 'Zoom can be also changed by {key} or mouse w }, undefined, { escape: false }) const generalNotificationOptions = [ - { label: t('talk_desktop', 'Always'), value: 'always' } as const, - { label: t('talk_desktop', 'When not in "Do not disturb"'), value: 'respect-dnd' } as const, - { label: t('talk_desktop', 'Never'), value: 'never' } as const, + { label: t('talk_desktop', 'When not in "Do not disturb"'), value: true } as const, + { label: t('talk_desktop', 'Never'), value: false } as const, ] const playSoundChat = useAppConfigValue('playSoundChat') diff --git a/src/talk/renderer/Settings/appConfig.store.ts b/src/talk/renderer/Settings/appConfig.store.ts index 5b536d668..f25b2dae0 100644 --- a/src/talk/renderer/Settings/appConfig.store.ts +++ b/src/talk/renderer/Settings/appConfig.store.ts @@ -30,12 +30,8 @@ export const useAppConfigStore = defineStore('appConfig', () => { const userStatusStore = useUserStatusStore() watchEffect(() => { - const playSoundChat = appConfig.value.playSoundChat === 'respect-dnd' - ? userStatusStore.userStatus?.status !== 'dnd' - : appConfig.value.playSoundChat === 'always' - const playSoundCall = appConfig.value.playSoundCall === 'respect-dnd' - ? userStatusStore.userStatus?.status !== 'dnd' - : appConfig.value.playSoundCall === 'always' + const playSoundChat = appConfig.value.playSoundChat && userStatusStore.userStatus?.status !== 'dnd' + const playSoundCall = appConfig.value.playSoundCall && userStatusStore.userStatus?.status !== 'dnd' setInitialState('notifications', 'sound_notification', playSoundChat) setInitialState('notifications', 'sound_talk', playSoundCall) }) diff --git a/src/talk/renderer/notifications/notifications.store.js b/src/talk/renderer/notifications/notifications.store.js index 7a7342fdf..70c198e61 100644 --- a/src/talk/renderer/notifications/notifications.store.js +++ b/src/talk/renderer/notifications/notifications.store.js @@ -166,12 +166,14 @@ export function createNotificationStore() { return } - const isNotificationFromPendingCall = notification.objectType === 'call' - && await checkCurrentUserHasPendingCall(notification.objectId) - const enableCallboxConfig = getAppConfigValue('enableCallbox') - const shouldShowCallPopup = isNotificationFromPendingCall - && (enableCallboxConfig === 'always' || (enableCallboxConfig === 'respect-dnd' && !userStatusStore.isDnd)) + const callboxEnabled = enableCallboxConfig && !userStatusStore.isDnd + const isCallNotification = notification.objectType === 'call' + + // Check for pending call only as the last check to avoid unnecessary requests + const shouldShowCallPopup = isCallNotification + && callboxEnabled + && await checkCurrentUserHasPendingCall(notification.objectId) if (shouldShowCallPopup) { const params = {