fix logic for earpiece quick switcher to be based on switching target

(also show quick switcher if headphones are connected)
This commit is contained in:
Timo
2025-06-25 17:43:59 +02:00
parent a98ced3e5b
commit 2207e6ac21
2 changed files with 39 additions and 33 deletions
+12 -13
View File
@@ -312,7 +312,7 @@ export const InCallView: FC<InCallViewProps> = ({
const showHeader = useObservableEagerState(vm.showHeader$); const showHeader = useObservableEagerState(vm.showHeader$);
const showFooter = useObservableEagerState(vm.showFooter$); const showFooter = useObservableEagerState(vm.showFooter$);
const earpieceMode = useObservableEagerState(vm.earpieceMode$); const earpieceMode = useObservableEagerState(vm.earpieceMode$);
const toggleEarpieceMode = useObservableEagerState(vm.toggleEarpieceMode$); const audioOutputSwitcher = useObservableEagerState(vm.audioOutputSwitcher$);
const switchCamera = useSwitchCamera(vm.localVideo$); const switchCamera = useSwitchCamera(vm.localVideo$);
// Ideally we could detect taps by listening for click events and checking // Ideally we could detect taps by listening for click events and checking
@@ -457,27 +457,26 @@ export const InCallView: FC<InCallViewProps> = ({
useAppBarSecondaryButton( useAppBarSecondaryButton(
useMemo(() => { useMemo(() => {
if (toggleEarpieceMode === null) return null; if (audioOutputSwitcher === null) return null;
const Icon = earpieceMode ? VolumeOnSolidIcon : EarpieceIcon; const isEarpieceTarget = audioOutputSwitcher.targetOutput === "earpiece";
return ( const Icon = isEarpieceTarget ? EarpieceIcon : VolumeOnSolidIcon;
<Tooltip const label = isEarpieceTarget
label={
earpieceMode
? t("settings.devices.earpiece") ? t("settings.devices.earpiece")
: t("settings.devices.loudspeaker") : t("settings.devices.loudspeaker");
}
> return (
<Tooltip label={label}>
<IconButton <IconButton
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
toggleEarpieceMode(); audioOutputSwitcher.switch();
}} }}
> >
<Icon /> <Icon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
); );
}, [t, earpieceMode, toggleEarpieceMode]), }, [t, audioOutputSwitcher]),
); );
useAppBarHidden(!showHeader); useAppBarHidden(!showHeader);
@@ -789,7 +788,7 @@ export const InCallView: FC<InCallViewProps> = ({
<ReactionsAudioRenderer vm={vm} muted={muteAllAudio} /> <ReactionsAudioRenderer vm={vm} muted={muteAllAudio} />
<EarpieceOverlay <EarpieceOverlay
show={earpieceMode} show={earpieceMode}
onBackToVideoPressed={toggleEarpieceMode} onBackToVideoPressed={audioOutputSwitcher?.switch}
/> />
<ReactionsOverlay vm={vm} /> <ReactionsOverlay vm={vm} />
{footer} {footer}
+12 -5
View File
@@ -1261,18 +1261,22 @@ export class CallViewModel extends ViewModel {
/** /**
* Callback to toggle between the earpiece and the loudspeaker. * Callback to toggle between the earpiece and the loudspeaker.
*
* This will be `null` in case the target does not exist in the list
* of available audio outputs.
*/ */
public readonly toggleEarpieceMode$: Observable<(() => void) | null> = public readonly audioOutputSwitcher$: Observable<{
combineLatest( targetOutput: "earpiece" | "speaker";
switch: () => void;
} | null> = combineLatest(
[ [
this.mediaDevices.audioOutput.available$, this.mediaDevices.audioOutput.available$,
this.mediaDevices.audioOutput.selected$, this.mediaDevices.audioOutput.selected$,
], ],
(available, selected) => { (available, selected) => {
const selectionType = selected && available.get(selected.id)?.type; const selectionType = selected && available.get(selected.id)?.type;
if (!(selectionType === "speaker" || selectionType === "earpiece"))
return null;
// If we are in any output mode other than spaeker switch to speaker.
const newSelectionType = const newSelectionType =
selectionType === "speaker" ? "earpiece" : "speaker"; selectionType === "speaker" ? "earpiece" : "speaker";
const newSelection = [...available].find( const newSelection = [...available].find(
@@ -1281,7 +1285,10 @@ export class CallViewModel extends ViewModel {
if (newSelection === undefined) return null; if (newSelection === undefined) return null;
const [id] = newSelection; const [id] = newSelection;
return () => this.mediaDevices.audioOutput.select(id); return {
targetOutput: newSelectionType,
switch: () => this.mediaDevices.audioOutput.select(id),
};
}, },
); );