From bdf12874031932f22cb168aa3383f84013f1155e Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Wed, 29 Sep 2021 11:37:30 -0700 Subject: [PATCH] Subscribe to theme change in settings --- main.js | 11 +++++++++-- ts/components/Preferences.stories.tsx | 2 -- ts/components/Preferences.tsx | 7 ------- ts/window.d.ts | 1 + ts/windows/applyTheme.ts | 12 ++++++++++++ ts/windows/configure.ts | 2 ++ ts/windows/settings/preload.ts | 3 +-- ts/windows/waitForSettingsChange.ts | 25 +++++++++++++++++++++++++ 8 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 ts/windows/waitForSettingsChange.ts diff --git a/main.js b/main.js index 92efede4a..fbf54fdb4 100644 --- a/main.js +++ b/main.js @@ -61,6 +61,8 @@ let mainWindow; let mainWindowCreated = false; let loadingWindow; +const activeWindows = new Set(); + function getMainWindow() { return mainWindow; } @@ -312,6 +314,9 @@ function handleCommonWindowEvents(window) { console.error(`Preload error in ${preloadPath}: `, error.message); }); + activeWindows.add(window); + window.on('closed', () => activeWindows.delete(window)); + // Works only for mainWindow because it has `enablePreferredSizeMode` let lastZoomFactor = window.webContents.getZoomFactor(); const onZoomChanged = () => { @@ -1804,8 +1809,10 @@ ipc.on('get-user-data-path', event => { // Refresh the settings window whenever preferences change ipc.on('preferences-changed', () => { - if (settingsWindow && settingsWindow.webContents) { - settingsWindow.webContents.send('render'); + for (const window of activeWindows) { + if (window.webContents) { + window.webContents.send('preferences-changed'); + } } }); diff --git a/ts/components/Preferences.stories.tsx b/ts/components/Preferences.stories.tsx index 1b72b451c..4a317cfa4 100644 --- a/ts/components/Preferences.stories.tsx +++ b/ts/components/Preferences.stories.tsx @@ -9,7 +9,6 @@ import enMessages from '../../_locales/en/messages.json'; import { Preferences, PropsType } from './Preferences'; import { setupI18n } from '../util/setupI18n'; import { DEFAULT_CONVERSATION_COLOR } from '../types/Colors'; -import { ThemeType } from '../types/Util'; import { PhoneNumberSharingMode } from '../util/phoneNumberSharingMode'; import { PhoneNumberDiscoverability } from '../util/phoneNumberDiscoverability'; @@ -93,7 +92,6 @@ const createProps = (): PropsType => ({ 'dfbe6effe70b0611ba0fdc2a9ea3f39f6cb110e6687948f7e5f016c111b7329c', selectedMicrophone: availableMicrophones[0], selectedSpeaker: availableSpeakers[1], - theme: ThemeType.light, themeSetting: 'system', universalExpireTimer: 3600, whoCanFindMe: PhoneNumberDiscoverability.Discoverable, diff --git a/ts/components/Preferences.tsx b/ts/components/Preferences.tsx index 3e6265400..f23a98b83 100644 --- a/ts/components/Preferences.tsx +++ b/ts/components/Preferences.tsx @@ -69,7 +69,6 @@ export type PropsType = { selectedCamera?: string; selectedMicrophone?: AudioDevice; selectedSpeaker?: AudioDevice; - theme: ThemeType; themeSetting: ThemeSettingType; universalExpireTimer: number; whoCanFindMe: PhoneNumberDiscoverability; @@ -257,7 +256,6 @@ export const Preferences = ({ selectedMicrophone, selectedSpeaker, setGlobalDefaultConversationColor, - theme, themeSetting, universalExpireTimer = 0, whoCanFindMe, @@ -273,11 +271,6 @@ export const Preferences = ({ setShowDisappearingTimerDialog, ] = useState(false); - useEffect(() => { - document.body.classList.toggle('light-theme', theme === ThemeType.light); - document.body.classList.toggle('dark-theme', theme === ThemeType.dark); - }, [theme]); - useEffect(() => { doneRendering(); }, [doneRendering]); diff --git a/ts/window.d.ts b/ts/window.d.ts index 1daf9f530..0f9e3caa5 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -474,6 +474,7 @@ declare global { SignalWindow: { Settings: { themeSetting: SettingType; + waitForChange: () => Promise; }; config: string; context: SignalContext; diff --git a/ts/windows/applyTheme.ts b/ts/windows/applyTheme.ts index 116902fbf..eef400fed 100644 --- a/ts/windows/applyTheme.ts +++ b/ts/windows/applyTheme.ts @@ -14,7 +14,19 @@ async function applyTheme() { ); } +async function applyThemeLoop() { + // eslint-disable-next-line no-constant-condition + while (true) { + // eslint-disable-next-line no-await-in-loop + await window.SignalWindow.Settings.waitForChange(); + + // eslint-disable-next-line no-await-in-loop + await applyTheme(); + } +} + applyTheme(); +applyThemeLoop(); window.SignalWindow.context.nativeThemeListener.subscribe(() => { applyTheme(); diff --git a/ts/windows/configure.ts b/ts/windows/configure.ts index 740c1e4b3..029c79e3c 100644 --- a/ts/windows/configure.ts +++ b/ts/windows/configure.ts @@ -13,6 +13,7 @@ import { import { strictAssert } from '../util/assert'; import { createSetting } from '../util/preload'; import { initialize as initializeLogging } from '../logging/set_up_renderer_logging'; +import { waitForSettingsChange } from './waitForSettingsChange'; const config = url.parse(window.location.toString(), true).query; const { locale } = config; @@ -29,6 +30,7 @@ initializeLogging(); export const SignalWindow = { Settings: { themeSetting: createSetting('themeSetting', { setter: false }), + waitForChange: waitForSettingsChange, }, config, context: window.SignalContext, diff --git a/ts/windows/settings/preload.ts b/ts/windows/settings/preload.ts index 0a7fede48..cbde26832 100644 --- a/ts/windows/settings/preload.ts +++ b/ts/windows/settings/preload.ts @@ -246,7 +246,6 @@ const renderPreferences = async () => { selectedCamera, selectedMicrophone, selectedSpeaker, - theme: themeSetting === 'system' ? window.systemTheme : themeSetting, themeSetting, universalExpireTimer, whoCanFindMe, @@ -360,7 +359,7 @@ const renderPreferences = async () => { ); }; -ipcRenderer.on('render', () => renderPreferences()); +ipcRenderer.on('preferences-changed', () => renderPreferences()); contextBridge.exposeInMainWorld('SignalWindow', { ...SignalWindow, diff --git a/ts/windows/waitForSettingsChange.ts b/ts/windows/waitForSettingsChange.ts new file mode 100644 index 000000000..45c3dd4be --- /dev/null +++ b/ts/windows/waitForSettingsChange.ts @@ -0,0 +1,25 @@ +// Copyright 2021 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only + +import { ipcRenderer as ipc } from 'electron'; + +import { explodePromise } from '../util/explodePromise'; + +let preferencesChangeResolvers = new Array<() => void>(); + +ipc.on('preferences-changed', _event => { + const resolvers = preferencesChangeResolvers; + preferencesChangeResolvers = []; + + for (const resolve of resolvers) { + resolve(); + } +}); + +export function waitForSettingsChange(): Promise { + const { promise, resolve } = explodePromise(); + + preferencesChangeResolvers.push(resolve); + + return promise; +}