From 1ed0104b48b334e6eb37d1bc04322fa72010df8d Mon Sep 17 00:00:00 2001 From: Ruizhe Pang Date: Tue, 22 Apr 2025 22:02:40 +0800 Subject: [PATCH 01/10] Make the notification volume adjustable --- src/renderer/__mocks__/state-mocks.ts | 1 + .../settings/NotificationSettings.tsx | 20 +++++++++++++ src/renderer/context/App.tsx | 1 + src/renderer/types.ts | 1 + .../utils/notifications/native.test.ts | 29 +++++++++++++++++++ src/renderer/utils/notifications/native.ts | 6 ++-- 6 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/renderer/__mocks__/state-mocks.ts b/src/renderer/__mocks__/state-mocks.ts index a12d6ce96..ee6cb1c93 100644 --- a/src/renderer/__mocks__/state-mocks.ts +++ b/src/renderer/__mocks__/state-mocks.ts @@ -93,6 +93,7 @@ const mockNotificationSettings: NotificationSettingsState = { markAsDoneOnOpen: false, markAsDoneOnUnsubscribe: false, delayNotificationState: false, + notificationVolume: 20, }; const mockSystemSettings: SystemSettingsState = { diff --git a/src/renderer/components/settings/NotificationSettings.tsx b/src/renderer/components/settings/NotificationSettings.tsx index 78aaae595..a81c2cb84 100644 --- a/src/renderer/components/settings/NotificationSettings.tsx +++ b/src/renderer/components/settings/NotificationSettings.tsx @@ -246,6 +246,26 @@ export const NotificationSettings: FC = () => { } /> + + + + Notification Volume: {settings.notificationVolume}% + + + updateSetting( + 'notificationVolume', + Number.parseInt(evt.target.value, 10), + ) + } + /> + ); diff --git a/src/renderer/context/App.tsx b/src/renderer/context/App.tsx index d3421e6c2..e41d55ac7 100644 --- a/src/renderer/context/App.tsx +++ b/src/renderer/context/App.tsx @@ -85,6 +85,7 @@ const defaultNotificationSettings: NotificationSettingsState = { markAsDoneOnOpen: false, markAsDoneOnUnsubscribe: false, delayNotificationState: false, + notificationVolume: 20, }; const defaultSystemSettings: SystemSettingsState = { diff --git a/src/renderer/types.ts b/src/renderer/types.ts index 3c631bc53..c7ae479fe 100644 --- a/src/renderer/types.ts +++ b/src/renderer/types.ts @@ -81,6 +81,7 @@ export interface NotificationSettingsState { markAsDoneOnOpen: boolean; markAsDoneOnUnsubscribe: boolean; delayNotificationState: boolean; + notificationVolume: number; } export interface SystemSettingsState { diff --git a/src/renderer/utils/notifications/native.test.ts b/src/renderer/utils/notifications/native.test.ts index f30cc9c8f..6e33703aa 100644 --- a/src/renderer/utils/notifications/native.test.ts +++ b/src/renderer/utils/notifications/native.test.ts @@ -134,4 +134,33 @@ describe('renderer/utils/notifications/native.ts', () => { expect(window.Audio.prototype.play).toHaveBeenCalledTimes(1); }); }); + + describe('triggerNativeNotifications', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should raise only sound notification with correct volume', () => { + const settings: SettingsState = { + ...defaultSettings, + playSound: true, + showNotifications: false, + notificationVolume: 80, + }; + + const raiseSoundNotificationMock = jest.spyOn( + native, + 'raiseSoundNotification', + ); + jest.spyOn(native, 'raiseNativeNotification'); + + native.triggerNativeNotifications([], mockAccountNotifications, { + auth: mockAuth, + settings, + }); + + expect(raiseSoundNotificationMock).toHaveBeenCalledWith(0.8); + expect(native.raiseNativeNotification).not.toHaveBeenCalled(); + }); + }); }); diff --git a/src/renderer/utils/notifications/native.ts b/src/renderer/utils/notifications/native.ts index cda7f6367..1f4b56bdc 100644 --- a/src/renderer/utils/notifications/native.ts +++ b/src/renderer/utils/notifications/native.ts @@ -48,7 +48,7 @@ export const triggerNativeNotifications = ( } if (state.settings.playSound) { - raiseSoundNotification(); + raiseSoundNotification(state.settings.notificationVolume / 100); } if (state.settings.showNotifications) { @@ -86,7 +86,7 @@ export const raiseNativeNotification = (notifications: Notification[]) => { return nativeNotification; }; -export const raiseSoundNotification = () => { +export const raiseSoundNotification = (volume = 0.2) => { const audio = new Audio( path.join( __dirname, @@ -96,6 +96,6 @@ export const raiseSoundNotification = () => { Constants.NOTIFICATION_SOUND, ), ); - audio.volume = 0.2; + audio.volume = volume; audio.play(); }; From 933538be0451e529a58b1eab840df193e1455c0e Mon Sep 17 00:00:00 2001 From: Ruizhe Pang Date: Tue, 22 Apr 2025 22:45:37 +0800 Subject: [PATCH 02/10] Modify isNaN(val) to Number.isNaN(val) --- .../AccountNotifications.test.tsx.snap | 8 +++--- .../NotificationFooter.test.tsx.snap | 20 +++++++------- .../NotificationRow.test.tsx.snap | 12 ++++----- .../settings/NotificationSettings.tsx | 27 ++++++++++++------- .../__snapshots__/Settings.test.tsx.snap | 26 ++++++++++++++++++ 5 files changed, 63 insertions(+), 30 deletions(-) diff --git a/src/renderer/components/notifications/__snapshots__/AccountNotifications.test.tsx.snap b/src/renderer/components/notifications/__snapshots__/AccountNotifications.test.tsx.snap index aaa3b4f20..a3f78bc6c 100644 --- a/src/renderer/components/notifications/__snapshots__/AccountNotifications.test.tsx.snap +++ b/src/renderer/components/notifications/__snapshots__/AccountNotifications.test.tsx.snap @@ -901,7 +901,7 @@ exports[`renderer/components/notifications/AccountNotifications.tsx should rende class="sc-Qotzb" datetime="2017-05-20T17:51:57.000Z" > - May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
- May 20, 2017 + May 21, 2017
{ } /> - + - Notification Volume: {settings.notificationVolume}% + Notification Volume: - updateSetting( - 'notificationVolume', - Number.parseInt(evt.target.value, 10), - ) - } + onChange={(evt) => { + let val = Number(evt.target.value); + if (Number.isNaN(val)) val = 0; + if (val > 100) val = 100; + if (val < 0) val = 0; + updateSetting('notificationVolume', val); + }} + style={{ + width: '3rem', + textAlign: 'center', + border: '1px solid #ccc', + borderRadius: '4px', + }} /> - + ); diff --git a/src/renderer/routes/__snapshots__/Settings.test.tsx.snap b/src/renderer/routes/__snapshots__/Settings.test.tsx.snap index 1ad989a05..8041209d2 100644 --- a/src/renderer/routes/__snapshots__/Settings.test.tsx.snap +++ b/src/renderer/routes/__snapshots__/Settings.test.tsx.snap @@ -919,6 +919,32 @@ exports[`renderer/routes/Settings.tsx should render itself & its children 1`] =
+
+ + +
From 04e79d16f8eaabd9766fc63f0f839b41ccdb90bb Mon Sep 17 00:00:00 2001 From: Ruizhe Pang Date: Wed, 23 Apr 2025 00:32:20 +0800 Subject: [PATCH 03/10] Update the UI --- .../settings/NotificationSettings.tsx | 27 ------- .../components/settings/SystemSettings.tsx | 80 ++++++++++++++++++- 2 files changed, 78 insertions(+), 29 deletions(-) diff --git a/src/renderer/components/settings/NotificationSettings.tsx b/src/renderer/components/settings/NotificationSettings.tsx index 2ea5157a7..78aaae595 100644 --- a/src/renderer/components/settings/NotificationSettings.tsx +++ b/src/renderer/components/settings/NotificationSettings.tsx @@ -246,33 +246,6 @@ export const NotificationSettings: FC = () => { } /> - - - - Notification Volume: - - { - let val = Number(evt.target.value); - if (Number.isNaN(val)) val = 0; - if (val > 100) val = 100; - if (val < 0) val = 0; - updateSetting('notificationVolume', val); - }} - style={{ - width: '3rem', - textAlign: 'center', - border: '1px solid #ccc', - borderRadius: '4px', - }} - /> -
); diff --git a/src/renderer/components/settings/SystemSettings.tsx b/src/renderer/components/settings/SystemSettings.tsx index 58745f203..a0a823088 100644 --- a/src/renderer/components/settings/SystemSettings.tsx +++ b/src/renderer/components/settings/SystemSettings.tsx @@ -1,7 +1,20 @@ import { type FC, useContext } from 'react'; -import { DeviceDesktopIcon } from '@primer/octicons-react'; -import { Box, Stack, Text } from '@primer/react'; +import { + DashIcon, + DeviceDesktopIcon, + PlusIcon, + XCircleIcon, +} from '@primer/octicons-react'; + +import { + Box, + Button, + ButtonGroup, + IconButton, + Stack, + Text, +} from '@primer/react'; import { APPLICATION } from '../../../shared/constants'; import { isLinux, isMacOS } from '../../../shared/platform'; @@ -9,6 +22,7 @@ import { AppContext } from '../../context/App'; import { OpenPreference } from '../../types'; import { Constants } from '../../utils/constants'; import { Checkbox } from '../fields/Checkbox'; +import { FieldLabel } from '../fields/FieldLabel'; import { RadioGroup } from '../fields/RadioGroup'; import { Title } from '../primitives/Title'; @@ -77,6 +91,68 @@ export const SystemSettings: FC = () => { onChange={(evt) => updateSetting('playSound', evt.target.checked)} /> + {settings.playSound && ( + + + + + { + const newVolume = Math.max( + settings.notificationVolume - 10, + 0, + ); + updateSetting('notificationVolume', newVolume); + }} + data-testid="settings-volume-down" + /> + + + + { + const newVolume = Math.min( + settings.notificationVolume + 10, + 100, + ); + updateSetting('notificationVolume', newVolume); + }} + data-testid="settings-volume-up" + /> + + { + updateSetting('notificationVolume', 20); + }} + data-testid="settings-volume-reset" + /> + + + )} + Date: Wed, 23 Apr 2025 00:46:18 +0800 Subject: [PATCH 04/10] move variable(notificationVolume) to SystemSettingsState --- src/renderer/__mocks__/state-mocks.ts | 2 +- src/renderer/context/App.tsx | 2 +- .../__snapshots__/Settings.test.tsx.snap | 171 ++++++++++++++---- src/renderer/types.ts | 2 +- 4 files changed, 141 insertions(+), 36 deletions(-) diff --git a/src/renderer/__mocks__/state-mocks.ts b/src/renderer/__mocks__/state-mocks.ts index ee6cb1c93..a56037a8d 100644 --- a/src/renderer/__mocks__/state-mocks.ts +++ b/src/renderer/__mocks__/state-mocks.ts @@ -93,7 +93,6 @@ const mockNotificationSettings: NotificationSettingsState = { markAsDoneOnOpen: false, markAsDoneOnUnsubscribe: false, delayNotificationState: false, - notificationVolume: 20, }; const mockSystemSettings: SystemSettingsState = { @@ -104,6 +103,7 @@ const mockSystemSettings: SystemSettingsState = { playSound: true, useAlternateIdleIcon: false, openAtStartup: false, + notificationVolume: 20, }; const mockFilters: FilterSettingsState = { diff --git a/src/renderer/context/App.tsx b/src/renderer/context/App.tsx index e41d55ac7..1cbbce415 100644 --- a/src/renderer/context/App.tsx +++ b/src/renderer/context/App.tsx @@ -85,7 +85,6 @@ const defaultNotificationSettings: NotificationSettingsState = { markAsDoneOnOpen: false, markAsDoneOnUnsubscribe: false, delayNotificationState: false, - notificationVolume: 20, }; const defaultSystemSettings: SystemSettingsState = { @@ -96,6 +95,7 @@ const defaultSystemSettings: SystemSettingsState = { playSound: true, useAlternateIdleIcon: false, openAtStartup: false, + notificationVolume: 20, }; export const defaultFilters: FilterSettingsState = { diff --git a/src/renderer/routes/__snapshots__/Settings.test.tsx.snap b/src/renderer/routes/__snapshots__/Settings.test.tsx.snap index 8041209d2..8b9823b78 100644 --- a/src/renderer/routes/__snapshots__/Settings.test.tsx.snap +++ b/src/renderer/routes/__snapshots__/Settings.test.tsx.snap @@ -919,32 +919,6 @@ exports[`renderer/routes/Settings.tsx should render itself & its children 1`] = -
- - -
@@ -1176,6 +1150,137 @@ exports[`renderer/routes/Settings.tsx should render itself & its children 1`] = Play sound +
+ +
+ + + + +
+
-
- - -
@@ -1176,6 +1150,141 @@ exports[`renderer/routes/Settings.tsx should render itself & its children 1`] = Play sound +
+
+ +
+ + + + +
+
+
-
- -
- - - - -
-
Date: Wed, 23 Apr 2025 03:50:23 +1000 Subject: [PATCH 09/10] update snapshots Signed-off-by: Adam Setch --- .../AccountNotifications.test.tsx.snap | 8 ++++---- .../NotificationFooter.test.tsx.snap | 20 +++++++++---------- .../NotificationRow.test.tsx.snap | 12 +++++------ 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/renderer/components/notifications/__snapshots__/AccountNotifications.test.tsx.snap b/src/renderer/components/notifications/__snapshots__/AccountNotifications.test.tsx.snap index a3f78bc6c..aaa3b4f20 100644 --- a/src/renderer/components/notifications/__snapshots__/AccountNotifications.test.tsx.snap +++ b/src/renderer/components/notifications/__snapshots__/AccountNotifications.test.tsx.snap @@ -901,7 +901,7 @@ exports[`renderer/components/notifications/AccountNotifications.tsx should rende class="sc-Qotzb" datetime="2017-05-20T17:51:57.000Z" > - May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
- May 21, 2017 + May 20, 2017
Date: Thu, 24 Apr 2025 01:46:53 +1000 Subject: [PATCH 10/10] update volume icons Signed-off-by: Adam Setch --- .../components/icons/VolumeDownIcon.tsx | 18 +++ .../components/icons/VolumeUpIcon.tsx | 16 +++ .../components/settings/SystemSettings.tsx | 36 +++--- .../__snapshots__/Settings.test.tsx.snap | 108 +++++++++--------- 4 files changed, 100 insertions(+), 78 deletions(-) create mode 100644 src/renderer/components/icons/VolumeDownIcon.tsx create mode 100644 src/renderer/components/icons/VolumeUpIcon.tsx diff --git a/src/renderer/components/icons/VolumeDownIcon.tsx b/src/renderer/components/icons/VolumeDownIcon.tsx new file mode 100644 index 000000000..93b2910a4 --- /dev/null +++ b/src/renderer/components/icons/VolumeDownIcon.tsx @@ -0,0 +1,18 @@ +import type { FC } from 'react'; + +export const VolumeDownIcon: FC = () => ( + + + + + + +); diff --git a/src/renderer/components/icons/VolumeUpIcon.tsx b/src/renderer/components/icons/VolumeUpIcon.tsx new file mode 100644 index 000000000..84aac91a4 --- /dev/null +++ b/src/renderer/components/icons/VolumeUpIcon.tsx @@ -0,0 +1,16 @@ +import type { FC } from 'react'; + +export const VolumeUpIcon: FC = () => ( + + + + +); diff --git a/src/renderer/components/settings/SystemSettings.tsx b/src/renderer/components/settings/SystemSettings.tsx index ab4672013..ab224cba4 100644 --- a/src/renderer/components/settings/SystemSettings.tsx +++ b/src/renderer/components/settings/SystemSettings.tsx @@ -1,12 +1,6 @@ import { type FC, useContext } from 'react'; -import { - DashIcon, - DeviceDesktopIcon, - PlusIcon, - XCircleIcon, -} from '@primer/octicons-react'; - +import { DeviceDesktopIcon, SyncIcon } from '@primer/octicons-react'; import { Box, Button, @@ -22,8 +16,9 @@ import { AppContext, defaultSettings } from '../../context/App'; import { OpenPreference } from '../../types'; import { Constants } from '../../utils/constants'; import { Checkbox } from '../fields/Checkbox'; -import { FieldLabel } from '../fields/FieldLabel'; import { RadioGroup } from '../fields/RadioGroup'; +import { VolumeDownIcon } from '../icons/VolumeDownIcon'; +import { VolumeUpIcon } from '../icons/VolumeUpIcon'; import { Title } from '../primitives/Title'; export const SystemSettings: FC = () => { @@ -84,30 +79,25 @@ export const SystemSettings: FC = () => { } /> - updateSetting('playSound', evt.target.checked)} - /> - -
- - -
-
- + + +
@@ -1184,20 +1178,24 @@ exports[`renderer/routes/Settings.tsx should render itself & its children 1`] = type="button" > @@ -1267,7 +1265,7 @@ exports[`renderer/routes/Settings.tsx should render itself & its children 1`] = >