(frontend) add notification store for managing user preferences

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.
This commit is contained in:
lebaudantoine
2024-12-06 14:55:32 +01:00
committed by aleb_the_flash
parent be54709598
commit 83914f8307
2 changed files with 52 additions and 2 deletions

View File

@@ -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 }
}

View File

@@ -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<NotificationType, boolean>
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<State>(getNotificationsState())
subscribe(notificationsStore, () => {
localStorage.setItem(
STORAGE_KEYS.NOTIFICATIONS,
JSON.stringify(notificationsStore, serializeProxyMap)
)
})