feat(calls): configurable ringtone volume in Settings (Bug #4 partial)
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 <noreply@anthropic.com>
This commit is contained in:
+3
-2
@@ -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
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ function IncomingCall({ dm, info, onIgnore, onAnswer, onReject }: IncomingCallPr
|
||||
const { room } = info;
|
||||
|
||||
const audioRef = useRef<HTMLAudioElement>(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;
|
||||
|
||||
@@ -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() {
|
||||
/>
|
||||
)}
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Ringtone Volume"
|
||||
description="Volume of the incoming call ringtone."
|
||||
after={
|
||||
<Box direction="Row" alignItems="Center" gap="200" style={{ minWidth: '160px' }}>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
step="5"
|
||||
value={ringtoneVolume}
|
||||
onChange={(e) => setRingtoneVolume(parseInt(e.target.value, 10))}
|
||||
aria-label="Ringtone volume"
|
||||
style={{ flex: 1, accentColor: 'var(--accent-orange)' }}
|
||||
/>
|
||||
<Text size="T200" style={{ minWidth: '32px', textAlign: 'right' }}>
|
||||
{ringtoneVolume}%
|
||||
</Text>
|
||||
</Box>
|
||||
}
|
||||
/>
|
||||
</SequenceCard>
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SettingTile
|
||||
title="Join & Leave Sounds"
|
||||
|
||||
@@ -148,6 +148,7 @@ export interface Settings {
|
||||
afkTimeoutMinutes: number;
|
||||
|
||||
callJoinLeaveSound: 'off' | 'chime' | 'soft' | 'retro';
|
||||
ringtoneVolume: number; // 0–100
|
||||
|
||||
seasonalThemeOverride:
|
||||
| 'auto'
|
||||
@@ -242,6 +243,7 @@ const defaultSettings: Settings = {
|
||||
afkTimeoutMinutes: 10,
|
||||
|
||||
callJoinLeaveSound: 'chime',
|
||||
ringtoneVolume: 70,
|
||||
|
||||
seasonalThemeOverride: 'auto',
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user