From a77c4b6db5b46618e0966ed47f32d45d0217f8a7 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Thu, 18 Jun 2026 18:56:04 -0400 Subject: [PATCH] feat(calls): configurable ringtone volume in Settings (Bug #4 partial) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds 'Ringtone Volume' slider (0–100, default 70%) to Settings → Calls. The IncomingCall audio element reads the setting and applies it as audioElement.volume before playing, replacing the implicit browser default of 1.0. Co-Authored-By: Claude Sonnet 4.6 --- LOTUS_BUGS.md | 5 ++-- src/app/components/CallEmbedProvider.tsx | 7 ++++-- src/app/features/settings/general/General.tsx | 24 +++++++++++++++++++ src/app/state/settings.ts | 2 ++ 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/LOTUS_BUGS.md b/LOTUS_BUGS.md index 4df384021..86df42840 100644 --- a/LOTUS_BUGS.md +++ b/LOTUS_BUGS.md @@ -35,10 +35,11 @@ This document tracks identified bugs, edge cases, and architectural discrepancie ### 4. DM and Group Message Calls - **File:** `cinny/src/app/components/CallEmbedProvider.tsx` -- **Status:** **OPEN** +- **Status:** **PARTIALLY FIXED ⚠️ UNTESTED** — Volume control added. Remaining: ringtone selection, suppression during active calls. - **Issue:** Incoming call ringtone is hardcoded, lacks volume control, and is suppressed if the user is already in an active call. - **Root Cause:** Ringing logic is tightly coupled to `RTCNotification` events in `CallEmbedProvider.tsx`, using a hardcoded audio file path. It lacks an abstraction for sound management or user-configurable settings for ringtones/volumes. -- **Proposed Fix:** Migrate sound asset management to a dedicated audio service. Implement user-configurable settings for ringtone and notification volume. Update the `IncomingCallListener` to support ringing even during active calls (if appropriate) by enhancing event handling. +- **Fix Applied:** Added `ringtoneVolume` setting (0–100, default 70). `IncomingCall` reads this setting and applies `audioElement.volume = ringtoneVolume / 100` before `play()`. Slider added to Settings → General → Calls section. +- **Remaining:** (a) Ringtone selection (still hardcoded to `call.ogg`); (b) Suppression during active calls — not investigated. ### 5. Seasonal Themes and Chat Backgrounds Design diff --git a/src/app/components/CallEmbedProvider.tsx b/src/app/components/CallEmbedProvider.tsx index 87f3e3369..058a991c5 100644 --- a/src/app/components/CallEmbedProvider.tsx +++ b/src/app/components/CallEmbedProvider.tsx @@ -104,6 +104,7 @@ function IncomingCall({ dm, info, onIgnore, onAnswer, onReject }: IncomingCallPr const { room } = info; const audioRef = useRef(null); + const [ringtoneVolume] = useSetting(settingsAtom, 'ringtoneVolume'); const roomName = useRoomName(room); const roomAvatar = useRoomAvatar(room, dm); @@ -126,8 +127,10 @@ function IncomingCall({ dm, info, onIgnore, onAnswer, onReject }: IncomingCallPr const playSound = useCallback(() => { const audioElement = audioRef.current; - audioElement?.play().catch(() => undefined); - }, []); + if (!audioElement) return; + audioElement.volume = Math.max(0, Math.min(1, ringtoneVolume / 100)); + audioElement.play().catch(() => undefined); + }, [ringtoneVolume]); useEffect(() => { const audioEl = audioRef.current; diff --git a/src/app/features/settings/general/General.tsx b/src/app/features/settings/general/General.tsx index 389e3e2cd..e07cf3386 100644 --- a/src/app/features/settings/general/General.tsx +++ b/src/app/features/settings/general/General.tsx @@ -1234,6 +1234,7 @@ function Calls() { settingsAtom, 'callJoinLeaveSound', ); + const [ringtoneVolume, setRingtoneVolume] = useSetting(settingsAtom, 'ringtoneVolume'); const handleJoinLeaveSoundChange = (value: 'off' | 'chime' | 'soft' | 'retro') => { setCallJoinLeaveSound(value); @@ -1565,6 +1566,29 @@ function Calls() { /> )} + + + setRingtoneVolume(parseInt(e.target.value, 10))} + aria-label="Ringtone volume" + style={{ flex: 1, accentColor: 'var(--accent-orange)' }} + /> + + {ringtoneVolume}% + + + } + /> +