feat: audio devices + fullscreen + banner cleanup (v0.7.0)
Audio device selection: - audioSettings: persisted inputDeviceId + outputDeviceId - CallContext: uses stored input deviceId on mic enable, new setAudioInputDevice / setAudioOutputDevice actions that hot-swap without reconnect. Output swap applies HTMLMediaElement.setSinkId to every attached remote-audio element (LiveKit's switchActiveDevice only tracks elements it attached itself) - SettingsPage: new "Mikrofon" + "Ausgabegerät" selects with enumerateDevices, devicechange listener, permission-probe button. setSinkId-unsupported fallback is messaged but non-blocking Fullscreen: - FullscreenCall was absolute inset-0 z-40 which trapped it inside the <main> pane — sidebar + chat-list stayed visible. Switched to fixed inset-0 z-[60] so the call overlays the whole window Discord-style - ScreenShareViewer fullscreen: CSS-only toggle (native Fullscreen API unreliable under Tauri WKWebView), portalled to document.body when active so no ancestor stacking context can clip it. Esc exits ActiveCallBanner: - cleanup effect returned early when presence was entirely empty, leaving the "1 im Raum" fallback stuck after both peers left. Now schedules dismissLastCall as soon as othersIn.length === 0, with a 3s grace window to absorb presence re-sync flicker Bump tauri version 0.6.0 -> 0.7.0
This commit is contained in:
@@ -210,17 +210,14 @@ function ActiveCallBanner({ conversationId }: { conversationId: string }) {
|
||||
const justLeft = state.kind === 'idle' && lastCallConversationId === conversationId;
|
||||
|
||||
// Once presence confirms the room is empty, drop the "just left" hint so the
|
||||
// banner hides cleanly instead of sticking forever.
|
||||
// banner hides cleanly instead of sticking forever. Grace window handles the
|
||||
// brief gap between hangup and presence re-sync so we don't flicker.
|
||||
useEffect(() => {
|
||||
if (!justLeft) return;
|
||||
if (active.length === 0) return;
|
||||
if (othersIn.length === 0) {
|
||||
// Active reports only us (or something stale) — wait, then dismiss.
|
||||
const id = window.setTimeout(() => dismissLastCall(), 3000);
|
||||
return () => window.clearTimeout(id);
|
||||
}
|
||||
return undefined;
|
||||
}, [justLeft, active.length, othersIn.length, dismissLastCall]);
|
||||
if (othersIn.length > 0) return; // still live — keep banner
|
||||
const id = window.setTimeout(() => dismissLastCall(), 3000);
|
||||
return () => window.clearTimeout(id);
|
||||
}, [justLeft, othersIn.length, dismissLastCall]);
|
||||
|
||||
if (iAmIn) return null;
|
||||
if (othersIn.length === 0 && !justLeft) return null;
|
||||
|
||||
Reference in New Issue
Block a user