Skip to content

Commit

Permalink
Use device label instead of id to save defaults
Browse files Browse the repository at this point in the history
  • Loading branch information
streamer45 committed Feb 25, 2025
1 parent 693d026 commit f5a0618
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 39 deletions.
36 changes: 18 additions & 18 deletions e2e/tests/start_call.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,21 +246,21 @@ test.describe('setting audio input device', () => {
await page.locator('#calls-widget-audio-input-button').click();
await expect(page.locator('#calls-widget-audio-inputs-menu')).toBeVisible();

let currentAudioInputDevice = await page.evaluate(() => {
const currentAudioInputDeviceID = await page.evaluate(() => {
return window.callsClient.currentInputAudioDevice?.deviceId;
});
if (currentAudioInputDevice) {
if (currentAudioInputDeviceID) {
test.fail();
return;
}

await page.locator('#calls-widget-audio-inputs-menu button:has-text("Fake Audio Input 1")').click();
await expect(page.locator('#calls-widget-audio-inputs-menu')).toBeHidden();

currentAudioInputDevice = await page.evaluate(() => {
return window.callsClient.currentAudioInputDevice?.deviceId;
const currentAudioInputDevice = await page.evaluate(() => {
return window.callsClient.currentAudioInputDevice;
});
if (!currentAudioInputDevice) {
if (currentAudioInputDevice.label !== 'Fake Audio Input 1') {
test.fail();
return;
}
Expand All @@ -272,18 +272,18 @@ test.describe('setting audio input device', () => {
const currentAudioInputDevice2 = await page.evaluate(() => {
return window.callsClient.currentAudioInputDevice?.deviceId;
});
if (currentAudioInputDevice2 !== currentAudioInputDevice) {
if (currentAudioInputDevice2 !== currentAudioInputDevice.deviceId) {
test.fail();
return;
}

await devPage.leaveCall();

await page.reload();
const deviceID = await page.evaluate(() => {
return window.localStorage.getItem('calls_default_audio_input');
const device = await page.evaluate(() => {
return JSON.parse(window.localStorage.getItem('calls_default_audio_input')!);
});
if (!deviceID) {
if (!device || !device.deviceId || !device.label) {
test.fail();
}
});
Expand Down Expand Up @@ -316,21 +316,21 @@ test.describe('setting audio output device', () => {
await page.locator('#calls-widget-audio-output-button').click();
await expect(page.locator('#calls-widget-audio-outputs-menu')).toBeVisible();

let currentAudioOutputDevice = await page.evaluate(() => {
const currentAudioOutputDeviceID = await page.evaluate(() => {
return window.callsClient.currentAudioOutputDevice?.deviceId;
});
if (currentAudioOutputDevice) {
if (currentAudioOutputDeviceID) {
test.fail();
return;
}

await page.locator('#calls-widget-audio-outputs-menu button:has-text("Fake Audio Output 1")').click();
await expect(page.locator('#calls-widget-audio-outputs-menu')).toBeHidden();

currentAudioOutputDevice = await page.evaluate(() => {
return window.callsClient.currentAudioOutputDevice?.deviceId;
const currentAudioOutputDevice = await page.evaluate(() => {
return window.callsClient.currentAudioOutputDevice;
});
if (!currentAudioOutputDevice) {
if (currentAudioOutputDevice.label !== 'Fake Audio Output 1') {
test.fail();
return;
}
Expand All @@ -342,18 +342,18 @@ test.describe('setting audio output device', () => {
const currentAudioOutputDevice2 = await page.evaluate(() => {
return window.callsClient.currentAudioOutputDevice?.deviceId;
});
if (currentAudioOutputDevice2 !== currentAudioOutputDevice) {
if (currentAudioOutputDevice2 !== currentAudioOutputDevice.deviceId) {
test.fail();
return;
}

await devPage.leaveCall();

await page.reload();
const deviceID = await page.evaluate(() => {
return window.localStorage.getItem('calls_default_audio_output');
const device = await page.evaluate(() => {
return JSON.parse(window.localStorage.getItem('calls_default_audio_output')!);
});
if (!deviceID) {
if (!device || !device.deviceId || !device.label) {
test.fail();
}
});
Expand Down
62 changes: 51 additions & 11 deletions webapp/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,17 +107,51 @@ export default class CallsClient extends EventEmitter {
};
}

const defaultInputID = window.localStorage.getItem(STORAGE_CALLS_DEFAULT_AUDIO_INPUT_KEY);
const defaultOutputID = window.localStorage.getItem(STORAGE_CALLS_DEFAULT_AUDIO_OUTPUT_KEY);
if (defaultInputID && !this.currentAudioInputDevice) {
const devices = this.audioDevices.inputs.filter((dev) => {
return dev.deviceId === defaultInputID;
let defaultInputDevice: {deviceId: string; label?: string} = {
deviceId: '',
};
const defaultAudioInputData = window.localStorage.getItem(STORAGE_CALLS_DEFAULT_AUDIO_INPUT_KEY);
if (defaultAudioInputData) {
try {
defaultInputDevice = JSON.parse(defaultAudioInputData);
} catch {
// Backwards compatibility case when we used to store the device id directly (before MM-63274).
defaultInputDevice = {
deviceId: defaultAudioInputData,
};
}
}

let defaultOutputDevice: {deviceId: string; label?: string} = {
deviceId: '',
};
const defaultAudioOutputData = window.localStorage.getItem(STORAGE_CALLS_DEFAULT_AUDIO_OUTPUT_KEY);
if (defaultAudioOutputData) {
try {
defaultOutputDevice = JSON.parse(defaultAudioOutputData);
} catch {
// Backwards compatibility case when we used to store the device id directly (before MM-63274).
defaultOutputDevice = {
deviceId: defaultAudioOutputData,
};
}
}

if (defaultInputDevice.deviceId && !this.currentAudioInputDevice) {
let devices = this.audioDevices.inputs.filter((dev) => {
return dev.deviceId === defaultInputDevice.deviceId || dev.label === defaultInputDevice.label;
});

if (devices.length > 1) {
// If there are multiple devices with the same label, we select the default device by ID.
logInfo('multiple audio input devices found with the same label, checking by id', devices);
devices = devices.filter((dev) => dev.deviceId === defaultInputDevice.deviceId);
}

if (devices && devices.length === 1) {
logDebug(`found default audio input device to use: ${devices[0].label}`);
audioOptions.deviceId = {
exact: defaultInputID,
exact: devices[0].deviceId,
};
this.currentAudioInputDevice = devices[0];
} else {
Expand All @@ -126,11 +160,17 @@ export default class CallsClient extends EventEmitter {
}
}

if (defaultOutputID) {
const devices = this.audioDevices.outputs.filter((dev) => {
return dev.deviceId === defaultOutputID;
if (defaultOutputDevice.deviceId) {
let devices = this.audioDevices.outputs.filter((dev) => {
return dev.deviceId === defaultOutputDevice.deviceId || dev.label === defaultOutputDevice.label;
});

if (devices.length > 1) {
// If there are multiple devices with the same label, we select the default device by ID.
logInfo('multiple audio output devices found with the same label, checking by id', devices);
devices = devices.filter((dev) => dev.deviceId === defaultInputDevice.deviceId);
}

if (devices && devices.length === 1) {
logDebug(`found default audio output device to use: ${devices[0].label}`);
this.currentAudioOutputDevice = devices[0];
Expand Down Expand Up @@ -423,7 +463,7 @@ export default class CallsClient extends EventEmitter {
return;
}

window.localStorage.setItem(STORAGE_CALLS_DEFAULT_AUDIO_INPUT_KEY, device.deviceId);
window.localStorage.setItem(STORAGE_CALLS_DEFAULT_AUDIO_INPUT_KEY, JSON.stringify(device));
this.currentAudioInputDevice = device;

// We emit this event so it's easier to keep state in sync between widget and pop out.
Expand Down Expand Up @@ -473,7 +513,7 @@ export default class CallsClient extends EventEmitter {
if (!this.peer) {
return;
}
window.localStorage.setItem(STORAGE_CALLS_DEFAULT_AUDIO_OUTPUT_KEY, device.deviceId);
window.localStorage.setItem(STORAGE_CALLS_DEFAULT_AUDIO_OUTPUT_KEY, JSON.stringify(device));
this.currentAudioOutputDevice = device;

// We emit this event so it's easier to keep state in sync between widget and pop out.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
import React, {forwardRef, useEffect, useImperativeHandle, useRef, useState} from 'react';
import {useIntl} from 'react-intl';
import ReactSelect from 'react-select';
import {
STORAGE_CALLS_DEFAULT_AUDIO_INPUT_KEY,
STORAGE_CALLS_DEFAULT_AUDIO_OUTPUT_KEY,
} from 'src/constants';
import {logErr} from 'src/log';
import styled from 'styled-components';

Expand Down Expand Up @@ -41,19 +45,39 @@ const AudioDevicesSelection = forwardRef<AudioDevicesSelectionHandle, AudioDevic
return selectedOption;
}

const defaultDeviceID = deviceType === 'inputs' ?
window.localStorage.getItem('calls_default_audio_input') :
window.localStorage.getItem('calls_default_audio_output');
const defaultDeviceData = deviceType === 'inputs' ?
window.localStorage.getItem(STORAGE_CALLS_DEFAULT_AUDIO_INPUT_KEY) :
window.localStorage.getItem(STORAGE_CALLS_DEFAULT_AUDIO_OUTPUT_KEY);

for (const device of devices) {
if (device.deviceId === defaultDeviceID) {
return {
label: device.label,
value: device.deviceId,
let defaultDevice: {deviceId: string; label?: string} = {
deviceId: '',
};

if (defaultDeviceData) {
try {
defaultDevice = JSON.parse(defaultDeviceData);
} catch {
// Backwards compatibility case when we used to store the device id directly (before MM-63274).
defaultDevice = {
deviceId: defaultDeviceData,
};
}
}

let selected = devices.filter((dev) => {
return dev.deviceId === defaultDevice.deviceId || dev.label === defaultDevice.label;
});
if (selected.length > 1) {
// If there are multiple devices with the same label, we select the default device by ID.
selected = selected.filter((dev) => dev.deviceId === defaultDevice.deviceId);
}
if (selected.length > 0) {
return {
label: selected[0].label,
value: selected[0].deviceId,
};
}

return {
label: devices[0]?.label ?? '',
value: devices[0]?.deviceId ?? '',
Expand Down Expand Up @@ -122,10 +146,17 @@ export default function AudioDevicesSettingsSection() {

const handleSave = () => {
if (audioInputsRef.current) {
window.localStorage.setItem('calls_default_audio_input', audioInputsRef.current.getOption().value);
window.localStorage.setItem(STORAGE_CALLS_DEFAULT_AUDIO_INPUT_KEY, JSON.stringify({
deviceId: audioInputsRef.current.getOption().value,
label: audioInputsRef.current.getOption().label,
}));
}
if (audioOutputsRef.current) {
window.localStorage.setItem('calls_default_audio_output', audioOutputsRef.current.getOption().value);
window.localStorage.setItem(STORAGE_CALLS_DEFAULT_AUDIO_OUTPUT_KEY, JSON.stringify({
deviceId: audioOutputsRef.current.getOption().value,
label: audioOutputsRef.current.getOption().label,
},
));
}
setActive(false);
};
Expand Down

0 comments on commit f5a0618

Please sign in to comment.