signal-desktop/ts/windows/settings/preload.ts

462 lines
16 KiB
TypeScript
Raw Normal View History

2023-01-03 19:55:46 +00:00
// Copyright 2021 Signal Messenger, LLC
2021-08-18 20:08:14 +00:00
// SPDX-License-Identifier: AGPL-3.0-only
import { contextBridge, ipcRenderer, webFrame } from 'electron';
import { MinimalSignalContext } from '../minimalContext';
2021-08-18 20:08:14 +00:00
import type { PropsPreloadType } from '../../components/Preferences';
import OS from '../../util/os/osPreload';
2021-08-18 20:08:14 +00:00
import * as Settings from '../../types/Settings';
import {
SystemTraySetting,
parseSystemTraySetting,
shouldMinimizeToSystemTray,
} from '../../types/SystemTraySetting';
import { awaitObject } from '../../util/awaitObject';
2022-11-16 20:18:02 +00:00
import { DurationInSeconds } from '../../util/durations';
2021-08-18 20:08:14 +00:00
import { createSetting, createCallback } from '../../util/preload';
function doneRendering() {
ipcRenderer.send('settings-done-rendering');
}
2021-08-18 20:08:14 +00:00
const settingMessageAudio = createSetting('audioMessage');
2021-08-18 20:08:14 +00:00
const settingAudioNotification = createSetting('audioNotification');
const settingAutoDownloadUpdate = createSetting('autoDownloadUpdate');
2021-08-18 20:08:14 +00:00
const settingAutoLaunch = createSetting('autoLaunch');
const settingCallRingtoneNotification = createSetting(
'callRingtoneNotification'
);
const settingCallSystemNotification = createSetting('callSystemNotification');
const settingCountMutedConversations = createSetting('countMutedConversations');
const settingDeviceName = createSetting('deviceName', { setter: false });
const settingHideMenuBar = createSetting('hideMenuBar');
const settingIncomingCallNotification = createSetting(
'incomingCallNotification'
);
const settingMediaCameraPermissions = createSetting('mediaCameraPermissions');
const settingMediaPermissions = createSetting('mediaPermissions');
const settingNotificationDrawAttention = createSetting(
'notificationDrawAttention'
);
const settingNotificationSetting = createSetting('notificationSetting');
const settingRelayCalls = createSetting('alwaysRelayCalls');
const settingSentMediaQuality = createSetting('sentMediaQualitySetting');
const settingSpellCheck = createSetting('spellCheck');
const settingTextFormatting = createSetting('textFormatting');
2021-08-18 20:08:14 +00:00
const settingTheme = createSetting('themeSetting');
const settingSystemTraySetting = createSetting('systemTraySetting');
2023-11-06 21:19:23 +00:00
const settingLocaleOverride = createSetting('localeOverride');
2021-08-18 20:08:14 +00:00
const settingLastSyncTime = createSetting('lastSyncTime');
const settingHasStoriesDisabled = createSetting('hasStoriesDisabled');
2021-08-18 20:08:14 +00:00
const settingZoomFactor = createSetting('zoomFactor');
// Getters only.
const settingBlockedCount = createSetting('blockedCount');
const settingLinkPreview = createSetting('linkPreviewSetting', {
setter: false,
});
const settingPhoneNumberDiscoverability = createSetting(
2023-02-23 21:32:19 +00:00
'phoneNumberDiscoverabilitySetting'
2021-08-18 20:08:14 +00:00
);
2023-02-23 21:32:19 +00:00
const settingPhoneNumberSharing = createSetting('phoneNumberSharingSetting');
2021-08-18 20:08:14 +00:00
const settingReadReceipts = createSetting('readReceiptSetting', {
setter: false,
});
const settingTypingIndicators = createSetting('typingIndicatorSetting', {
setter: false,
});
// Media settings
const settingAudioInput = createSetting('preferredAudioInputDevice');
const settingAudioOutput = createSetting('preferredAudioOutputDevice');
const settingVideoInput = createSetting('preferredVideoInputDevice');
const settingUniversalExpireTimer = createSetting('universalExpireTimer');
// Callbacks
const ipcGetAvailableIODevices = createCallback('getAvailableIODevices');
const ipcGetCustomColors = createCallback('getCustomColors');
const ipcIsFormattingFlagEnabled = createCallback('isFormattingFlagEnabled');
2021-08-18 20:08:14 +00:00
const ipcIsSyncNotSupported = createCallback('isPrimary');
const ipcMakeSyncRequest = createCallback('syncRequest');
2021-08-19 01:04:38 +00:00
const ipcPNP = createCallback('isPhoneNumberSharingEnabled');
2022-07-20 00:47:05 +00:00
const ipcShouldShowStoriesSettings = createCallback(
'shouldShowStoriesSettings'
);
const ipcDeleteAllMyStories = createCallback('deleteAllMyStories');
2021-08-18 20:08:14 +00:00
// ChatColorPicker redux hookups
// The redux actions update over IPC through a preferences re-render
const ipcGetDefaultConversationColor = createCallback(
'getDefaultConversationColor'
);
const ipcGetConversationsWithCustomColor = createCallback(
'getConversationsWithCustomColor'
);
const ipcAddCustomColor = createCallback('addCustomColor');
const ipcEditCustomColor = createCallback('editCustomColor');
const ipcRemoveCustomColor = createCallback('removeCustomColor');
const ipcRemoveCustomColorOnConversations = createCallback(
'removeCustomColorOnConversations'
);
const ipcResetAllChatColors = createCallback('resetAllChatColors');
const ipcResetDefaultChatColor = createCallback('resetDefaultChatColor');
const ipcSetGlobalDefaultConversationColor = createCallback(
'setGlobalDefaultConversationColor'
);
const DEFAULT_NOTIFICATION_SETTING = 'message';
2021-11-11 22:43:05 +00:00
function getSystemTraySettingValues(systemTraySetting: SystemTraySetting): {
2021-08-18 20:08:14 +00:00
hasMinimizeToAndStartInSystemTray: boolean;
hasMinimizeToSystemTray: boolean;
} {
const parsedSystemTraySetting = parseSystemTraySetting(systemTraySetting);
const hasMinimizeToAndStartInSystemTray =
parsedSystemTraySetting ===
SystemTraySetting.MinimizeToAndStartInSystemTray;
const hasMinimizeToSystemTray = shouldMinimizeToSystemTray(
parsedSystemTraySetting
);
return {
hasMinimizeToAndStartInSystemTray,
hasMinimizeToSystemTray,
};
}
let renderInBrowser = (_props: PropsPreloadType): void => {
throw new Error('render is not defined');
};
function attachRenderCallback<Value>(f: (value: Value) => Promise<Value>) {
return async (value: Value) => {
await f(value);
void renderPreferences();
};
}
async function renderPreferences() {
2021-08-18 20:08:14 +00:00
const {
blockedCount,
deviceName,
hasAudioNotifications,
hasAutoDownloadUpdate,
2021-08-18 20:08:14 +00:00
hasAutoLaunch,
hasCallNotifications,
hasCallRingtoneNotification,
hasCountMutedConversations,
hasHideMenuBar,
hasIncomingCallNotifications,
hasLinkPreviews,
hasMediaCameraPermissions,
hasMediaPermissions,
hasMessageAudio,
2021-08-18 20:08:14 +00:00
hasNotificationAttention,
hasReadReceipts,
hasRelayCalls,
hasSpellCheck,
hasStoriesDisabled,
hasTextFormatting,
2021-08-18 20:08:14 +00:00
hasTypingIndicators,
isFormattingFlagEnabled,
2021-08-19 01:04:38 +00:00
isPhoneNumberSharingSupported,
2021-08-18 20:08:14 +00:00
lastSyncTime,
notificationContent,
selectedCamera,
selectedMicrophone,
selectedSpeaker,
sentMediaQualitySetting,
2023-11-06 21:19:23 +00:00
localeOverride,
2021-08-18 20:08:14 +00:00
systemTraySetting,
themeSetting,
universalExpireTimer,
whoCanFindMe,
whoCanSeeMe,
zoomFactor,
availableIODevices,
customColors,
defaultConversationColor,
2022-07-20 00:47:05 +00:00
isSyncNotSupported,
shouldShowStoriesSettings,
2021-08-18 20:08:14 +00:00
} = await awaitObject({
blockedCount: settingBlockedCount.getValue(),
deviceName: settingDeviceName.getValue(),
hasAudioNotifications: settingAudioNotification.getValue(),
hasAutoDownloadUpdate: settingAutoDownloadUpdate.getValue(),
2021-08-18 20:08:14 +00:00
hasAutoLaunch: settingAutoLaunch.getValue(),
hasCallNotifications: settingCallSystemNotification.getValue(),
hasCallRingtoneNotification: settingCallRingtoneNotification.getValue(),
hasCountMutedConversations: settingCountMutedConversations.getValue(),
hasHideMenuBar: settingHideMenuBar.getValue(),
hasIncomingCallNotifications: settingIncomingCallNotification.getValue(),
hasLinkPreviews: settingLinkPreview.getValue(),
hasMediaCameraPermissions: settingMediaCameraPermissions.getValue(),
hasMediaPermissions: settingMediaPermissions.getValue(),
hasMessageAudio: settingMessageAudio.getValue(),
2021-08-18 20:08:14 +00:00
hasNotificationAttention: settingNotificationDrawAttention.getValue(),
hasReadReceipts: settingReadReceipts.getValue(),
hasRelayCalls: settingRelayCalls.getValue(),
hasSpellCheck: settingSpellCheck.getValue(),
hasStoriesDisabled: settingHasStoriesDisabled.getValue(),
hasTextFormatting: settingTextFormatting.getValue(),
2021-08-18 20:08:14 +00:00
hasTypingIndicators: settingTypingIndicators.getValue(),
2021-08-19 01:04:38 +00:00
isPhoneNumberSharingSupported: ipcPNP(),
2021-08-18 20:08:14 +00:00
lastSyncTime: settingLastSyncTime.getValue(),
notificationContent: settingNotificationSetting.getValue(),
selectedCamera: settingVideoInput.getValue(),
selectedMicrophone: settingAudioInput.getValue(),
selectedSpeaker: settingAudioOutput.getValue(),
sentMediaQualitySetting: settingSentMediaQuality.getValue(),
2023-11-06 21:19:23 +00:00
localeOverride: settingLocaleOverride.getValue(),
2021-08-18 20:08:14 +00:00
systemTraySetting: settingSystemTraySetting.getValue(),
themeSetting: settingTheme.getValue(),
universalExpireTimer: settingUniversalExpireTimer.getValue(),
whoCanFindMe: settingPhoneNumberDiscoverability.getValue(),
whoCanSeeMe: settingPhoneNumberSharing.getValue(),
zoomFactor: settingZoomFactor.getValue(),
// Callbacks
availableIODevices: ipcGetAvailableIODevices(),
customColors: ipcGetCustomColors(),
defaultConversationColor: ipcGetDefaultConversationColor(),
isFormattingFlagEnabled: ipcIsFormattingFlagEnabled(),
2022-07-20 00:47:05 +00:00
isSyncNotSupported: ipcIsSyncNotSupported(),
shouldShowStoriesSettings: ipcShouldShowStoriesSettings(),
2021-08-18 20:08:14 +00:00
});
2021-11-11 22:43:05 +00:00
const { availableCameras, availableMicrophones, availableSpeakers } =
availableIODevices;
2021-08-18 20:08:14 +00:00
2021-11-11 22:43:05 +00:00
const { hasMinimizeToAndStartInSystemTray, hasMinimizeToSystemTray } =
getSystemTraySettingValues(systemTraySetting);
2021-08-18 20:08:14 +00:00
const onUniversalExpireTimerChange = attachRenderCallback(
2022-11-16 20:18:02 +00:00
settingUniversalExpireTimer.setValue
);
2023-11-06 21:19:23 +00:00
const availableLocales = MinimalSignalContext.getI18nAvailableLocales();
const resolvedLocale = MinimalSignalContext.getI18nLocale();
const preferredSystemLocales =
MinimalSignalContext.getPreferredSystemLocales();
2021-08-18 20:08:14 +00:00
const props = {
// Settings
availableCameras,
2023-11-06 21:19:23 +00:00
availableLocales,
2021-08-18 20:08:14 +00:00
availableMicrophones,
availableSpeakers,
blockedCount,
customColors,
defaultConversationColor,
deviceName,
hasAudioNotifications,
hasAutoDownloadUpdate,
2021-08-18 20:08:14 +00:00
hasAutoLaunch,
hasCallNotifications,
hasCallRingtoneNotification,
hasCountMutedConversations,
hasHideMenuBar,
hasIncomingCallNotifications,
hasLinkPreviews,
hasMediaCameraPermissions,
hasMediaPermissions,
hasMessageAudio,
2021-08-18 20:08:14 +00:00
hasMinimizeToAndStartInSystemTray,
hasMinimizeToSystemTray,
hasNotificationAttention,
hasNotifications: notificationContent !== 'off',
hasReadReceipts,
hasRelayCalls,
hasSpellCheck,
hasStoriesDisabled,
hasTextFormatting,
2021-08-18 20:08:14 +00:00
hasTypingIndicators,
lastSyncTime,
2023-11-06 21:19:23 +00:00
localeOverride,
2021-08-18 20:08:14 +00:00
notificationContent,
2023-11-06 21:19:23 +00:00
preferredSystemLocales,
resolvedLocale,
2021-08-18 20:08:14 +00:00
selectedCamera,
selectedMicrophone,
selectedSpeaker,
sentMediaQualitySetting,
2021-08-18 20:08:14 +00:00
themeSetting,
2022-11-16 20:18:02 +00:00
universalExpireTimer: DurationInSeconds.fromSeconds(universalExpireTimer),
2021-08-18 20:08:14 +00:00
whoCanFindMe,
whoCanSeeMe,
zoomFactor,
// Actions and other props
addCustomColor: ipcAddCustomColor,
closeSettings: () => MinimalSignalContext.executeMenuRole('close'),
2021-08-18 20:08:14 +00:00
doDeleteAllData: () => ipcRenderer.send('delete-all-data'),
doneRendering,
2021-08-18 20:08:14 +00:00
editCustomColor: ipcEditCustomColor,
getConversationsWithCustomColor: ipcGetConversationsWithCustomColor,
initialSpellCheckSetting:
MinimalSignalContext.config.appStartInitialSpellcheckSetting,
2021-08-18 20:08:14 +00:00
makeSyncRequest: ipcMakeSyncRequest,
removeCustomColor: ipcRemoveCustomColor,
removeCustomColorOnConversations: ipcRemoveCustomColorOnConversations,
resetAllChatColors: ipcResetAllChatColors,
resetDefaultChatColor: ipcResetDefaultChatColor,
setGlobalDefaultConversationColor: ipcSetGlobalDefaultConversationColor,
2022-07-20 00:47:05 +00:00
shouldShowStoriesSettings,
2021-08-18 20:08:14 +00:00
// Limited support features
isAutoDownloadUpdatesSupported: Settings.isAutoDownloadUpdatesSupported(OS),
isAutoLaunchSupported: Settings.isAutoLaunchSupported(OS),
isHideMenuBarSupported: Settings.isHideMenuBarSupported(OS),
isNotificationAttentionSupported: Settings.isDrawAttentionSupported(OS),
2021-08-19 01:04:38 +00:00
isPhoneNumberSharingSupported,
2021-08-18 20:08:14 +00:00
isSyncSupported: !isSyncNotSupported,
isSystemTraySupported: Settings.isSystemTraySupported(
OS,
MinimalSignalContext.getVersion()
),
2022-09-06 22:09:52 +00:00
isMinimizeToAndStartInSystemTraySupported:
Settings.isMinimizeToAndStartInSystemTraySupported(
OS,
MinimalSignalContext.getVersion()
2022-09-06 22:09:52 +00:00
),
2021-08-18 20:08:14 +00:00
// Feature flags
isFormattingFlagEnabled,
2021-08-18 20:08:14 +00:00
// Change handlers
onAudioNotificationsChange: attachRenderCallback(
settingAudioNotification.setValue
),
onAutoDownloadUpdateChange: attachRenderCallback(
settingAutoDownloadUpdate.setValue
),
onAutoLaunchChange: attachRenderCallback(settingAutoLaunch.setValue),
onCallNotificationsChange: attachRenderCallback(
settingCallSystemNotification.setValue
),
onCallRingtoneNotificationChange: attachRenderCallback(
2021-08-18 20:08:14 +00:00
settingCallRingtoneNotification.setValue
),
onCountMutedConversationsChange: attachRenderCallback(
2021-08-18 20:08:14 +00:00
settingCountMutedConversations.setValue
),
onHasStoriesDisabledChanged: attachRenderCallback(
async (value: boolean) => {
await settingHasStoriesDisabled.setValue(value);
if (!value) {
void ipcDeleteAllMyStories();
}
return value;
}
),
onHideMenuBarChange: attachRenderCallback(settingHideMenuBar.setValue),
onIncomingCallNotificationsChange: attachRenderCallback(
2021-08-18 20:08:14 +00:00
settingIncomingCallNotification.setValue
),
onLastSyncTimeChange: attachRenderCallback(settingLastSyncTime.setValue),
2023-11-06 21:19:23 +00:00
onLocaleChange: async (locale: string | null) => {
await settingLocaleOverride.setValue(locale);
MinimalSignalContext.restartApp();
},
onMediaCameraPermissionsChange: attachRenderCallback(
2021-08-18 20:08:14 +00:00
settingMediaCameraPermissions.setValue
),
onMessageAudioChange: attachRenderCallback(settingMessageAudio.setValue),
onMinimizeToAndStartInSystemTrayChange: attachRenderCallback(
async (value: boolean) => {
await settingSystemTraySetting.setValue(
value
? SystemTraySetting.MinimizeToAndStartInSystemTray
: SystemTraySetting.MinimizeToSystemTray
);
return value;
}
),
onMinimizeToSystemTrayChange: attachRenderCallback(
async (value: boolean) => {
await settingSystemTraySetting.setValue(
value
? SystemTraySetting.MinimizeToSystemTray
: SystemTraySetting.DoNotUseSystemTray
);
return value;
}
),
onMediaPermissionsChange: attachRenderCallback(
settingMediaPermissions.setValue
),
onNotificationAttentionChange: attachRenderCallback(
2021-08-18 20:08:14 +00:00
settingNotificationDrawAttention.setValue
),
onNotificationContentChange: attachRenderCallback(
settingNotificationSetting.setValue
),
onNotificationsChange: attachRenderCallback(async (value: boolean) => {
2021-08-18 20:08:14 +00:00
await settingNotificationSetting.setValue(
value ? DEFAULT_NOTIFICATION_SETTING : 'off'
);
return value;
}),
onRelayCallsChange: attachRenderCallback(settingRelayCalls.setValue),
onSelectedCameraChange: attachRenderCallback(settingVideoInput.setValue),
onSelectedMicrophoneChange: attachRenderCallback(
settingAudioInput.setValue
),
onSelectedSpeakerChange: attachRenderCallback(settingAudioOutput.setValue),
onSentMediaQualityChange: attachRenderCallback(
settingSentMediaQuality.setValue
),
onSpellCheckChange: attachRenderCallback(settingSpellCheck.setValue),
onTextFormattingChange: attachRenderCallback(
settingTextFormatting.setValue
),
onThemeChange: attachRenderCallback(settingTheme.setValue),
2022-11-16 20:18:02 +00:00
onUniversalExpireTimerChange: (newValue: number): Promise<void> => {
return onUniversalExpireTimerChange(
DurationInSeconds.fromSeconds(newValue)
);
},
onWhoCanFindMeChange: attachRenderCallback(
settingPhoneNumberDiscoverability.setValue
),
onWhoCanSeeMeChange: attachRenderCallback(
settingPhoneNumberSharing.setValue
),
2023-02-23 21:32:19 +00:00
// Zoom factor change doesn't require immediate rerender since it will:
// 1. Update the zoom factor in the main window
// 2. Trigger `preferred-size-changed` in the main process
// 3. Finally result in `window.storage` update which will cause the
// rerender.
onZoomFactorChange: (value: number) => {
// Update Settings window zoom factor to match the selected value.
webFrame.setZoomFactor(value);
return settingZoomFactor.setValue(value);
},
2021-08-18 20:08:14 +00:00
hasCustomTitleBar: MinimalSignalContext.OS.hasCustomTitleBar(),
executeMenuRole: MinimalSignalContext.executeMenuRole,
2021-08-18 20:08:14 +00:00
};
renderInBrowser(props);
}
2021-09-29 18:37:30 +00:00
ipcRenderer.on('preferences-changed', () => renderPreferences());
const Signal = {
SettingsWindowProps: {
onRender: (renderer: (_props: PropsPreloadType) => void) => {
renderInBrowser = renderer;
void renderPreferences();
},
},
};
contextBridge.exposeInMainWorld('Signal', Signal);
contextBridge.exposeInMainWorld('SignalContext', MinimalSignalContext);