From 59a4f237fd6c79542eead617861505293db5d33f Mon Sep 17 00:00:00 2001 From: Jim Gustafson Date: Wed, 1 Nov 2023 11:03:08 -0700 Subject: [PATCH] Preload media devices to avoid later delay Co-authored-by: ayumi yu --- app/main.ts | 9 +++++++++ ts/services/calling.ts | 21 +++++++++++++++++++++ ts/util/createIPCEvents.ts | 8 ++++++++ ts/window.d.ts | 3 +++ ts/windows/main/phase1-ipc.ts | 2 ++ 5 files changed, 43 insertions(+) diff --git a/app/main.ts b/app/main.ts index a68dbdafe8..fd76ecc8f7 100644 --- a/app/main.ts +++ b/app/main.ts @@ -2653,6 +2653,15 @@ async function ensureFilePermissions(onlyFiles?: Array) { getLogger().info(`Finish ensuring permissions in ${Date.now() - start}ms`); } +ipc.handle('get-media-access-status', async (_event, value) => { + // This function is not supported on Linux + if (!systemPreferences.getMediaAccessStatus) { + return undefined; + } + + return systemPreferences.getMediaAccessStatus(value); +}); + ipc.handle('get-auto-launch', async () => { return app.getLoginItemSettings(await getDefaultLoginItemSettings()) .openAtLogin; diff --git a/ts/services/calling.ts b/ts/services/calling.ts index 2eada3c7a8..43ad3b4ee0 100644 --- a/ts/services/calling.ts +++ b/ts/services/calling.ts @@ -383,6 +383,10 @@ export class CallingClass { }); void this.cleanExpiredGroupCallRingsAndLoop(); + + if (process.platform === 'darwin') { + drop(this.enumerateMediaDevices()); + } } private attemptToGiveOurServiceIdToRingRtc(): void { @@ -2433,6 +2437,23 @@ export class CallingClass { void this.cleanExpiredGroupCallRingsAndLoop(); }, CLEAN_EXPIRED_GROUP_CALL_RINGS_INTERVAL); } + + // MacOS: Preload devices to work around delay when first entering call lobby + // https://bugs.chromium.org/p/chromium/issues/detail?id=1287628 + private async enumerateMediaDevices(): Promise { + try { + const microphoneStatus = await window.IPC.getMediaAccessStatus( + 'microphone' + ); + if (microphoneStatus !== 'granted') { + return; + } + + drop(window.navigator.mediaDevices.enumerateDevices()); + } catch (error) { + log.error('enumerateMediaDevices failed:', Errors.toLogFormat(error)); + } + } } export const calling = new CallingClass(); diff --git a/ts/util/createIPCEvents.ts b/ts/util/createIPCEvents.ts index 2f23c6f500..695573ca00 100644 --- a/ts/util/createIPCEvents.ts +++ b/ts/util/createIPCEvents.ts @@ -108,6 +108,9 @@ export type IPCEventsCallbacksType = { deleteAllMyStories: () => Promise; editCustomColor: (colorId: string, customColor: CustomColorType) => void; getConversationsWithCustomColor: (x: string) => Array; + getMediaAccessStatus: ( + mediaType: 'screen' | 'microphone' | 'camera' + ) => Promise; installStickerPack: (packId: string, key: string) => Promise; isFormattingFlagEnabled: () => boolean; isPhoneNumberSharingEnabled: () => boolean; @@ -609,6 +612,11 @@ export function createIPCEvents( showWhatsNewModal(); }, + getMediaAccessStatus: async ( + mediaType: 'screen' | 'microphone' | 'camera' + ) => { + return window.IPC.getMediaAccessStatus(mediaType); + }, getMediaPermissions: window.IPC.getMediaPermissions, getMediaCameraPermissions: window.IPC.getMediaCameraPermissions, diff --git a/ts/window.d.ts b/ts/window.d.ts index 7d10164c36..2329338ee4 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -66,6 +66,9 @@ export type IPCType = { }; drawAttention: () => void; getAutoLaunch: () => Promise; + getMediaAccessStatus: ( + mediaType: 'screen' | 'microphone' | 'camera' + ) => Promise; getMediaCameraPermissions: () => Promise; getMediaPermissions: () => Promise; logAppLoadedEvent?: (options: { processedCount?: number }) => void; diff --git a/ts/windows/main/phase1-ipc.ts b/ts/windows/main/phase1-ipc.ts index 5abad790c8..8739404251 100644 --- a/ts/windows/main/phase1-ipc.ts +++ b/ts/windows/main/phase1-ipc.ts @@ -86,6 +86,8 @@ const IPC: IPCType = { ipc.send('draw-attention'); }, getAutoLaunch: () => ipc.invoke('get-auto-launch'), + getMediaAccessStatus: mediaType => + ipc.invoke('get-media-access-status', mediaType), getMediaPermissions: () => ipc.invoke('settings:get:mediaPermissions'), getMediaCameraPermissions: () => ipc.invoke('settings:get:mediaCameraPermissions'),