| 1 | import type { RoomSummary } from './types'; |
| 2 | |
| 3 | export type MessageSoundMode = 'all' | 'mentions_dms' | 'off'; |
| 4 | |
| 5 | export interface MessageSoundSettings { |
| 6 | mode: MessageSoundMode; |
| 7 | sound: string | null; |
| 8 | } |
| 9 | |
| 10 | export const DEFAULT_MESSAGE_SOUND: MessageSoundSettings = { mode: 'mentions_dms', sound: null }; |
| 11 | export const SOUND_MAX_BYTES = 1024 * 1024; |
| 12 | export const SOUND_THROTTLE_MS = 1500; |
| 13 | |
| 14 | export function parseMessageSound(raw: unknown): MessageSoundSettings { |
| 15 | if (typeof raw !== 'object' || raw === null) return DEFAULT_MESSAGE_SOUND; |
| 16 | const { mode, sound } = raw as Record<string, unknown>; |
| 17 | return { |
| 18 | mode: mode === 'all' || mode === 'mentions_dms' || mode === 'off' ? mode : DEFAULT_MESSAGE_SOUND.mode, |
| 19 | sound: typeof sound === 'string' && sound.startsWith('mxc://') ? sound : null |
| 20 | }; |
| 21 | } |
| 22 | |
| 23 | export function shouldPlaySound( |
| 24 | mode: MessageSoundMode, |
| 25 | room: Pick<RoomSummary, 'direct'>, |
| 26 | arrival: { mention: boolean }, |
| 27 | lastPlayedAt: number, |
| 28 | now: number |
| 29 | ): boolean { |
| 30 | if (mode === 'off' || now - lastPlayedAt < SOUND_THROTTLE_MS) return false; |
| 31 | return mode === 'all' || arrival.mention || room.direct; |
| 32 | } |