From 83914f8307bdd09a49646ea11d9766d05a1a1402 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Fri, 6 Dec 2024 14:55:32 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(frontend)=20add=20notification=20stor?= =?UTF-8?q?e=20for=20managing=20user=20preferences?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduced a global state to handle user preferences related to notifications. The first use case is sound notifications, allowing users to disable them based on feedback. Additionally, the sound volume is now stored globally, making it easy to configure in the future if needed. I've lowered the volume of the notifications to make them more discreet. Preferences are persisted in local storage, ensuring they are retained between meetings. --- .../hooks/useSoundNotification.tsx | 10 ++++- src/frontend/src/stores/notifications.ts | 44 +++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 src/frontend/src/stores/notifications.ts diff --git a/src/frontend/src/features/notifications/hooks/useSoundNotification.tsx b/src/frontend/src/features/notifications/hooks/useSoundNotification.tsx index ce9b3d3e..fcaa6cb7 100644 --- a/src/frontend/src/features/notifications/hooks/useSoundNotification.tsx +++ b/src/frontend/src/features/notifications/hooks/useSoundNotification.tsx @@ -1,7 +1,11 @@ import useSound from 'use-sound' +import { useSnapshot } from 'valtio' +import { notificationsStore } from '@/stores/notifications' +import { NotificationType } from '@/features/notifications/NotificationType' // fixme - handle dynamic audio output changes export const useNotificationSound = () => { + const notificationsSnap = useSnapshot(notificationsStore) const [play] = useSound('./sounds/notifications.mp3', { sprite: { participantJoined: [0, 1150], @@ -10,9 +14,11 @@ export const useNotificationSound = () => { waiting: [2039, 710], success: [2740, 1304], }, + volume: notificationsSnap.soundNotificationVolume, }) - const triggerNotificationSound = (type: string) => { - play({ id: type }) + const triggerNotificationSound = (type: NotificationType) => { + const isSoundEnabled = notificationsSnap.soundNotifications.get(type) + if (isSoundEnabled) play({ id: type }) } return { triggerNotificationSound } } diff --git a/src/frontend/src/stores/notifications.ts b/src/frontend/src/stores/notifications.ts new file mode 100644 index 00000000..19871f42 --- /dev/null +++ b/src/frontend/src/stores/notifications.ts @@ -0,0 +1,44 @@ +import { proxy, subscribe } from 'valtio' +import { proxyMap } from 'valtio/utils' +import { deserializeToProxyMap, serializeProxyMap } from '@/utils/valtio' +import { STORAGE_KEYS } from '@/utils/storageKeys' +import { NotificationType } from '@/features/notifications/NotificationType' + +type State = { + soundNotifications: Map + soundNotificationVolume: number +} + +const DEFAULT_STATE: State = { + soundNotifications: proxyMap( + new Map([ + [NotificationType.ParticipantJoined, true], + [NotificationType.HandRaised, true], + ]) + ), + soundNotificationVolume: 0.1, +} + +function getNotificationsState(): State { + try { + const stored = localStorage.getItem(STORAGE_KEYS.NOTIFICATIONS) + if (!stored) return DEFAULT_STATE + const parsed = JSON.parse(stored, deserializeToProxyMap) + return parsed || DEFAULT_STATE + } catch (error: unknown) { + console.error( + '[NotificationsStore] Failed to parse stored settings:', + error + ) + return DEFAULT_STATE + } +} + +export const notificationsStore = proxy(getNotificationsState()) + +subscribe(notificationsStore, () => { + localStorage.setItem( + STORAGE_KEYS.NOTIFICATIONS, + JSON.stringify(notificationsStore, serializeProxyMap) + ) +})