fix(lotus): revert to the default output sink when the selected device disappears
Fixes #27 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
co-authored by
Claude Opus 5
parent
68eafcb9a8
commit
c7494e68ca
+22
-4
@@ -6,7 +6,7 @@ Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { logger } from "matrix-js-sdk/lib/logger";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { useObservableEagerState } from "observable-hooks";
|
||||
|
||||
import {
|
||||
@@ -172,13 +172,22 @@ export function useAudioContext<S extends string>(
|
||||
useMediaDevices().audioOutput.selected$,
|
||||
)?.id;
|
||||
const { controlledAudioDevices } = useUrlParams();
|
||||
// [lotus] Tracks whether audioOutputId has ever resolved to a real device,
|
||||
// so we can tell "MediaDevices hasn't resolved yet" (skip) apart from "the
|
||||
// previously selected output device just disappeared" (revert to default,
|
||||
// #27) — both present as audioOutputId === undefined.
|
||||
const outputHasResolved = useRef(false);
|
||||
|
||||
// Update the sink ID whenever we change devices.
|
||||
useEffect(() => {
|
||||
if (typeof audioOutputId === "string") outputHasResolved.current = true;
|
||||
if (
|
||||
!audioContext ||
|
||||
!("setSinkId" in audioContext) ||
|
||||
controlledAudioDevices
|
||||
)
|
||||
return;
|
||||
if (
|
||||
audioContext &&
|
||||
"setSinkId" in audioContext &&
|
||||
!controlledAudioDevices &&
|
||||
// Skip until a device is actually selected. audioOutputId is undefined
|
||||
// before MediaDevices resolves (e.g. on the Tauri desktop webview, where
|
||||
// the selected$ observable emits undefined first); setSinkId(undefined)
|
||||
@@ -191,6 +200,15 @@ export function useAudioContext<S extends string>(
|
||||
audioContext.setSinkId(audioOutputId).catch((ex) => {
|
||||
logger.warn("Unable to change sink for audio context", ex);
|
||||
});
|
||||
} else if (outputHasResolved.current) {
|
||||
// [lotus] The previously selected output device disappeared (selected$
|
||||
// re-emits undefined once devices have already resolved), not the
|
||||
// pre-resolution case above. Revert to the default sink instead of
|
||||
// leaving the context pinned to a now-nonexistent device (#27).
|
||||
// @ts-expect-error - setSinkId doesn't exist yet in types, maybe because it's not supported everywhere.
|
||||
audioContext.setSinkId("").catch((ex) => {
|
||||
logger.warn("Unable to revert sink for audio context", ex);
|
||||
});
|
||||
}
|
||||
}, [audioContext, audioOutputId, controlledAudioDevices]);
|
||||
const { pan: earpiecePan, volume: earpieceVolume } = useEarpieceAudioConfig();
|
||||
|
||||
Reference in New Issue
Block a user