mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-04-02 00:07:56 +01:00
calling: add internal preferences for DRED, bitrate, VP9, sfu url
This commit is contained in:
@@ -56,6 +56,9 @@ export type SemverKeyType = ArrayValues<typeof SemverKeys>;
|
||||
|
||||
const ScalarKeys = [
|
||||
'desktop.callQualitySurveyPPM',
|
||||
'desktop.calling.dredDuration.alpha',
|
||||
'desktop.calling.dredDuration.beta',
|
||||
'desktop.calling.dredDuration.prod',
|
||||
'desktop.clientExpiration',
|
||||
'desktop.internalUser',
|
||||
'desktop.loggingErrorToasts',
|
||||
|
||||
@@ -647,6 +647,18 @@ export default {
|
||||
},
|
||||
cqsTestMode: false,
|
||||
setCqsTestMode: action('setCqsTestMode'),
|
||||
dredDuration: 0,
|
||||
setDredDuration: action('setDredDuration'),
|
||||
directMaxBitrate: 1000000,
|
||||
setDirectMaxBitrate: action('setDirectMaxBitrate'),
|
||||
isDirectVp9Enabled: true,
|
||||
setIsDirectVp9Enabled: action('setIsDirectVp9Enabled'),
|
||||
groupMaxBitrate: 1000000,
|
||||
setGroupMaxBitrate: action('setGroupMaxBitrate'),
|
||||
isGroupVp9Enabled: false,
|
||||
setIsGroupVp9Enabled: action('setIsDirectVp9Enabled'),
|
||||
sfuUrl: 'https://sfu.voip.signal.org',
|
||||
setSfuUrl: action('setSfuUrl'),
|
||||
} satisfies PropsType,
|
||||
} satisfies Meta<PropsType>;
|
||||
|
||||
|
||||
@@ -210,6 +210,14 @@ export type PropsDataType = {
|
||||
>;
|
||||
|
||||
donationReceipts: ReadonlyArray<DonationReceipt>;
|
||||
|
||||
// calling internal preferences
|
||||
dredDuration: number | undefined;
|
||||
isDirectVp9Enabled: boolean | undefined;
|
||||
directMaxBitrate: number | undefined;
|
||||
isGroupVp9Enabled: boolean | undefined;
|
||||
groupMaxBitrate: number | undefined;
|
||||
sfuUrl: string | undefined;
|
||||
} & Omit<MediaDeviceSettings, 'availableCameras'>;
|
||||
|
||||
type PropsFunctionType = {
|
||||
@@ -345,6 +353,12 @@ type PropsFunctionType = {
|
||||
) => Promise<ReadonlyArray<RowType<object>>>;
|
||||
cqsTestMode: boolean;
|
||||
setCqsTestMode: (value: boolean) => void;
|
||||
setDredDuration: (value: number | undefined) => void;
|
||||
setIsDirectVp9Enabled: (value: boolean | undefined) => void;
|
||||
setDirectMaxBitrate: (value: number | undefined) => void;
|
||||
setIsGroupVp9Enabled: (value: boolean | undefined) => void;
|
||||
setGroupMaxBitrate: (value: number | undefined) => void;
|
||||
setSfuUrl: (value: string | undefined) => void;
|
||||
|
||||
// Localization
|
||||
i18n: LocalizerType;
|
||||
@@ -554,6 +568,18 @@ export function Preferences({
|
||||
__dangerouslyRunAbitraryReadOnlySqlQuery,
|
||||
cqsTestMode,
|
||||
setCqsTestMode,
|
||||
setDredDuration,
|
||||
dredDuration,
|
||||
setIsDirectVp9Enabled,
|
||||
isDirectVp9Enabled,
|
||||
setDirectMaxBitrate,
|
||||
directMaxBitrate,
|
||||
setIsGroupVp9Enabled,
|
||||
isGroupVp9Enabled,
|
||||
setGroupMaxBitrate,
|
||||
groupMaxBitrate,
|
||||
setSfuUrl,
|
||||
sfuUrl,
|
||||
}: PropsType): React.JSX.Element {
|
||||
const storiesId = useId();
|
||||
const themeSelectId = useId();
|
||||
@@ -2333,6 +2359,18 @@ export function Preferences({
|
||||
}
|
||||
cqsTestMode={cqsTestMode}
|
||||
setCqsTestMode={setCqsTestMode}
|
||||
dredDuration={dredDuration}
|
||||
setDredDuration={setDredDuration}
|
||||
setIsDirectVp9Enabled={setIsDirectVp9Enabled}
|
||||
isDirectVp9Enabled={isDirectVp9Enabled}
|
||||
setDirectMaxBitrate={setDirectMaxBitrate}
|
||||
directMaxBitrate={directMaxBitrate}
|
||||
setIsGroupVp9Enabled={setIsGroupVp9Enabled}
|
||||
isGroupVp9Enabled={isGroupVp9Enabled}
|
||||
setGroupMaxBitrate={setGroupMaxBitrate}
|
||||
groupMaxBitrate={groupMaxBitrate}
|
||||
sfuUrl={sfuUrl}
|
||||
setSfuUrl={setSfuUrl}
|
||||
/>
|
||||
}
|
||||
contentsRef={settingsPaneRef}
|
||||
|
||||
@@ -40,6 +40,19 @@ export function PreferencesInternal({
|
||||
__dangerouslyRunAbitraryReadOnlySqlQuery,
|
||||
cqsTestMode,
|
||||
setCqsTestMode,
|
||||
|
||||
dredDuration,
|
||||
setDredDuration,
|
||||
isDirectVp9Enabled,
|
||||
setIsDirectVp9Enabled,
|
||||
directMaxBitrate,
|
||||
setDirectMaxBitrate,
|
||||
isGroupVp9Enabled,
|
||||
setIsGroupVp9Enabled,
|
||||
groupMaxBitrate,
|
||||
setGroupMaxBitrate,
|
||||
sfuUrl,
|
||||
setSfuUrl,
|
||||
}: {
|
||||
i18n: LocalizerType;
|
||||
validateBackup: () => Promise<BackupValidationResultType>;
|
||||
@@ -65,6 +78,18 @@ export function PreferencesInternal({
|
||||
) => Promise<ReadonlyArray<RowType<object>>>;
|
||||
cqsTestMode: boolean;
|
||||
setCqsTestMode: (value: boolean) => void;
|
||||
dredDuration: number | undefined;
|
||||
setDredDuration: (value: number | undefined) => void;
|
||||
isDirectVp9Enabled: boolean | undefined;
|
||||
setIsDirectVp9Enabled: (value: boolean | undefined) => void;
|
||||
directMaxBitrate: number | undefined;
|
||||
setDirectMaxBitrate: (value: number | undefined) => void;
|
||||
isGroupVp9Enabled: boolean | undefined;
|
||||
setIsGroupVp9Enabled: (value: boolean | undefined) => void;
|
||||
groupMaxBitrate: number | undefined;
|
||||
setGroupMaxBitrate: (value: number | undefined) => void;
|
||||
sfuUrl: string | undefined;
|
||||
setSfuUrl: (value: string | undefined) => void;
|
||||
}): React.JSX.Element {
|
||||
const [messageCountBySchemaVersion, setMessageCountBySchemaVersion] =
|
||||
useState<MessageCountBySchemaVersionType>();
|
||||
@@ -89,6 +114,57 @@ export function PreferencesInternal({
|
||||
RowType<object>
|
||||
> | null>(null);
|
||||
|
||||
const stripAndParseString = (input: string): number | undefined => {
|
||||
const stripped = input.replace(/\D/g, '');
|
||||
return stripped.length !== 0 ? parseInt(stripped, 10) : undefined;
|
||||
};
|
||||
|
||||
const handleDredDurationUpdate = useCallback(
|
||||
(input: string) => {
|
||||
const parsed = stripAndParseString(input);
|
||||
if (parsed) {
|
||||
setDredDuration(Math.min(100, parsed));
|
||||
} else {
|
||||
setDredDuration(undefined);
|
||||
}
|
||||
},
|
||||
[setDredDuration]
|
||||
);
|
||||
const handleDirectMaxBitrateUpdate = useCallback(
|
||||
(input: string) => {
|
||||
setDirectMaxBitrate(stripAndParseString(input));
|
||||
},
|
||||
[setDirectMaxBitrate]
|
||||
);
|
||||
const handleGroupMaxBitrateUpdate = useCallback(
|
||||
(input: string) => {
|
||||
setGroupMaxBitrate(stripAndParseString(input));
|
||||
},
|
||||
[setGroupMaxBitrate]
|
||||
);
|
||||
const handleSfuUrlUpdate = useCallback(
|
||||
(input: string) => {
|
||||
const url = input.trim();
|
||||
setSfuUrl(url.length !== 0 ? url : undefined);
|
||||
},
|
||||
[setSfuUrl]
|
||||
);
|
||||
const handleResetCallingOverrides = useCallback(() => {
|
||||
setDredDuration(undefined);
|
||||
setIsDirectVp9Enabled(undefined);
|
||||
setDirectMaxBitrate(undefined);
|
||||
setIsGroupVp9Enabled(undefined);
|
||||
setGroupMaxBitrate(undefined);
|
||||
setSfuUrl(undefined);
|
||||
}, [
|
||||
setDredDuration,
|
||||
setIsDirectVp9Enabled,
|
||||
setDirectMaxBitrate,
|
||||
setIsGroupVp9Enabled,
|
||||
setGroupMaxBitrate,
|
||||
setSfuUrl,
|
||||
]);
|
||||
|
||||
const validateBackup = useCallback(async () => {
|
||||
setIsValidationPending(true);
|
||||
setValidationResult(undefined);
|
||||
@@ -559,6 +635,94 @@ export function PreferencesInternal({
|
||||
/>
|
||||
)}
|
||||
</SettingsRow>
|
||||
<SettingsRow title="Calling General">
|
||||
<FlowingSettingsControl>
|
||||
<div className="Preferences__two-thirds-flow">
|
||||
Clear custom calling preferences
|
||||
</div>
|
||||
<div className="Preferences__one-third-flow Preferences__one-third-flow--justify-end">
|
||||
<AxoButton.Root
|
||||
variant="destructive"
|
||||
size="lg"
|
||||
onClick={handleResetCallingOverrides}
|
||||
>
|
||||
Clear
|
||||
</AxoButton.Root>
|
||||
</div>
|
||||
</FlowingSettingsControl>
|
||||
<FlowingSettingsControl>
|
||||
<div className="Preferences__two-thirds-flow">
|
||||
DRED Duration (0 - 100)
|
||||
</div>
|
||||
<div className="Preferences__one-third-flow Preferences__one-third-flow--justify-end">
|
||||
<AutoSizeTextArea
|
||||
i18n={i18n}
|
||||
value={dredDuration?.toString(10)}
|
||||
onChange={handleDredDurationUpdate}
|
||||
placeholder="0 - 100"
|
||||
moduleClassName="Preferences__ReadonlySqlPlayground__Textarea"
|
||||
/>
|
||||
</div>
|
||||
</FlowingSettingsControl>
|
||||
</SettingsRow>
|
||||
<SettingsRow title="Direct Calls">
|
||||
<FlowingSettingsControl>
|
||||
<div className="Preferences__two-thirds-flow">Enable VP9</div>
|
||||
<div className="Preferences__one-third-flow Preferences__one-third-flow--justify-end">
|
||||
<AxoSwitch.Root
|
||||
checked={isDirectVp9Enabled ?? true}
|
||||
onCheckedChange={setIsDirectVp9Enabled}
|
||||
/>
|
||||
</div>
|
||||
</FlowingSettingsControl>
|
||||
<FlowingSettingsControl>
|
||||
<div className="Preferences__two-thirds-flow">Max bitrate</div>
|
||||
<div className="Preferences__one-third-flow Preferences__one-third-flow--justify-end">
|
||||
<AutoSizeTextArea
|
||||
i18n={i18n}
|
||||
value={directMaxBitrate?.toString(10)}
|
||||
onChange={handleDirectMaxBitrateUpdate}
|
||||
placeholder="Default"
|
||||
moduleClassName="Preferences__ReadonlySqlPlayground__Textarea"
|
||||
/>
|
||||
</div>
|
||||
</FlowingSettingsControl>
|
||||
</SettingsRow>
|
||||
<SettingsRow title="Group/Adhoc Calls">
|
||||
<FlowingSettingsControl>
|
||||
<div className="Preferences__two-thirds-flow">Enable VP9</div>
|
||||
<div className="Preferences__one-third-flow Preferences__one-third-flow--justify-end">
|
||||
<AxoSwitch.Root
|
||||
checked={isGroupVp9Enabled ?? false}
|
||||
onCheckedChange={setIsGroupVp9Enabled}
|
||||
/>
|
||||
</div>
|
||||
</FlowingSettingsControl>
|
||||
<FlowingSettingsControl>
|
||||
<div className="Preferences__two-thirds-flow">Max bitrate</div>
|
||||
<div className="Preferences__one-third-flow Preferences__one-third-flow--justify-end">
|
||||
<AutoSizeTextArea
|
||||
i18n={i18n}
|
||||
value={groupMaxBitrate?.toString(10)}
|
||||
onChange={handleGroupMaxBitrateUpdate}
|
||||
placeholder="Default"
|
||||
moduleClassName="Preferences__ReadonlySqlPlayground__Textarea"
|
||||
/>
|
||||
</div>
|
||||
</FlowingSettingsControl>
|
||||
<FlowingSettingsControl>
|
||||
<div className="Preferences__one-third-flow">SFU URL</div>
|
||||
<div className="Preferences__two-thirds-flow Preferences__two-thirds-flow--justify-end">
|
||||
<AutoSizeTextArea
|
||||
i18n={i18n}
|
||||
value={sfuUrl}
|
||||
onChange={handleSfuUrlUpdate}
|
||||
placeholder="https://sfu.voip.signal.org"
|
||||
moduleClassName="Preferences__ReadonlySqlPlayground__Textarea"
|
||||
/>
|
||||
</div>
|
||||
</FlowingSettingsControl>
|
||||
</SettingsRow>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -184,6 +184,9 @@ import {
|
||||
isCallFailure,
|
||||
shouldShowCallQualitySurvey,
|
||||
} from '../util/callQualitySurvey.dom.js';
|
||||
import * as RemoteConfig from '../RemoteConfig.dom.js';
|
||||
import { isAlpha, isBeta, isProduction } from '../util/version.std.js';
|
||||
import { parseIntOrThrow } from '../util/parseIntOrThrow.std.js';
|
||||
|
||||
const { i18n } = window.SignalContext;
|
||||
|
||||
@@ -572,8 +575,11 @@ export class CallingClass {
|
||||
#localPreviewContainer: HTMLDivElement | undefined;
|
||||
#localPreview: HTMLVideoElement | undefined;
|
||||
#reduxInterface?: CallingReduxInterface;
|
||||
#_sfuUrl?: string;
|
||||
|
||||
public _sfuUrl?: string;
|
||||
public get sfuUrl(): string | undefined {
|
||||
return itemStorage.get('sfuUrl') ?? this.#_sfuUrl;
|
||||
}
|
||||
|
||||
public _iceServerOverride?: GetIceServersResultType | string;
|
||||
|
||||
@@ -606,7 +612,7 @@ export class CallingClass {
|
||||
throw new Error('CallingClass.initialize: Invalid uxActions.');
|
||||
}
|
||||
|
||||
this._sfuUrl = sfuUrl;
|
||||
this.#_sfuUrl = sfuUrl;
|
||||
|
||||
RingRTC.setConfig({
|
||||
field_trials: undefined,
|
||||
@@ -851,11 +857,11 @@ export class CallingClass {
|
||||
|
||||
async createCallLink(): Promise<CallLinkType> {
|
||||
strictAssert(
|
||||
this._sfuUrl,
|
||||
this.sfuUrl,
|
||||
'createCallLink() missing SFU URL; not creating call link'
|
||||
);
|
||||
|
||||
const sfuUrl = this._sfuUrl;
|
||||
const { sfuUrl } = this;
|
||||
const userId = Aci.parseFromServiceIdString(
|
||||
itemStorage.user.getCheckedAci()
|
||||
);
|
||||
@@ -936,11 +942,11 @@ export class CallingClass {
|
||||
|
||||
async deleteCallLink(callLink: CallLinkType): Promise<void> {
|
||||
strictAssert(
|
||||
this._sfuUrl,
|
||||
this.sfuUrl,
|
||||
'createCallLink() missing SFU URL; not deleting call link'
|
||||
);
|
||||
|
||||
const sfuUrl = this._sfuUrl;
|
||||
const { sfuUrl } = this;
|
||||
const logId = `deleteCallLink(${callLink.roomId})`;
|
||||
log.info(logId);
|
||||
|
||||
@@ -973,10 +979,10 @@ export class CallingClass {
|
||||
name: string
|
||||
): Promise<CallLinkStateType> {
|
||||
strictAssert(
|
||||
this._sfuUrl,
|
||||
this.sfuUrl,
|
||||
'updateCallLinkName() missing SFU URL; not update call link name'
|
||||
);
|
||||
const sfuUrl = this._sfuUrl;
|
||||
const { sfuUrl } = this;
|
||||
const logId = `updateCallLinkName(${callLink.roomId})`;
|
||||
|
||||
log.info(`${logId}: Updating call link name`);
|
||||
@@ -1011,10 +1017,10 @@ export class CallingClass {
|
||||
restrictions: CallLinkRestrictions
|
||||
): Promise<CallLinkStateType> {
|
||||
strictAssert(
|
||||
this._sfuUrl,
|
||||
this.sfuUrl,
|
||||
'updateCallLinkRestrictions() missing SFU URL; not update call link restrictions'
|
||||
);
|
||||
const sfuUrl = this._sfuUrl;
|
||||
const { sfuUrl } = this;
|
||||
const logId = `updateCallLinkRestrictions(${callLink.roomId})`;
|
||||
|
||||
log.info(`${logId}: Updating call link restrictions`);
|
||||
@@ -1054,7 +1060,7 @@ export class CallingClass {
|
||||
async readCallLink(
|
||||
callLinkRootKey: CallLinkRootKey
|
||||
): Promise<CallLinkStateType | null> {
|
||||
if (!this._sfuUrl) {
|
||||
if (!this.sfuUrl) {
|
||||
throw new Error('readCallLink() missing SFU URL; not handling call link');
|
||||
}
|
||||
|
||||
@@ -1066,7 +1072,7 @@ export class CallingClass {
|
||||
await getCallLinkAuthCredentialPresentation(callLinkRootKey);
|
||||
|
||||
const result = await RingRTC.readCallLink(
|
||||
this._sfuUrl,
|
||||
this.sfuUrl,
|
||||
authCredentialPresentation.serialize(),
|
||||
callLinkRootKey
|
||||
);
|
||||
@@ -1315,7 +1321,7 @@ export class CallingClass {
|
||||
return statefulPeekInfo;
|
||||
}
|
||||
|
||||
if (!this._sfuUrl) {
|
||||
if (!this.sfuUrl) {
|
||||
throw new Error('Missing SFU URL; not peeking group call');
|
||||
}
|
||||
|
||||
@@ -1338,7 +1344,7 @@ export class CallingClass {
|
||||
const membershipProof = Bytes.fromString(proof);
|
||||
|
||||
return RingRTC.peekGroupCall(
|
||||
this._sfuUrl,
|
||||
this.sfuUrl,
|
||||
membershipProof,
|
||||
this.#getGroupCallMembers(conversationId)
|
||||
);
|
||||
@@ -1360,7 +1366,7 @@ export class CallingClass {
|
||||
);
|
||||
}
|
||||
|
||||
if (!this._sfuUrl) {
|
||||
if (!this.sfuUrl) {
|
||||
throw new Error('Missing SFU URL; not peeking call link call');
|
||||
}
|
||||
|
||||
@@ -1369,7 +1375,7 @@ export class CallingClass {
|
||||
await getCallLinkAuthCredentialPresentation(callLinkRootKey);
|
||||
|
||||
const result = await RingRTC.peekCallLinkCall(
|
||||
this._sfuUrl,
|
||||
this.sfuUrl,
|
||||
authCredentialPresentation.serialize(),
|
||||
callLinkRootKey
|
||||
);
|
||||
@@ -1412,7 +1418,7 @@ export class CallingClass {
|
||||
return existing;
|
||||
}
|
||||
|
||||
if (!this._sfuUrl) {
|
||||
if (!this.sfuUrl) {
|
||||
throw new Error('Missing SFU URL; not connecting group call');
|
||||
}
|
||||
|
||||
@@ -1420,16 +1426,16 @@ export class CallingClass {
|
||||
log.info(logId);
|
||||
|
||||
const groupIdBuffer = Bytes.fromBase64(groupId);
|
||||
const dredDuration = 0;
|
||||
|
||||
let isRequestingMembershipProof = false;
|
||||
const config = this.#getRemoteAndOverrideConfigValues();
|
||||
|
||||
const outerGroupCall = RingRTC.getGroupCall(
|
||||
groupIdBuffer,
|
||||
this._sfuUrl,
|
||||
this.sfuUrl,
|
||||
new Uint8Array(),
|
||||
AUDIO_LEVEL_INTERVAL_MS,
|
||||
dredDuration,
|
||||
config.dredDuration,
|
||||
{
|
||||
...this.#getGroupCallObserver(conversationId, CallMode.Group),
|
||||
async requestMembershipProof(groupCall) {
|
||||
@@ -1496,23 +1502,22 @@ export class CallingClass {
|
||||
const logId = `connectCallLinkCall(${roomId}`;
|
||||
log.info(logId);
|
||||
|
||||
if (!this._sfuUrl) {
|
||||
if (!this.sfuUrl) {
|
||||
throw new Error(
|
||||
`${logId}: Missing SFU URL; not connecting group call link call`
|
||||
);
|
||||
}
|
||||
|
||||
const dredDuration = 0;
|
||||
const config = this.#getRemoteAndOverrideConfigValues();
|
||||
|
||||
const outerGroupCall = RingRTC.getCallLinkCall(
|
||||
this._sfuUrl,
|
||||
this.sfuUrl,
|
||||
endorsementsPublicKey,
|
||||
authCredentialPresentation.serialize(),
|
||||
callLinkRootKey,
|
||||
adminPasskey,
|
||||
new Uint8Array(),
|
||||
AUDIO_LEVEL_INTERVAL_MS,
|
||||
dredDuration,
|
||||
config.dredDuration,
|
||||
this.#getGroupCallObserver(roomId, CallMode.Adhoc)
|
||||
);
|
||||
|
||||
@@ -3863,6 +3868,59 @@ export class CallingClass {
|
||||
return null;
|
||||
}
|
||||
|
||||
#getRemoteAndOverrideConfigValues(): {
|
||||
dredDuration: number | undefined;
|
||||
isDirectVp9Enabled: boolean | undefined;
|
||||
directMaxBitrate: number | undefined;
|
||||
isGroupVp9Enabled: boolean | undefined;
|
||||
groupMaxBitrate: number | undefined;
|
||||
} {
|
||||
function dredDuration(version: string): number | undefined {
|
||||
const override = itemStorage.get('dredDuration');
|
||||
if (override) {
|
||||
return override;
|
||||
}
|
||||
|
||||
if (isProduction(version)) {
|
||||
return tryParseInt(
|
||||
RemoteConfig.getValue('desktop.calling.dredDuration.prod')
|
||||
);
|
||||
}
|
||||
|
||||
if (isBeta(version)) {
|
||||
return tryParseInt(
|
||||
RemoteConfig.getValue('desktop.calling.dredDuration.beta')
|
||||
);
|
||||
}
|
||||
|
||||
if (isAlpha(version)) {
|
||||
return tryParseInt(
|
||||
RemoteConfig.getValue('desktop.calling.dredDuration.alpha')
|
||||
);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function tryParseInt(v: string | undefined): number | undefined {
|
||||
try {
|
||||
return parseIntOrThrow(v, 'invalid');
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const version = window.SignalContext.getVersion();
|
||||
|
||||
return {
|
||||
dredDuration: dredDuration(version),
|
||||
isDirectVp9Enabled: itemStorage.get('isDirectVp9Enabled'),
|
||||
directMaxBitrate: itemStorage.get('directMaxBitrate'),
|
||||
isGroupVp9Enabled: itemStorage.get('isGroupVp9Enabled'),
|
||||
groupMaxBitrate: itemStorage.get('directMaxBitrate'),
|
||||
};
|
||||
}
|
||||
|
||||
async #getIceServers(): Promise<Array<IceServerType>> {
|
||||
function iceServerConfigToList(
|
||||
iceServerConfig: GetIceServersResultType
|
||||
@@ -3964,6 +4022,7 @@ export class CallingClass {
|
||||
}
|
||||
|
||||
const iceServers = await this.#getIceServers();
|
||||
const config = this.#getRemoteAndOverrideConfigValues();
|
||||
|
||||
// We do this again, since getIceServers is a call that can take some time
|
||||
if (call.endedReason) {
|
||||
@@ -3984,7 +4043,7 @@ export class CallingClass {
|
||||
hideIp: shouldRelayCalls || isContactUntrusted,
|
||||
dataMode: DataMode.Normal,
|
||||
audioLevelsIntervalMillis: AUDIO_LEVEL_INTERVAL_MS,
|
||||
dredDuration: 0,
|
||||
dredDuration: config.dredDuration,
|
||||
};
|
||||
|
||||
log.info('CallingClass.handleStartCall(): Proceeding');
|
||||
|
||||
@@ -784,6 +784,25 @@ export function SmartPreferences(): React.JSX.Element | null {
|
||||
drop(itemStorage.put('cqsTestMode', value));
|
||||
}, []);
|
||||
|
||||
const setDredDuration = useCallback((value: number | undefined) => {
|
||||
drop(itemStorage.put('dredDuration', value));
|
||||
}, []);
|
||||
const setIsDirectVp9Enabled = useCallback((value: boolean | undefined) => {
|
||||
drop(itemStorage.put('isDirectVp9Enabled', value));
|
||||
}, []);
|
||||
const setDirectMaxBitrate = useCallback((value: number | undefined) => {
|
||||
drop(itemStorage.put('directMaxBitrate', value));
|
||||
}, []);
|
||||
const setIsGroupVp9Enabled = useCallback((value: boolean | undefined) => {
|
||||
drop(itemStorage.put('isGroupVp9Enabled', value));
|
||||
}, []);
|
||||
const setGroupMaxBitrate = useCallback((value: number | undefined) => {
|
||||
drop(itemStorage.put('groupMaxBitrate', value));
|
||||
}, []);
|
||||
const setSfuUrl = useCallback((value: string | undefined) => {
|
||||
drop(itemStorage.put('sfuUrl', value));
|
||||
}, []);
|
||||
|
||||
if (currentLocation.tab !== NavTab.Settings) {
|
||||
return null;
|
||||
}
|
||||
@@ -998,6 +1017,18 @@ export function SmartPreferences(): React.JSX.Element | null {
|
||||
}
|
||||
cqsTestMode={cqsTestMode}
|
||||
setCqsTestMode={setCqsTestMode}
|
||||
dredDuration={items.dredDuration}
|
||||
setDredDuration={setDredDuration}
|
||||
setIsDirectVp9Enabled={setIsDirectVp9Enabled}
|
||||
isDirectVp9Enabled={items.isDirectVp9Enabled}
|
||||
setDirectMaxBitrate={setDirectMaxBitrate}
|
||||
directMaxBitrate={items.directMaxBitrate}
|
||||
setIsGroupVp9Enabled={setIsGroupVp9Enabled}
|
||||
isGroupVp9Enabled={items.isGroupVp9Enabled}
|
||||
setGroupMaxBitrate={setGroupMaxBitrate}
|
||||
groupMaxBitrate={items.groupMaxBitrate}
|
||||
sfuUrl={items.sfuUrl}
|
||||
setSfuUrl={setSfuUrl}
|
||||
/>
|
||||
</AxoProvider>
|
||||
</StrictMode>
|
||||
|
||||
@@ -291,6 +291,14 @@ export type StorageAccessType = {
|
||||
defaultDimWallpaperInDarkMode: boolean;
|
||||
defaultAutoBubbleColor: boolean;
|
||||
|
||||
// Used for manually controlling calling settings
|
||||
dredDuration: number | undefined;
|
||||
isDirectVp9Enabled: boolean | undefined;
|
||||
directMaxBitrate: number | undefined;
|
||||
isGroupVp9Enabled: boolean | undefined;
|
||||
groupMaxBitrate: number | undefined;
|
||||
sfuUrl: string | undefined;
|
||||
|
||||
// Deprecated
|
||||
'challenge:retry-message-ids': never;
|
||||
nextSignedKeyRotationTime: number;
|
||||
@@ -514,6 +522,12 @@ const STORAGE_KEYS_TO_REMOVE_AFTER_UNLINK = [
|
||||
'backupMediaDownloadIdle',
|
||||
'callQualitySurveyCooldownDisabled',
|
||||
'localDeleteWarningShown',
|
||||
'dredDuration',
|
||||
'directMaxBitrate',
|
||||
'isDirectVp9Enabled',
|
||||
'groupMaxBitrate',
|
||||
'isGroupVp9Enabled',
|
||||
'sfuUrl',
|
||||
] as const satisfies ReadonlyArray<keyof StorageAccessType>;
|
||||
|
||||
// Ensure every storage key is explicitly marked to be preserved or removed on unlink.
|
||||
|
||||
@@ -87,7 +87,7 @@ if (
|
||||
return message?.attributes;
|
||||
},
|
||||
getReduxState: () => window.reduxStore.getState(),
|
||||
getSfuUrl: () => calling._sfuUrl,
|
||||
getSfuUrl: () => calling.sfuUrl,
|
||||
getIceServerOverride: () => calling._iceServerOverride,
|
||||
getSocketStatus: () => getSocketStatus(),
|
||||
getStorageItem: (name: keyof StorageAccessType) => itemStorage.get(name),
|
||||
@@ -101,8 +101,8 @@ if (
|
||||
}
|
||||
window.Flags[name] = value;
|
||||
},
|
||||
setSfuUrl: (url: string) => {
|
||||
calling._sfuUrl = url;
|
||||
setSfuUrl: async (url: string) => {
|
||||
await itemStorage.put('sfuUrl', url);
|
||||
},
|
||||
setIceServerOverride: (
|
||||
override: GetIceServersResultType | string | undefined
|
||||
|
||||
Reference in New Issue
Block a user