Change ephemeral settings to only persist in ephemeralConfig
This commit is contained in:
parent
07e2fb7f60
commit
73e8bec42f
18 changed files with 295 additions and 265 deletions
|
@ -8,7 +8,6 @@ import {
|
|||
SystemTraySetting,
|
||||
} from '../ts/types/SystemTraySetting';
|
||||
import { isSystemTraySupported } from '../ts/types/Settings';
|
||||
import type { MainSQL } from '../ts/sql/main';
|
||||
import type { ConfigType } from './base_config';
|
||||
|
||||
/**
|
||||
|
@ -21,7 +20,6 @@ export class SystemTraySettingCache {
|
|||
private getPromise: undefined | Promise<SystemTraySetting>;
|
||||
|
||||
constructor(
|
||||
private readonly sql: Pick<MainSQL, 'sqlCall'>,
|
||||
private readonly ephemeralConfig: Pick<ConfigType, 'get' | 'set'>,
|
||||
private readonly argv: Array<string>,
|
||||
private readonly appVersion: string
|
||||
|
@ -56,15 +54,11 @@ export class SystemTraySettingCache {
|
|||
`getSystemTraySetting saw --use-tray-icon flag. Returning ${result}`
|
||||
);
|
||||
} else if (isSystemTraySupported(OS, this.appVersion)) {
|
||||
const fastValue = this.ephemeralConfig.get('system-tray-setting');
|
||||
if (fastValue !== undefined) {
|
||||
log.info('getSystemTraySetting got fast value', fastValue);
|
||||
const value = this.ephemeralConfig.get('system-tray-setting');
|
||||
if (value !== undefined) {
|
||||
log.info('getSystemTraySetting got value', value);
|
||||
}
|
||||
|
||||
const value =
|
||||
fastValue ??
|
||||
(await this.sql.sqlCall('getItemById', 'system-tray-setting'))?.value;
|
||||
|
||||
if (value !== undefined) {
|
||||
result = parseSystemTraySetting(value);
|
||||
log.info(`getSystemTraySetting returning ${result}`);
|
||||
|
@ -73,7 +67,7 @@ export class SystemTraySettingCache {
|
|||
log.info(`getSystemTraySetting got no value, returning ${result}`);
|
||||
}
|
||||
|
||||
if (result !== fastValue) {
|
||||
if (result !== value) {
|
||||
this.ephemeralConfig.set('system-tray-setting', result);
|
||||
}
|
||||
} else {
|
||||
|
|
118
app/main.ts
118
app/main.ts
|
@ -292,22 +292,18 @@ const sql = new MainSQL();
|
|||
const heicConverter = getHeicConverter();
|
||||
|
||||
async function getSpellCheckSetting(): Promise<boolean> {
|
||||
const fastValue = ephemeralConfig.get('spell-check');
|
||||
if (typeof fastValue === 'boolean') {
|
||||
getLogger().info('got fast spellcheck setting', fastValue);
|
||||
return fastValue;
|
||||
const value = ephemeralConfig.get('spell-check');
|
||||
if (typeof value === 'boolean') {
|
||||
getLogger().info('got fast spellcheck setting', value);
|
||||
return value;
|
||||
}
|
||||
|
||||
const json = await sql.sqlCall('getItemById', 'spell-check');
|
||||
|
||||
// Default to `true` if setting doesn't exist yet
|
||||
const slowValue = typeof json?.value === 'boolean' ? json.value : true;
|
||||
ephemeralConfig.set('spell-check', true);
|
||||
|
||||
ephemeralConfig.set('spell-check', slowValue);
|
||||
getLogger().info('initializing spellcheck setting', true);
|
||||
|
||||
getLogger().info('got slow spellcheck setting', slowValue);
|
||||
|
||||
return slowValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
type GetThemeSettingOptionsType = Readonly<{
|
||||
|
@ -317,29 +313,22 @@ type GetThemeSettingOptionsType = Readonly<{
|
|||
async function getThemeSetting({
|
||||
ephemeralOnly = false,
|
||||
}: GetThemeSettingOptionsType = {}): Promise<ThemeSettingType> {
|
||||
let result: unknown;
|
||||
|
||||
const fastValue = ephemeralConfig.get('theme-setting');
|
||||
if (fastValue !== undefined) {
|
||||
getLogger().info('got fast theme-setting value', fastValue);
|
||||
result = fastValue;
|
||||
const value = ephemeralConfig.get('theme-setting');
|
||||
if (value !== undefined) {
|
||||
getLogger().info('got fast theme-setting value', value);
|
||||
} else if (ephemeralOnly) {
|
||||
return 'system';
|
||||
} else {
|
||||
const json = await sql.sqlCall('getItemById', 'theme-setting');
|
||||
|
||||
result = json?.value;
|
||||
}
|
||||
|
||||
// Default to `system` if setting doesn't exist or is invalid
|
||||
const validatedResult =
|
||||
result === 'light' || result === 'dark' || result === 'system'
|
||||
? result
|
||||
value === 'light' || value === 'dark' || value === 'system'
|
||||
? value
|
||||
: 'system';
|
||||
|
||||
if (fastValue !== validatedResult) {
|
||||
if (value !== validatedResult) {
|
||||
ephemeralConfig.set('theme-setting', validatedResult);
|
||||
getLogger().info('got slow theme-setting value', result);
|
||||
getLogger().info('saving theme-setting value', validatedResult);
|
||||
}
|
||||
|
||||
return validatedResult;
|
||||
|
@ -372,23 +361,19 @@ async function getBackgroundColor(
|
|||
}
|
||||
|
||||
async function getLocaleOverrideSetting(): Promise<string | null> {
|
||||
const fastValue = ephemeralConfig.get('localeOverride');
|
||||
const value = ephemeralConfig.get('localeOverride');
|
||||
// eslint-disable-next-line eqeqeq -- Checking for null explicitly
|
||||
if (typeof fastValue === 'string' || fastValue === null) {
|
||||
getLogger().info('got fast localeOverride setting', fastValue);
|
||||
return fastValue;
|
||||
if (typeof value === 'string' || value === null) {
|
||||
getLogger().info('got fast localeOverride setting', value);
|
||||
return value;
|
||||
}
|
||||
|
||||
const json = await sql.sqlCall('getItemById', 'localeOverride');
|
||||
|
||||
// Default to `null` if setting doesn't exist yet
|
||||
const slowValue = typeof json?.value === 'string' ? json.value : null;
|
||||
ephemeralConfig.set('localeOverride', null);
|
||||
|
||||
ephemeralConfig.set('localeOverride', slowValue);
|
||||
getLogger().info('initializing localeOverride setting', null);
|
||||
|
||||
getLogger().info('got slow localeOverride setting', slowValue);
|
||||
|
||||
return slowValue;
|
||||
return null;
|
||||
}
|
||||
|
||||
const zoomFactorService = new ZoomFactorService({
|
||||
|
@ -409,7 +394,6 @@ const zoomFactorService = new ZoomFactorService({
|
|||
|
||||
let systemTrayService: SystemTrayService | undefined;
|
||||
const systemTraySettingCache = new SystemTraySettingCache(
|
||||
sql,
|
||||
ephemeralConfig,
|
||||
process.argv,
|
||||
app.getVersion()
|
||||
|
@ -1811,12 +1795,7 @@ app.on('ready', async () => {
|
|||
getLogger().info(`app.ready: setting system-tray-setting to ${newValue}`);
|
||||
systemTraySettingCache.set(newValue);
|
||||
|
||||
// Update both stores
|
||||
ephemeralConfig.set('system-tray-setting', newValue);
|
||||
await sql.sqlCall('createOrUpdateItem', {
|
||||
id: 'system-tray-setting',
|
||||
value: newValue,
|
||||
});
|
||||
|
||||
if (OS.isWindows()) {
|
||||
getLogger().info('app.ready: enabling open at login');
|
||||
|
@ -1832,6 +1811,32 @@ app.on('ready', async () => {
|
|||
settingsChannel = new SettingsChannel();
|
||||
settingsChannel.install();
|
||||
|
||||
settingsChannel.on('change:systemTraySetting', async rawSystemTraySetting => {
|
||||
const { openAtLogin } = app.getLoginItemSettings(
|
||||
await getDefaultLoginItemSettings()
|
||||
);
|
||||
|
||||
const systemTraySetting = parseSystemTraySetting(rawSystemTraySetting);
|
||||
systemTraySettingCache.set(systemTraySetting);
|
||||
|
||||
if (systemTrayService) {
|
||||
const isEnabled = shouldMinimizeToSystemTray(systemTraySetting);
|
||||
systemTrayService.setEnabled(isEnabled);
|
||||
}
|
||||
|
||||
// Default login item settings might have changed, so update the object.
|
||||
getLogger().info('refresh-auto-launch: new value', openAtLogin);
|
||||
app.setLoginItemSettings({
|
||||
...(await getDefaultLoginItemSettings()),
|
||||
openAtLogin,
|
||||
});
|
||||
});
|
||||
|
||||
settingsChannel.on(
|
||||
'ephemeral-setting-changed',
|
||||
sendPreferencesChangedEventToWindows
|
||||
);
|
||||
|
||||
// We use this event only a single time to log the startup time of the app
|
||||
// from when it's first ready until the loading screen disappears.
|
||||
ipc.once('signal-app-loaded', (event, info) => {
|
||||
|
@ -2318,30 +2323,6 @@ ipc.on(
|
|||
}
|
||||
);
|
||||
|
||||
ipc.handle(
|
||||
'update-system-tray-setting',
|
||||
async (_event, rawSystemTraySetting /* : Readonly<unknown> */) => {
|
||||
const { openAtLogin } = app.getLoginItemSettings(
|
||||
await getDefaultLoginItemSettings()
|
||||
);
|
||||
|
||||
const systemTraySetting = parseSystemTraySetting(rawSystemTraySetting);
|
||||
systemTraySettingCache.set(systemTraySetting);
|
||||
|
||||
if (systemTrayService) {
|
||||
const isEnabled = shouldMinimizeToSystemTray(systemTraySetting);
|
||||
systemTrayService.setEnabled(isEnabled);
|
||||
}
|
||||
|
||||
// Default login item settings might have changed, so update the object.
|
||||
getLogger().info('refresh-auto-launch: new value', openAtLogin);
|
||||
app.setLoginItemSettings({
|
||||
...(await getDefaultLoginItemSettings()),
|
||||
openAtLogin,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
ipc.on('close-screen-share-controller', () => {
|
||||
if (screenShareWindow) {
|
||||
screenShareWindow.close();
|
||||
|
@ -2564,13 +2545,14 @@ ipc.on('get-user-data-path', event => {
|
|||
});
|
||||
|
||||
// Refresh the settings window whenever preferences change
|
||||
ipc.on('preferences-changed', () => {
|
||||
const sendPreferencesChangedEventToWindows = () => {
|
||||
for (const window of activeWindows) {
|
||||
if (window.webContents) {
|
||||
window.webContents.send('preferences-changed');
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
ipc.on('preferences-changed', sendPreferencesChangedEventToWindows);
|
||||
|
||||
function maybeGetIncomingSignalRoute(argv: Array<string>) {
|
||||
for (const arg of argv) {
|
||||
|
|
|
@ -190,6 +190,7 @@ import {
|
|||
updateLocalGroupCallHistoryTimestamp,
|
||||
} from './util/callDisposition';
|
||||
import { deriveStorageServiceKey } from './Crypto';
|
||||
import { getThemeType } from './util/getThemeType';
|
||||
|
||||
export function isOverHourIntoPast(timestamp: number): boolean {
|
||||
return isNumber(timestamp) && isOlderThan(timestamp, HOUR);
|
||||
|
@ -697,25 +698,6 @@ export async function startApp(): Promise<void> {
|
|||
log.info('Storage fetch');
|
||||
drop(window.storage.fetch());
|
||||
|
||||
function mapOldThemeToNew(
|
||||
theme: Readonly<
|
||||
'system' | 'light' | 'dark' | 'android' | 'ios' | 'android-dark'
|
||||
>
|
||||
): 'system' | 'light' | 'dark' {
|
||||
switch (theme) {
|
||||
case 'dark':
|
||||
case 'light':
|
||||
case 'system':
|
||||
return theme;
|
||||
case 'android-dark':
|
||||
return 'dark';
|
||||
case 'android':
|
||||
case 'ios':
|
||||
default:
|
||||
return 'light';
|
||||
}
|
||||
}
|
||||
|
||||
// We need this 'first' check because we don't want to start the app up any other time
|
||||
// than the first time. And window.storage.fetch() will cause onready() to fire.
|
||||
let first = true;
|
||||
|
@ -925,16 +907,6 @@ export async function startApp(): Promise<void> {
|
|||
);
|
||||
}
|
||||
|
||||
const themeSetting = window.Events.getThemeSetting();
|
||||
const newThemeSetting = mapOldThemeToNew(themeSetting);
|
||||
if (window.isBeforeVersion(lastVersion, 'v1.25.0')) {
|
||||
if (newThemeSetting === window.systemTheme) {
|
||||
void window.Events.setThemeSetting('system');
|
||||
} else {
|
||||
void window.Events.setThemeSetting(newThemeSetting);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
window.isBeforeVersion(lastVersion, 'v1.36.0-beta.1') &&
|
||||
window.isAfterVersion(lastVersion, 'v1.35.0-beta.1')
|
||||
|
@ -1133,6 +1105,8 @@ export async function startApp(): Promise<void> {
|
|||
platform: 'unknown',
|
||||
};
|
||||
|
||||
let theme: ThemeType = window.systemTheme;
|
||||
|
||||
try {
|
||||
// This needs to load before we prime the data because we expect
|
||||
// ConversationController to be loaded and ready to use by then.
|
||||
|
@ -1153,6 +1127,9 @@ export async function startApp(): Promise<void> {
|
|||
(async () => {
|
||||
menuOptions = await window.SignalContext.getMenuOptions();
|
||||
})(),
|
||||
(async () => {
|
||||
theme = await getThemeType();
|
||||
})(),
|
||||
]);
|
||||
await window.ConversationController.checkForConflicts();
|
||||
} catch (error) {
|
||||
|
@ -1161,7 +1138,7 @@ export async function startApp(): Promise<void> {
|
|||
Errors.toLogFormat(error)
|
||||
);
|
||||
} finally {
|
||||
setupAppState({ mainWindowStats, menuOptions });
|
||||
setupAppState({ mainWindowStats, menuOptions, theme });
|
||||
drop(start());
|
||||
window.Signal.Services.initializeNetworkObserver(
|
||||
window.reduxActions.network
|
||||
|
@ -1186,9 +1163,11 @@ export async function startApp(): Promise<void> {
|
|||
function setupAppState({
|
||||
mainWindowStats,
|
||||
menuOptions,
|
||||
theme,
|
||||
}: {
|
||||
mainWindowStats: MainWindowStatsType;
|
||||
menuOptions: MenuOptionsType;
|
||||
theme: ThemeType;
|
||||
}) {
|
||||
initializeRedux({
|
||||
callsHistory: getCallsHistoryForRedux(),
|
||||
|
@ -1198,6 +1177,7 @@ export async function startApp(): Promise<void> {
|
|||
menuOptions,
|
||||
stories: getStoriesForRedux(),
|
||||
storyDistributionLists: getDistributionListsForRedux(),
|
||||
theme,
|
||||
});
|
||||
|
||||
// Here we set up a full redux store with initial state for our LeftPane Root
|
||||
|
@ -1847,18 +1827,6 @@ export async function startApp(): Promise<void> {
|
|||
}
|
||||
}
|
||||
|
||||
const hasThemeSetting = Boolean(window.storage.get('theme-setting'));
|
||||
if (
|
||||
!hasThemeSetting &&
|
||||
window.textsecure.storage.get('userAgent') === 'OWI'
|
||||
) {
|
||||
await window.storage.put(
|
||||
'theme-setting',
|
||||
await window.Events.getThemeSetting()
|
||||
);
|
||||
themeChanged();
|
||||
}
|
||||
|
||||
const waitForEvent = createTaskWithTimeout(
|
||||
(event: string): Promise<void> => {
|
||||
const { promise, resolve } = explodePromise<void>();
|
||||
|
|
|
@ -14,6 +14,7 @@ import type {
|
|||
IPCEventsValuesType,
|
||||
IPCEventsCallbacksType,
|
||||
} from '../util/createIPCEvents';
|
||||
import type { EphemeralSettings, SettingsValuesType } from '../util/preload';
|
||||
|
||||
const EPHEMERAL_NAME_MAP = new Map([
|
||||
['spellCheck', 'spell-check'],
|
||||
|
@ -27,6 +28,9 @@ type ResponseQueueEntry = Readonly<{
|
|||
reject(error: Error): void;
|
||||
}>;
|
||||
|
||||
type SettingChangeEventType<Key extends keyof SettingsValuesType> =
|
||||
`change:${Key}`;
|
||||
|
||||
export class SettingsChannel extends EventEmitter {
|
||||
private mainWindow?: BrowserWindow;
|
||||
|
||||
|
@ -70,17 +74,7 @@ export class SettingsChannel extends EventEmitter {
|
|||
this.installSetting('readReceiptSetting', { setter: false });
|
||||
this.installSetting('typingIndicatorSetting', { setter: false });
|
||||
|
||||
this.installSetting('themeSetting', {
|
||||
isEphemeral: true,
|
||||
});
|
||||
this.installSetting('hideMenuBar');
|
||||
this.installSetting('systemTraySetting', {
|
||||
isEphemeral: true,
|
||||
});
|
||||
|
||||
this.installSetting('localeOverride', {
|
||||
isEphemeral: true,
|
||||
});
|
||||
this.installSetting('notificationSetting');
|
||||
this.installSetting('notificationDrawAttention');
|
||||
this.installSetting('audioMessage');
|
||||
|
@ -88,9 +82,6 @@ export class SettingsChannel extends EventEmitter {
|
|||
this.installSetting('countMutedConversations');
|
||||
|
||||
this.installSetting('sentMediaQualitySetting');
|
||||
this.installSetting('spellCheck', {
|
||||
isEphemeral: true,
|
||||
});
|
||||
this.installSetting('textFormatting');
|
||||
|
||||
this.installSetting('autoConvertEmoji');
|
||||
|
@ -116,6 +107,11 @@ export class SettingsChannel extends EventEmitter {
|
|||
this.installSetting('phoneNumberDiscoverabilitySetting');
|
||||
this.installSetting('phoneNumberSharingSetting');
|
||||
|
||||
this.installEphemeralSetting('themeSetting');
|
||||
this.installEphemeralSetting('systemTraySetting');
|
||||
this.installEphemeralSetting('localeOverride');
|
||||
this.installEphemeralSetting('spellCheck');
|
||||
|
||||
installPermissionsHandler({ session: session.defaultSession, userConfig });
|
||||
|
||||
// These ones are different because its single source of truth is userConfig,
|
||||
|
@ -234,8 +230,7 @@ export class SettingsChannel extends EventEmitter {
|
|||
{
|
||||
getter = true,
|
||||
setter = true,
|
||||
isEphemeral = false,
|
||||
}: { getter?: boolean; setter?: boolean; isEphemeral?: boolean } = {}
|
||||
}: { getter?: boolean; setter?: boolean } = {}
|
||||
): void {
|
||||
if (getter) {
|
||||
ipc.handle(`settings:get:${name}`, async () => {
|
||||
|
@ -248,18 +243,89 @@ export class SettingsChannel extends EventEmitter {
|
|||
}
|
||||
|
||||
ipc.handle(`settings:set:${name}`, async (_event, value) => {
|
||||
if (isEphemeral) {
|
||||
const ephemeralName = EPHEMERAL_NAME_MAP.get(name);
|
||||
strictAssert(
|
||||
ephemeralName !== undefined,
|
||||
`${name} is not an ephemeral setting`
|
||||
);
|
||||
ephemeralConfig.set(ephemeralName, value);
|
||||
}
|
||||
|
||||
await this.setSettingInMainWindow(name, value);
|
||||
|
||||
this.emit(`change:${name}`, value);
|
||||
});
|
||||
}
|
||||
|
||||
private installEphemeralSetting<Name extends keyof EphemeralSettings>(
|
||||
name: Name
|
||||
): void {
|
||||
ipc.handle(`settings:get:${name}`, async () => {
|
||||
const ephemeralName = EPHEMERAL_NAME_MAP.get(name);
|
||||
strictAssert(
|
||||
ephemeralName !== undefined,
|
||||
`${name} is not an ephemeral setting`
|
||||
);
|
||||
return ephemeralConfig.get(ephemeralName);
|
||||
});
|
||||
|
||||
ipc.handle(`settings:set:${name}`, async (_event, value) => {
|
||||
const ephemeralName = EPHEMERAL_NAME_MAP.get(name);
|
||||
strictAssert(
|
||||
ephemeralName !== undefined,
|
||||
`${name} is not an ephemeral setting`
|
||||
);
|
||||
ephemeralConfig.set(ephemeralName, value);
|
||||
|
||||
this.emit(`change:${name}`, value);
|
||||
|
||||
// Notify main to notify windows of preferences change. As for DB-backed
|
||||
// settings, those are set by the renderer, and afterwards the renderer IPC sends
|
||||
// to main the event 'preferences-changed'.
|
||||
this.emit('ephemeral-setting-changed');
|
||||
|
||||
const { mainWindow } = this;
|
||||
if (!mainWindow || !mainWindow.webContents) {
|
||||
return;
|
||||
}
|
||||
|
||||
mainWindow.webContents.send(`settings:update:${name}`, value);
|
||||
});
|
||||
}
|
||||
|
||||
// EventEmitter types
|
||||
|
||||
public override on(
|
||||
type: 'change:systemTraySetting',
|
||||
callback: (value: string) => void
|
||||
): this;
|
||||
|
||||
public override on(
|
||||
type: 'ephemeral-setting-changed',
|
||||
callback: () => void
|
||||
): this;
|
||||
|
||||
public override on(
|
||||
type: SettingChangeEventType<keyof SettingsValuesType>,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
callback: (...args: Array<any>) => void
|
||||
): this;
|
||||
|
||||
public override on(
|
||||
type: string | symbol,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
listener: (...args: Array<any>) => void
|
||||
): this {
|
||||
return super.on(type, listener);
|
||||
}
|
||||
|
||||
public override emit(
|
||||
type: 'change:systemTraySetting',
|
||||
value: string
|
||||
): boolean;
|
||||
|
||||
public override emit(type: 'ephemeral-setting-changed'): boolean;
|
||||
|
||||
public override emit(
|
||||
type: SettingChangeEventType<keyof SettingsValuesType>,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
...args: Array<any>
|
||||
): boolean;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public override emit(type: string | symbol, ...args: Array<any>): boolean {
|
||||
return super.emit(type, ...args);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
import { getThemeType } from '../util/getThemeType';
|
||||
|
||||
export function themeChanged(): void {
|
||||
export async function themeChanged(): Promise<void> {
|
||||
if (window.reduxActions && window.reduxActions.user) {
|
||||
const theme = getThemeType();
|
||||
const theme = await getThemeType();
|
||||
window.reduxActions.user.userChanged({ theme });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,10 +37,10 @@ import type { StoryDistributionListDataType } from './ducks/storyDistributionLis
|
|||
import OS from '../util/os/osMain';
|
||||
import { getEmojiReducerState as emojis } from '../util/loadRecentEmojis';
|
||||
import { getInitialState as stickers } from '../types/Stickers';
|
||||
import { getThemeType } from '../util/getThemeType';
|
||||
import { getInteractionMode } from '../services/InteractionMode';
|
||||
import { makeLookup } from '../util/makeLookup';
|
||||
import type { CallHistoryDetails } from '../types/CallDisposition';
|
||||
import type { ThemeType } from '../types/Util';
|
||||
|
||||
export function getInitialState({
|
||||
badges,
|
||||
|
@ -50,6 +50,7 @@ export function getInitialState({
|
|||
storyDistributionLists,
|
||||
mainWindowStats,
|
||||
menuOptions,
|
||||
theme,
|
||||
}: {
|
||||
badges: BadgesStateType;
|
||||
callsHistory: ReadonlyArray<CallHistoryDetails>;
|
||||
|
@ -58,6 +59,7 @@ export function getInitialState({
|
|||
storyDistributionLists: Array<StoryDistributionListDataType>;
|
||||
mainWindowStats: MainWindowStatsType;
|
||||
menuOptions: MenuOptionsType;
|
||||
theme: ThemeType;
|
||||
}): StateType {
|
||||
const items = window.storage.getItemsState();
|
||||
|
||||
|
@ -72,8 +74,6 @@ export function getInitialState({
|
|||
window.ConversationController.getOurConversationId();
|
||||
const ourDeviceId = window.textsecure.storage.user.getDeviceId();
|
||||
|
||||
const theme = getThemeType();
|
||||
|
||||
let osName: 'windows' | 'macos' | 'linux' | undefined;
|
||||
|
||||
if (OS.isWindows()) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import type { StoryDistributionListDataType } from './ducks/storyDistributionLis
|
|||
import { actionCreators } from './actions';
|
||||
import { createStore } from './createStore';
|
||||
import { getInitialState } from './getInitialState';
|
||||
import type { ThemeType } from '../types/Util';
|
||||
|
||||
export function initializeRedux({
|
||||
callsHistory,
|
||||
|
@ -20,6 +21,7 @@ export function initializeRedux({
|
|||
menuOptions,
|
||||
stories,
|
||||
storyDistributionLists,
|
||||
theme,
|
||||
}: {
|
||||
callsHistory: ReadonlyArray<CallHistoryDetails>;
|
||||
callsHistoryUnreadCount: number;
|
||||
|
@ -28,6 +30,7 @@ export function initializeRedux({
|
|||
menuOptions: MenuOptionsType;
|
||||
stories: Array<StoryDataType>;
|
||||
storyDistributionLists: Array<StoryDistributionListDataType>;
|
||||
theme: ThemeType;
|
||||
}): void {
|
||||
const initialState = getInitialState({
|
||||
badges: initialBadgesState,
|
||||
|
@ -37,6 +40,7 @@ export function initializeRedux({
|
|||
menuOptions,
|
||||
stories,
|
||||
storyDistributionLists,
|
||||
theme,
|
||||
});
|
||||
|
||||
const store = createStore(initialState);
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
import { assert } from 'chai';
|
||||
import * as sinon from 'sinon';
|
||||
import type { MainSQL } from '../../sql/main';
|
||||
import { SystemTraySetting } from '../../types/SystemTraySetting';
|
||||
|
||||
import type { ConfigType } from '../../../app/base_config';
|
||||
|
@ -12,18 +11,13 @@ import { SystemTraySettingCache } from '../../../app/SystemTraySettingCache';
|
|||
describe('SystemTraySettingCache', () => {
|
||||
let sandbox: sinon.SinonSandbox;
|
||||
|
||||
let sqlCallStub: sinon.SinonStub;
|
||||
let configGetStub: sinon.SinonStub;
|
||||
let configSetStub: sinon.SinonStub;
|
||||
let sql: Pick<MainSQL, 'sqlCall'>;
|
||||
let config: Pick<ConfigType, 'get' | 'set'>;
|
||||
|
||||
beforeEach(() => {
|
||||
sandbox = sinon.createSandbox();
|
||||
|
||||
sqlCallStub = sandbox.stub().resolves();
|
||||
sql = { sqlCall: sqlCallStub };
|
||||
|
||||
configGetStub = sandbox.stub().returns(undefined);
|
||||
configSetStub = sandbox.stub().returns(undefined);
|
||||
config = { get: configGetStub, set: configSetStub };
|
||||
|
@ -35,7 +29,6 @@ describe('SystemTraySettingCache', () => {
|
|||
|
||||
it('returns MinimizeToAndStartInSystemTray if passed the --start-in-tray argument', async () => {
|
||||
const justOneArg = new SystemTraySettingCache(
|
||||
sql,
|
||||
config,
|
||||
['--start-in-tray'],
|
||||
'1.2.3'
|
||||
|
@ -46,7 +39,6 @@ describe('SystemTraySettingCache', () => {
|
|||
);
|
||||
|
||||
const bothArgs = new SystemTraySettingCache(
|
||||
sql,
|
||||
config,
|
||||
['--start-in-tray', '--use-tray-icon'],
|
||||
'1.2.3'
|
||||
|
@ -56,14 +48,12 @@ describe('SystemTraySettingCache', () => {
|
|||
SystemTraySetting.MinimizeToAndStartInSystemTray
|
||||
);
|
||||
|
||||
sinon.assert.notCalled(sqlCallStub);
|
||||
sinon.assert.notCalled(configGetStub);
|
||||
sinon.assert.notCalled(configSetStub);
|
||||
});
|
||||
|
||||
it('returns MinimizeToSystemTray if passed the --use-tray-icon argument', async () => {
|
||||
const cache = new SystemTraySettingCache(
|
||||
sql,
|
||||
config,
|
||||
['--use-tray-icon'],
|
||||
'1.2.3'
|
||||
|
@ -73,7 +63,6 @@ describe('SystemTraySettingCache', () => {
|
|||
SystemTraySetting.MinimizeToSystemTray
|
||||
);
|
||||
|
||||
sinon.assert.notCalled(sqlCallStub);
|
||||
sinon.assert.notCalled(configGetStub);
|
||||
sinon.assert.notCalled(configSetStub);
|
||||
});
|
||||
|
@ -81,7 +70,7 @@ describe('SystemTraySettingCache', () => {
|
|||
it('returns Uninitialized if system tray is supported but no preference is stored', async () => {
|
||||
sandbox.stub(process, 'platform').value('win32');
|
||||
|
||||
const cache = new SystemTraySettingCache(sql, config, [], '1.2.3');
|
||||
const cache = new SystemTraySettingCache(config, [], '1.2.3');
|
||||
assert.strictEqual(await cache.get(), SystemTraySetting.Uninitialized);
|
||||
assert(configGetStub.calledOnceWith('system-tray-setting'));
|
||||
assert(
|
||||
|
@ -95,9 +84,9 @@ describe('SystemTraySettingCache', () => {
|
|||
it('returns Uninitialized if system tray is supported but the stored preference is invalid', async () => {
|
||||
sandbox.stub(process, 'platform').value('win32');
|
||||
|
||||
sqlCallStub.resolves({ value: 'garbage' });
|
||||
configGetStub.returns('garbage');
|
||||
|
||||
const cache = new SystemTraySettingCache(sql, config, [], '1.2.3');
|
||||
const cache = new SystemTraySettingCache(config, [], '1.2.3');
|
||||
assert.strictEqual(await cache.get(), SystemTraySetting.Uninitialized);
|
||||
assert(configGetStub.calledOnceWith('system-tray-setting'));
|
||||
assert(
|
||||
|
@ -108,58 +97,26 @@ describe('SystemTraySettingCache', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('returns the stored preference if system tray is supported and something is stored', async () => {
|
||||
sandbox.stub(process, 'platform').value('win32');
|
||||
|
||||
sqlCallStub.resolves({ value: 'MinimizeToSystemTray' });
|
||||
|
||||
const cache = new SystemTraySettingCache(sql, config, [], '1.2.3');
|
||||
assert.strictEqual(
|
||||
await cache.get(),
|
||||
SystemTraySetting.MinimizeToSystemTray
|
||||
);
|
||||
assert(configGetStub.calledOnceWith('system-tray-setting'));
|
||||
assert(
|
||||
configSetStub.calledOnceWith(
|
||||
'system-tray-setting',
|
||||
SystemTraySetting.MinimizeToSystemTray
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the cached preference if system tray is supported and something is stored', async () => {
|
||||
sandbox.stub(process, 'platform').value('win32');
|
||||
|
||||
configGetStub.returns('MinimizeToSystemTray');
|
||||
|
||||
const cache = new SystemTraySettingCache(sql, config, [], '1.2.3');
|
||||
const cache = new SystemTraySettingCache(config, [], '1.2.3');
|
||||
assert.strictEqual(
|
||||
await cache.get(),
|
||||
SystemTraySetting.MinimizeToSystemTray
|
||||
);
|
||||
assert(configGetStub.calledOnceWith('system-tray-setting'));
|
||||
sinon.assert.notCalled(sqlCallStub);
|
||||
});
|
||||
|
||||
it('only kicks off one request to the database if multiple sources ask at once', async () => {
|
||||
sandbox.stub(process, 'platform').value('win32');
|
||||
|
||||
const cache = new SystemTraySettingCache(sql, config, [], '1.2.3');
|
||||
|
||||
await Promise.all([cache.get(), cache.get(), cache.get()]);
|
||||
|
||||
assert(configGetStub.calledOnceWith('system-tray-setting'));
|
||||
sinon.assert.calledOnce(sqlCallStub);
|
||||
});
|
||||
|
||||
it('returns DoNotUseSystemTray if system tray is unsupported and there are no CLI flags', async () => {
|
||||
sandbox.stub(process, 'platform').value('darwin');
|
||||
|
||||
const cache = new SystemTraySettingCache(sql, config, [], '1.2.3');
|
||||
const cache = new SystemTraySettingCache(config, [], '1.2.3');
|
||||
assert.strictEqual(await cache.get(), SystemTraySetting.DoNotUseSystemTray);
|
||||
|
||||
sinon.assert.notCalled(configGetStub);
|
||||
sinon.assert.notCalled(configSetStub);
|
||||
sinon.assert.notCalled(sqlCallStub);
|
||||
});
|
||||
});
|
||||
|
|
6
ts/types/Storage.d.ts
vendored
6
ts/types/Storage.d.ts
vendored
|
@ -11,7 +11,6 @@ import type { PhoneNumberDiscoverability } from '../util/phoneNumberDiscoverabil
|
|||
import type { PhoneNumberSharingMode } from '../util/phoneNumberSharingMode';
|
||||
import type { RetryItemType } from '../util/retryPlaceholders';
|
||||
import type { ConfigMapType as RemoteConfigType } from '../RemoteConfig';
|
||||
import type { SystemTraySetting } from './SystemTraySetting';
|
||||
import type { ExtendedStorageID, UnknownRecord } from './StorageService.d';
|
||||
|
||||
import type { GroupCredentialType } from '../textsecure/WebAPI';
|
||||
|
@ -19,7 +18,6 @@ import type {
|
|||
SessionResetsType,
|
||||
StorageServiceCredentials,
|
||||
} from '../textsecure/Types.d';
|
||||
import type { ThemeSettingType } from './StorageUIKeys';
|
||||
import type { ServiceIdString } from './ServiceId';
|
||||
|
||||
import type { RegisteredChallengeType } from '../challenge';
|
||||
|
@ -57,14 +55,10 @@ export type StorageAccessType = {
|
|||
'call-system-notification': boolean;
|
||||
'hide-menu-bar': boolean;
|
||||
'incoming-call-notification': boolean;
|
||||
localeOverride: string | null;
|
||||
'notification-draw-attention': boolean;
|
||||
'notification-setting': NotificationSettingType;
|
||||
'read-receipt-setting': boolean;
|
||||
'sent-media-quality': SentMediaQualitySettingType;
|
||||
'spell-check': boolean;
|
||||
'system-tray-setting': SystemTraySetting;
|
||||
'theme-setting': ThemeSettingType;
|
||||
audioMessage: boolean;
|
||||
attachmentMigration_isComplete: boolean;
|
||||
attachmentMigration_lastProcessedIndex: number;
|
||||
|
|
|
@ -25,7 +25,6 @@ export const STORAGE_UI_KEYS: ReadonlyArray<keyof StorageAccessType> = [
|
|||
'hasCompletedUsernameLinkOnboarding',
|
||||
'hide-menu-bar',
|
||||
'incoming-call-notification',
|
||||
'localeOverride',
|
||||
'navTabsCollapsed',
|
||||
'notification-draw-attention',
|
||||
'notification-setting',
|
||||
|
@ -40,10 +39,7 @@ export const STORAGE_UI_KEYS: ReadonlyArray<keyof StorageAccessType> = [
|
|||
'showStickerPickerHint',
|
||||
'showStickersIntroduction',
|
||||
'skinTone',
|
||||
'spell-check',
|
||||
'system-tray-setting',
|
||||
'textFormatting',
|
||||
'theme-setting',
|
||||
'version',
|
||||
'zoomFactor',
|
||||
];
|
||||
|
|
|
@ -14,8 +14,6 @@ import type {
|
|||
import { DEFAULT_CONVERSATION_COLOR } from '../types/Colors';
|
||||
import * as Errors from '../types/errors';
|
||||
import * as Stickers from '../types/Stickers';
|
||||
import type { SystemTraySetting } from '../types/SystemTraySetting';
|
||||
import { parseSystemTraySetting } from '../types/SystemTraySetting';
|
||||
|
||||
import type { ConversationType } from '../state/ducks/conversations';
|
||||
import type { AuthorizeArtCreatorDataType } from '../state/ducks/globalModals';
|
||||
|
@ -45,9 +43,15 @@ import { fromWebSafeBase64 } from './webSafeBase64';
|
|||
import { getConversation } from './getConversation';
|
||||
import { instance, PhoneNumberFormat } from './libphonenumberInstance';
|
||||
import { showConfirmationDialog } from './showConfirmationDialog';
|
||||
import type {
|
||||
EphemeralSettings,
|
||||
SettingsValuesType,
|
||||
ThemeType,
|
||||
} from './preload';
|
||||
import type { SystemTraySetting } from '../types/SystemTraySetting';
|
||||
import { drop } from './drop';
|
||||
|
||||
type SentMediaQualityType = 'standard' | 'high';
|
||||
type ThemeType = 'light' | 'dark' | 'system';
|
||||
type NotificationSettingType = 'message' | 'name' | 'count' | 'off';
|
||||
|
||||
export type IPCEventsValuesType = {
|
||||
|
@ -64,17 +68,13 @@ export type IPCEventsValuesType = {
|
|||
hideMenuBar: boolean | undefined;
|
||||
incomingCallNotification: boolean;
|
||||
lastSyncTime: number | undefined;
|
||||
localeOverride: string | null;
|
||||
notificationDrawAttention: boolean;
|
||||
notificationSetting: NotificationSettingType;
|
||||
preferredAudioInputDevice: AudioDevice | undefined;
|
||||
preferredAudioOutputDevice: AudioDevice | undefined;
|
||||
preferredVideoInputDevice: string | undefined;
|
||||
sentMediaQualitySetting: SentMediaQualityType;
|
||||
spellCheck: boolean;
|
||||
systemTraySetting: SystemTraySetting;
|
||||
textFormatting: boolean;
|
||||
themeSetting: ThemeType;
|
||||
universalExpireTimer: DurationInSeconds;
|
||||
zoomFactor: ZoomFactorType;
|
||||
storyViewReceiptsEnabled: boolean;
|
||||
|
@ -144,17 +144,21 @@ export type IPCEventsCallbacksType = {
|
|||
};
|
||||
|
||||
type ValuesWithGetters = Omit<
|
||||
IPCEventsValuesType,
|
||||
SettingsValuesType,
|
||||
// Async
|
||||
| 'zoomFactor'
|
||||
| 'localeOverride'
|
||||
| 'spellCheck'
|
||||
| 'themeSetting'
|
||||
// Optional
|
||||
| 'mediaPermissions'
|
||||
| 'mediaCameraPermissions'
|
||||
| 'autoLaunch'
|
||||
| 'systemTraySetting'
|
||||
>;
|
||||
|
||||
type ValuesWithSetters = Omit<
|
||||
IPCEventsValuesType,
|
||||
SettingsValuesType,
|
||||
| 'blockedCount'
|
||||
| 'defaultConversationColor'
|
||||
| 'linkPreviewSetting'
|
||||
|
@ -166,19 +170,37 @@ type ValuesWithSetters = Omit<
|
|||
// Optional
|
||||
| 'mediaPermissions'
|
||||
| 'mediaCameraPermissions'
|
||||
|
||||
// Only set in the Settings window
|
||||
| 'localeOverride'
|
||||
| 'spellCheck'
|
||||
| 'systemTraySetting'
|
||||
>;
|
||||
|
||||
export type IPCEventGetterType<Key extends keyof IPCEventsValuesType> =
|
||||
export type IPCEventsUpdatersType = {
|
||||
[Key in keyof EphemeralSettings as IPCEventUpdaterType<Key>]?: (
|
||||
value: EphemeralSettings[Key]
|
||||
) => void;
|
||||
};
|
||||
|
||||
export type IPCEventGetterType<Key extends keyof SettingsValuesType> =
|
||||
`get${Capitalize<Key>}`;
|
||||
|
||||
export type IPCEventSetterType<Key extends keyof IPCEventsValuesType> =
|
||||
export type IPCEventSetterType<Key extends keyof SettingsValuesType> =
|
||||
`set${Capitalize<Key>}`;
|
||||
|
||||
export type IPCEventUpdaterType<Key extends keyof SettingsValuesType> =
|
||||
`update${Capitalize<Key>}`;
|
||||
|
||||
export type IPCEventsGettersType = {
|
||||
[Key in keyof ValuesWithGetters as IPCEventGetterType<Key>]: () => ValuesWithGetters[Key];
|
||||
} & {
|
||||
// Async
|
||||
getZoomFactor: () => Promise<ZoomFactorType>;
|
||||
getLocaleOverride: () => Promise<string | null>;
|
||||
getSpellCheck: () => Promise<boolean>;
|
||||
getSystemTraySetting: () => Promise<SystemTraySetting>;
|
||||
getThemeSetting: () => Promise<ThemeType>;
|
||||
// Events
|
||||
onZoomFactorChange: (callback: (zoomFactor: ZoomFactorType) => void) => void;
|
||||
// Optional
|
||||
|
@ -198,6 +220,7 @@ export type IPCEventsSettersType = {
|
|||
|
||||
export type IPCEventsType = IPCEventsGettersType &
|
||||
IPCEventsSettersType &
|
||||
IPCEventsUpdatersType &
|
||||
IPCEventsCallbacksType;
|
||||
|
||||
export function createIPCEvents(
|
||||
|
@ -393,11 +416,14 @@ export function createIPCEvents(
|
|||
window.storage.get('sent-media-quality', 'standard'),
|
||||
setSentMediaQualitySetting: value =>
|
||||
window.storage.put('sent-media-quality', value),
|
||||
getThemeSetting: () => window.storage.get('theme-setting', 'system'),
|
||||
setThemeSetting: value => {
|
||||
const promise = window.storage.put('theme-setting', value);
|
||||
themeChanged();
|
||||
return promise;
|
||||
getThemeSetting: async () => {
|
||||
return getEphemeralSetting('themeSetting') ?? null;
|
||||
},
|
||||
setThemeSetting: async value => {
|
||||
drop(setEphemeralSetting('themeSetting', value));
|
||||
},
|
||||
updateThemeSetting: _theme => {
|
||||
drop(themeChanged());
|
||||
},
|
||||
getHideMenuBar: () => window.storage.get('hide-menu-bar'),
|
||||
setHideMenuBar: value => {
|
||||
|
@ -406,19 +432,9 @@ export function createIPCEvents(
|
|||
window.IPC.setMenuBarVisibility(!value);
|
||||
return promise;
|
||||
},
|
||||
getSystemTraySetting: () =>
|
||||
parseSystemTraySetting(window.storage.get('system-tray-setting')),
|
||||
setSystemTraySetting: value => {
|
||||
const promise = window.storage.put('system-tray-setting', value);
|
||||
window.IPC.updateSystemTraySetting(value);
|
||||
return promise;
|
||||
},
|
||||
|
||||
getLocaleOverride: () => {
|
||||
return window.storage.get('localeOverride') ?? null;
|
||||
},
|
||||
setLocaleOverride: async (locale: string | null) => {
|
||||
await window.storage.put('localeOverride', locale);
|
||||
getSystemTraySetting: () => getEphemeralSetting('systemTraySetting'),
|
||||
getLocaleOverride: async () => {
|
||||
return getEphemeralSetting('localeOverride') ?? null;
|
||||
},
|
||||
getNotificationSetting: () =>
|
||||
window.storage.get('notification-setting', 'message'),
|
||||
|
@ -456,8 +472,9 @@ export function createIPCEvents(
|
|||
setIncomingCallNotification: value =>
|
||||
window.storage.put('incoming-call-notification', value),
|
||||
|
||||
getSpellCheck: () => window.storage.get('spell-check', true),
|
||||
setSpellCheck: value => window.storage.put('spell-check', value),
|
||||
getSpellCheck: () => {
|
||||
return getEphemeralSetting('spellCheck');
|
||||
},
|
||||
getTextFormatting: () => window.storage.get('textFormatting', true),
|
||||
setTextFormatting: value => window.storage.put('textFormatting', value),
|
||||
|
||||
|
@ -709,3 +726,16 @@ function showUnknownSgnlLinkModal(): void {
|
|||
description: window.i18n('icu:unknown-sgnl-link'),
|
||||
});
|
||||
}
|
||||
|
||||
function getEphemeralSetting<Name extends keyof EphemeralSettings>(
|
||||
name: Name
|
||||
): Promise<EphemeralSettings[Name]> {
|
||||
return ipcRenderer.invoke(`settings:get:${name}`);
|
||||
}
|
||||
|
||||
function setEphemeralSetting<Name extends keyof EphemeralSettings>(
|
||||
name: Name,
|
||||
value: EphemeralSettings[Name]
|
||||
): Promise<void> {
|
||||
return ipcRenderer.invoke(`settings:set:${name}`, value);
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
import { ThemeType } from '../types/Util';
|
||||
|
||||
export function getThemeType(): ThemeType {
|
||||
const themeSetting = window.Events.getThemeSetting();
|
||||
export async function getThemeType(): Promise<ThemeType> {
|
||||
const themeSetting = await window.Events.getThemeSetting();
|
||||
|
||||
if (themeSetting === 'light') {
|
||||
return ThemeType.light;
|
||||
|
|
|
@ -9,9 +9,8 @@ import type { UnwrapPromise } from '../types/Util';
|
|||
import type {
|
||||
IPCEventsValuesType,
|
||||
IPCEventsCallbacksType,
|
||||
IPCEventGetterType,
|
||||
IPCEventSetterType,
|
||||
} from './createIPCEvents';
|
||||
import type { SystemTraySetting } from '../types/SystemTraySetting';
|
||||
|
||||
type SettingOptionsType = {
|
||||
getter?: boolean;
|
||||
|
@ -23,7 +22,27 @@ export type SettingType<Value> = Readonly<{
|
|||
setValue: (value: Value) => Promise<Value>;
|
||||
}>;
|
||||
|
||||
function capitalize<Name extends keyof IPCEventsValuesType>(
|
||||
export type ThemeType = 'light' | 'dark' | 'system';
|
||||
|
||||
export type EphemeralSettings = {
|
||||
spellCheck: boolean;
|
||||
systemTraySetting: SystemTraySetting;
|
||||
themeSetting: ThemeType;
|
||||
localeOverride: string | null;
|
||||
};
|
||||
|
||||
export type SettingsValuesType = IPCEventsValuesType & EphemeralSettings;
|
||||
|
||||
type SettingGetterType<Key extends keyof SettingsValuesType> =
|
||||
`get${Capitalize<Key>}`;
|
||||
|
||||
type SettingSetterType<Key extends keyof SettingsValuesType> =
|
||||
`set${Capitalize<Key>}`;
|
||||
|
||||
type SettingUpdaterType<Key extends keyof SettingsValuesType> =
|
||||
`update${Capitalize<Key>}`;
|
||||
|
||||
function capitalize<Name extends keyof SettingsValuesType>(
|
||||
name: Name
|
||||
): Capitalize<Name> {
|
||||
const result = name.slice(0, 1).toUpperCase() + name.slice(1);
|
||||
|
@ -31,21 +50,27 @@ function capitalize<Name extends keyof IPCEventsValuesType>(
|
|||
return result as Capitalize<Name>;
|
||||
}
|
||||
|
||||
function getSetterName<Key extends keyof IPCEventsValuesType>(
|
||||
function getSetterName<Key extends keyof SettingsValuesType>(
|
||||
name: Key
|
||||
): IPCEventSetterType<Key> {
|
||||
): SettingSetterType<Key> {
|
||||
return `set${capitalize(name)}`;
|
||||
}
|
||||
|
||||
function getGetterName<Key extends keyof IPCEventsValuesType>(
|
||||
function getGetterName<Key extends keyof SettingsValuesType>(
|
||||
name: Key
|
||||
): IPCEventGetterType<Key> {
|
||||
): SettingGetterType<Key> {
|
||||
return `get${capitalize(name)}`;
|
||||
}
|
||||
|
||||
function getUpdaterName<Key extends keyof EphemeralSettings>(
|
||||
name: Key
|
||||
): SettingUpdaterType<Key> {
|
||||
return `update${capitalize(name)}`;
|
||||
}
|
||||
|
||||
export function createSetting<
|
||||
Name extends keyof IPCEventsValuesType,
|
||||
Value extends IPCEventsValuesType[Name]
|
||||
Name extends keyof SettingsValuesType,
|
||||
Value extends SettingsValuesType[Name]
|
||||
>(name: Name, overrideOptions: SettingOptionsType = {}): SettingType<Value> {
|
||||
const options = {
|
||||
getter: true,
|
||||
|
@ -86,7 +111,7 @@ export function createCallback<
|
|||
}
|
||||
|
||||
export function installSetting(
|
||||
name: keyof IPCEventsValuesType,
|
||||
name: keyof SettingsValuesType,
|
||||
{ getter = true, setter = true }: { getter?: boolean; setter?: boolean } = {}
|
||||
): void {
|
||||
const getterName = getGetterName(name);
|
||||
|
@ -135,6 +160,21 @@ export function installSetting(
|
|||
}
|
||||
}
|
||||
|
||||
export function installEphemeralSetting(name: keyof EphemeralSettings): void {
|
||||
installSetting(name);
|
||||
|
||||
const updaterName = getUpdaterName(name);
|
||||
|
||||
ipcRenderer.on(`settings:update:${name}`, async (_event, value) => {
|
||||
const updateFn = window.Events[updaterName] as (value: unknown) => void;
|
||||
if (!updateFn) {
|
||||
return;
|
||||
}
|
||||
|
||||
await updateFn(value);
|
||||
});
|
||||
}
|
||||
|
||||
export function installCallback<Name extends keyof IPCEventsCallbacksType>(
|
||||
name: Name
|
||||
): void {
|
||||
|
|
2
ts/window.d.ts
vendored
2
ts/window.d.ts
vendored
|
@ -41,7 +41,6 @@ import type { SocketStatus } from './types/SocketStatus';
|
|||
import type SyncRequest from './textsecure/SyncRequest';
|
||||
import type { MessageCache } from './services/MessageCache';
|
||||
import type { StateType } from './state/reducer';
|
||||
import type { SystemTraySetting } from './types/SystemTraySetting';
|
||||
import type { Address } from './types/Address';
|
||||
import type { QualifiedAddress } from './types/QualifiedAddress';
|
||||
import type { CIType } from './CI';
|
||||
|
@ -88,7 +87,6 @@ export type IPCType = {
|
|||
showWindowsNotification: (data: WindowsNotificationData) => Promise<void>;
|
||||
shutdown: () => void;
|
||||
titleBarDoubleClick: () => void;
|
||||
updateSystemTraySetting: (value: SystemTraySetting) => void;
|
||||
updateTrayIcon: (count: number) => void;
|
||||
};
|
||||
|
||||
|
|
|
@ -5,11 +5,10 @@ import { ipcRenderer } from 'electron';
|
|||
import type { MenuItemConstructorOptions } from 'electron';
|
||||
|
||||
import type { MenuOptionsType } from '../types/menu';
|
||||
import type { IPCEventsValuesType } from '../util/createIPCEvents';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
import type { LoggerType } from '../types/Logging';
|
||||
import type { NativeThemeType } from '../context/createNativeThemeListener';
|
||||
import type { SettingType } from '../util/preload';
|
||||
import type { SettingType, SettingsValuesType } from '../util/preload';
|
||||
import type { RendererConfigType } from '../types/RendererConfig';
|
||||
|
||||
import { Bytes } from '../context/Bytes';
|
||||
|
@ -58,7 +57,7 @@ export type MinimalSignalContextType = {
|
|||
nativeThemeListener: NativeThemeType;
|
||||
restartApp: () => void;
|
||||
Settings: {
|
||||
themeSetting: SettingType<IPCEventsValuesType['themeSetting']>;
|
||||
themeSetting: SettingType<SettingsValuesType['themeSetting']>;
|
||||
waitForChange: () => Promise<void>;
|
||||
};
|
||||
OS: {
|
||||
|
|
|
@ -127,11 +127,6 @@ const IPC: IPCType = {
|
|||
titleBarDoubleClick: () => {
|
||||
ipc.send('title-bar-double-click');
|
||||
},
|
||||
updateSystemTraySetting: (
|
||||
systemTraySetting /* : Readonly<SystemTraySetting> */
|
||||
) => {
|
||||
void ipc.invoke('update-system-tray-setting', systemTraySetting);
|
||||
},
|
||||
updateTrayIcon: unreadCount => ipc.send('update-tray-icon', unreadCount),
|
||||
};
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import { initMessageCleanup } from '../../services/messageStateCleanup';
|
|||
import { initializeMessageCounter } from '../../util/incrementMessageCounter';
|
||||
import { initializeRedux } from '../../state/initializeRedux';
|
||||
import * as Stickers from '../../types/Stickers';
|
||||
import { ThemeType } from '../../types/Util';
|
||||
|
||||
window.assert = assert;
|
||||
|
||||
|
@ -51,6 +52,7 @@ window.testUtilities = {
|
|||
},
|
||||
stories: [],
|
||||
storyDistributionLists: [],
|
||||
theme: ThemeType.dark,
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
// Copyright 2017 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { installCallback, installSetting } from '../util/preload';
|
||||
import {
|
||||
installCallback,
|
||||
installSetting,
|
||||
installEphemeralSetting,
|
||||
} from '../util/preload';
|
||||
|
||||
// ChatColorPicker redux hookups
|
||||
installCallback('getCustomColors');
|
||||
|
@ -48,14 +52,10 @@ installSetting('hasStoriesDisabled');
|
|||
installSetting('hideMenuBar');
|
||||
installSetting('incomingCallNotification');
|
||||
installSetting('lastSyncTime');
|
||||
installSetting('localeOverride');
|
||||
installSetting('notificationDrawAttention');
|
||||
installSetting('notificationSetting');
|
||||
installSetting('spellCheck');
|
||||
installSetting('systemTraySetting');
|
||||
installSetting('sentMediaQualitySetting');
|
||||
installSetting('textFormatting');
|
||||
installSetting('themeSetting');
|
||||
installSetting('universalExpireTimer');
|
||||
installSetting('zoomFactor');
|
||||
installSetting('phoneNumberDiscoverabilitySetting');
|
||||
|
@ -66,3 +66,8 @@ installCallback('getAvailableIODevices');
|
|||
installSetting('preferredAudioInputDevice');
|
||||
installSetting('preferredAudioOutputDevice');
|
||||
installSetting('preferredVideoInputDevice');
|
||||
|
||||
installEphemeralSetting('themeSetting');
|
||||
installEphemeralSetting('systemTraySetting');
|
||||
installEphemeralSetting('localeOverride');
|
||||
installEphemeralSetting('spellCheck');
|
||||
|
|
Loading…
Reference in a new issue