✨(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:
committed by
aleb_the_flash
parent
be54709598
commit
83914f8307
@@ -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 }
|
||||
}
|
||||
|
||||
44
src/frontend/src/stores/notifications.ts
Normal file
44
src/frontend/src/stores/notifications.ts
Normal 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)
|
||||
)
|
||||
})
|
||||
Reference in New Issue
Block a user