feat(call): add sound effects and incoming call notification UI

- Implemented sound management for call events including mute, unmute, deafen, undeafen, call joined, call depart, and dialing sounds.
- Created a new CallSounds class to handle sound playback and state management.
- Added IncomingCallNotification component to display incoming call alerts with caller information and action buttons.
- Styled the incoming call notification using vanilla-extract CSS for animations and layout.
- Integrated sound playback for incoming calls with a 15-second threshold for dialing sound.
This commit is contained in:
2026-02-05 03:24:18 +11:00
parent cd912025f1
commit 1a452f52ca
27 changed files with 1888 additions and 179 deletions

View File

@@ -10,7 +10,7 @@ import NotificationSound from '../../../../public/sound/notification.ogg';
import InviteSound from '../../../../public/sound/invite.ogg';
import { notificationPermission, setFavicon } from '../../utils/dom';
import { useSetting } from '../../state/hooks/settings';
import { settingsAtom } from '../../state/settings';
import { EmojiStyle, settingsAtom } from '../../state/settings';
import { allInvitesAtom } from '../../state/room-list/inviteList';
import { usePreviousValue } from '../../hooks/usePreviousValue';
import { useMatrixClient } from '../../hooks/useMatrixClient';
@@ -28,13 +28,26 @@ import { useInboxNotificationsSelected } from '../../hooks/router/useInbox';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { isTauri, sendNotification, setupNotificationTapListener } from '../../utils/tauri';
function SystemEmojiFeature() {
const [twitterEmoji] = useSetting(settingsAtom, 'twitterEmoji');
/**
* Applies the selected emoji style font to the document.
* - System: Uses the native OS emoji font
* - Apple: Uses Apple Color Emoji (bundled font)
* - Twemoji: Uses Twitter's Twemoji font
*/
function EmojiStyleFeature() {
const [emojiStyle] = useSetting(settingsAtom, 'emojiStyle');
if (twitterEmoji) {
document.documentElement.style.setProperty('--font-emoji', 'Twemoji');
} else {
document.documentElement.style.setProperty('--font-emoji', 'Twemoji_DISABLED');
switch (emojiStyle) {
case EmojiStyle.Apple:
document.documentElement.style.setProperty('--font-emoji', 'AppleColorEmoji');
break;
case EmojiStyle.Twemoji:
document.documentElement.style.setProperty('--font-emoji', 'Twemoji');
break;
case EmojiStyle.System:
default:
document.documentElement.style.setProperty('--font-emoji', 'SystemEmoji');
break;
}
return null;
@@ -316,7 +329,7 @@ type ClientNonUIFeaturesProps = {
export function ClientNonUIFeatures({ children }: ClientNonUIFeaturesProps) {
return (
<>
<SystemEmojiFeature />
<EmojiStyleFeature />
<PageZoomFeature />
<FaviconUpdater />
<InviteNotifications />