Dark theme loading screen
This commit is contained in:
parent
af2c884c9f
commit
b30c7f9c46
7 changed files with 114 additions and 18 deletions
92
app/main.ts
92
app/main.ts
|
@ -19,6 +19,7 @@ import {
|
|||
dialog,
|
||||
ipcMain as ipc,
|
||||
Menu,
|
||||
nativeTheme,
|
||||
powerSaveBlocker,
|
||||
protocol as electronProtocol,
|
||||
screen,
|
||||
|
@ -33,8 +34,11 @@ import * as GlobalErrors from './global_errors';
|
|||
import { setup as setupCrashReports } from './crashReports';
|
||||
import { setup as setupSpellChecker } from './spell_check';
|
||||
import { redactAll, addSensitivePath } from '../ts/util/privacy';
|
||||
import { missingCaseError } from '../ts/util/missingCaseError';
|
||||
import { strictAssert } from '../ts/util/assert';
|
||||
import { consoleLogger } from '../ts/util/consoleLogger';
|
||||
import type { ThemeSettingType } from '../ts/types/Storage.d';
|
||||
import { ThemeType } from '../ts/types/Util';
|
||||
|
||||
import './startup_config';
|
||||
|
||||
|
@ -230,6 +234,61 @@ async function getSpellCheckSetting() {
|
|||
return slowValue;
|
||||
}
|
||||
|
||||
type GetThemeSettingOptionsType = Readonly<{
|
||||
ephemeralOnly?: boolean;
|
||||
}>;
|
||||
|
||||
async function getThemeSetting({
|
||||
ephemeralOnly = false,
|
||||
}: GetThemeSettingOptionsType = {}): Promise<ThemeSettingType> {
|
||||
const fastValue = ephemeralConfig.get('theme-setting');
|
||||
if (fastValue !== undefined) {
|
||||
getLogger().info('got fast theme-setting value', fastValue);
|
||||
return fastValue as ThemeSettingType;
|
||||
}
|
||||
|
||||
if (ephemeralOnly) {
|
||||
return 'system';
|
||||
}
|
||||
|
||||
const json = await sql.sqlCall('getItemById', ['theme-setting']);
|
||||
|
||||
// Default to `system` if setting doesn't exist yet
|
||||
const slowValue = json ? json.value : 'system';
|
||||
|
||||
ephemeralConfig.set('theme-setting', slowValue);
|
||||
|
||||
getLogger().info('got slow theme-setting value', slowValue);
|
||||
|
||||
return slowValue;
|
||||
}
|
||||
|
||||
async function getResolvedThemeSetting(
|
||||
options?: GetThemeSettingOptionsType
|
||||
): Promise<ThemeType> {
|
||||
const theme = await getThemeSetting(options);
|
||||
if (theme === 'system') {
|
||||
return nativeTheme.shouldUseDarkColors ? ThemeType.dark : ThemeType.light;
|
||||
}
|
||||
return ThemeType[theme];
|
||||
}
|
||||
|
||||
async function getBackgroundColor(
|
||||
options?: GetThemeSettingOptionsType
|
||||
): Promise<string> {
|
||||
const theme = await getResolvedThemeSetting(options);
|
||||
|
||||
if (theme === 'light') {
|
||||
return '#3a76f0';
|
||||
}
|
||||
|
||||
if (theme === 'dark') {
|
||||
return '#121212';
|
||||
}
|
||||
|
||||
throw missingCaseError(theme);
|
||||
}
|
||||
|
||||
let systemTrayService: SystemTrayService | undefined;
|
||||
const systemTraySettingCache = new SystemTraySettingCache(
|
||||
sql,
|
||||
|
@ -479,7 +538,7 @@ async function createWindow() {
|
|||
: 'default',
|
||||
backgroundColor: isTestEnvironment(getEnvironment())
|
||||
? '#ffffff' // Tests should always be rendered on a white background
|
||||
: '#3a76f0',
|
||||
: await getBackgroundColor(),
|
||||
webPreferences: {
|
||||
...defaultWebPrefs,
|
||||
nodeIntegration: false,
|
||||
|
@ -599,6 +658,7 @@ async function createWindow() {
|
|||
|
||||
const moreKeys = {
|
||||
isFullScreen: String(Boolean(mainWindow.isFullScreen())),
|
||||
resolvedTheme: await getResolvedThemeSetting(),
|
||||
};
|
||||
|
||||
if (getEnvironment() === Environment.Test) {
|
||||
|
@ -996,7 +1056,7 @@ function showScreenShareWindow(sourceName: string) {
|
|||
}
|
||||
|
||||
let aboutWindow: BrowserWindow | undefined;
|
||||
function showAbout() {
|
||||
async function showAbout() {
|
||||
if (aboutWindow) {
|
||||
aboutWindow.show();
|
||||
return;
|
||||
|
@ -1008,7 +1068,7 @@ function showAbout() {
|
|||
resizable: false,
|
||||
title: getLocale().i18n('aboutSignalDesktop'),
|
||||
autoHideMenuBar: true,
|
||||
backgroundColor: '#3a76f0',
|
||||
backgroundColor: await getBackgroundColor(),
|
||||
show: false,
|
||||
webPreferences: {
|
||||
...defaultWebPrefs,
|
||||
|
@ -1038,7 +1098,7 @@ function showAbout() {
|
|||
}
|
||||
|
||||
let settingsWindow: BrowserWindow | undefined;
|
||||
function showSettingsWindow() {
|
||||
async function showSettingsWindow() {
|
||||
if (settingsWindow) {
|
||||
settingsWindow.show();
|
||||
return;
|
||||
|
@ -1051,7 +1111,7 @@ function showSettingsWindow() {
|
|||
resizable: false,
|
||||
title: getLocale().i18n('signalDesktopPreferences'),
|
||||
autoHideMenuBar: true,
|
||||
backgroundColor: '#3a76f0',
|
||||
backgroundColor: await getBackgroundColor(),
|
||||
show: false,
|
||||
webPreferences: {
|
||||
...defaultWebPrefs,
|
||||
|
@ -1121,7 +1181,7 @@ async function showStickerCreator() {
|
|||
height: 650,
|
||||
title: getLocale().i18n('signalDesktopStickerCreator'),
|
||||
autoHideMenuBar: true,
|
||||
backgroundColor: '#3a76f0',
|
||||
backgroundColor: await getBackgroundColor(),
|
||||
show: false,
|
||||
webPreferences: {
|
||||
...defaultWebPrefs,
|
||||
|
@ -1172,16 +1232,14 @@ async function showDebugLogWindow() {
|
|||
return;
|
||||
}
|
||||
|
||||
const theme = settingsChannel
|
||||
? await settingsChannel.getSettingFromMainWindow('themeSetting')
|
||||
: undefined;
|
||||
const theme = await getThemeSetting();
|
||||
const options = {
|
||||
width: 700,
|
||||
height: 500,
|
||||
resizable: false,
|
||||
title: getLocale().i18n('debugLog'),
|
||||
autoHideMenuBar: true,
|
||||
backgroundColor: '#3a76f0',
|
||||
backgroundColor: await getBackgroundColor(),
|
||||
show: false,
|
||||
webPreferences: {
|
||||
...defaultWebPrefs,
|
||||
|
@ -1235,9 +1293,7 @@ function showPermissionsPopupWindow(forCalling: boolean, forCamera: boolean) {
|
|||
return;
|
||||
}
|
||||
|
||||
const theme = settingsChannel
|
||||
? await settingsChannel.getSettingFromMainWindow('themeSetting')
|
||||
: undefined;
|
||||
const theme = await getThemeSetting();
|
||||
const size = mainWindow.getSize();
|
||||
const options = {
|
||||
width: Math.min(400, size[0]),
|
||||
|
@ -1245,7 +1301,7 @@ function showPermissionsPopupWindow(forCalling: boolean, forCamera: boolean) {
|
|||
resizable: false,
|
||||
title: getLocale().i18n('allowAccess'),
|
||||
autoHideMenuBar: true,
|
||||
backgroundColor: '#3a76f0',
|
||||
backgroundColor: await getBackgroundColor(),
|
||||
show: false,
|
||||
modal: true,
|
||||
webPreferences: {
|
||||
|
@ -1509,6 +1565,12 @@ app.on('ready', async () => {
|
|||
const timeout = new Promise(resolveFn =>
|
||||
setTimeout(resolveFn, 3000, 'timeout')
|
||||
);
|
||||
|
||||
// This color is to be used only in loading screen and in this case we should
|
||||
// never wait for the database to be initialized. Thus the theme setting
|
||||
// lookup should be done only in ephemeral config.
|
||||
const backgroundColor = await getBackgroundColor({ ephemeralOnly: true });
|
||||
|
||||
// eslint-disable-next-line more/no-then
|
||||
Promise.race([sqlInitPromise, timeout]).then(maybeTimeout => {
|
||||
if (maybeTimeout !== 'timeout') {
|
||||
|
@ -1525,7 +1587,7 @@ app.on('ready', async () => {
|
|||
height: 265,
|
||||
resizable: false,
|
||||
frame: false,
|
||||
backgroundColor: '#3a76f0',
|
||||
backgroundColor,
|
||||
webPreferences: {
|
||||
...defaultWebPrefs,
|
||||
nodeIntegration: false,
|
||||
|
|
|
@ -15,6 +15,7 @@ try {
|
|||
const { strictAssert } = require('./ts/util/assert');
|
||||
const { parseIntWithFallback } = require('./ts/util/parseIntWithFallback');
|
||||
const { UUIDKind } = require('./ts/types/UUID');
|
||||
const { ThemeType } = require('./ts/types/Util');
|
||||
|
||||
// It is important to call this as early as possible
|
||||
const { SignalContext } = require('./ts/windows/context');
|
||||
|
@ -247,6 +248,12 @@ try {
|
|||
});
|
||||
}
|
||||
|
||||
if (config.resolvedTheme === 'light') {
|
||||
window.initialTheme = ThemeType.light;
|
||||
} else if (config.resolvedTheme === 'dark') {
|
||||
window.initialTheme = ThemeType.dark;
|
||||
}
|
||||
|
||||
// Settings-related events
|
||||
|
||||
window.showSettings = () => ipc.send('show-settings');
|
||||
|
|
|
@ -235,7 +235,16 @@ $loading-height: 16px;
|
|||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
||||
/* Note: background-color is intentionally transparent until body has the
|
||||
* theme class.
|
||||
*/
|
||||
@include explicit-light-theme {
|
||||
background-color: $color-ultramarine-icon;
|
||||
}
|
||||
@include dark-theme {
|
||||
background-color: $color-gray-95;
|
||||
}
|
||||
color: $color-white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
|
@ -97,6 +97,12 @@
|
|||
@content;
|
||||
}
|
||||
|
||||
@mixin explicit-light-theme() {
|
||||
.light-theme & {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin dark-theme() {
|
||||
.dark-theme & {
|
||||
@content;
|
||||
|
|
|
@ -29,6 +29,7 @@ import type { Receipt } from './types/Receipt';
|
|||
import { getTitleBarVisibility, TitleBarVisibility } from './types/Settings';
|
||||
import { SocketStatus } from './types/SocketStatus';
|
||||
import { DEFAULT_CONVERSATION_COLOR } from './types/Colors';
|
||||
import { ThemeType } from './types/Util';
|
||||
import { ChallengeHandler } from './challenge';
|
||||
import * as durations from './util/durations';
|
||||
import { explodePromise } from './util/explodePromise';
|
||||
|
@ -166,6 +167,13 @@ export async function cleanupSessionResets(): Promise<void> {
|
|||
}
|
||||
|
||||
export async function startApp(): Promise<void> {
|
||||
if (window.initialTheme === ThemeType.light) {
|
||||
document.body.classList.add('light-theme');
|
||||
}
|
||||
if (window.initialTheme === ThemeType.dark) {
|
||||
document.body.classList.add('dark-theme');
|
||||
}
|
||||
|
||||
const idleDetector = new IdleDetector();
|
||||
|
||||
await KeyboardLayout.initialize();
|
||||
|
|
|
@ -17,6 +17,7 @@ import type {
|
|||
const EPHEMERAL_NAME_MAP = new Map([
|
||||
['spellCheck', 'spell-check'],
|
||||
['systemTraySetting', 'system-tray-setting'],
|
||||
['themeSetting', 'theme-setting'],
|
||||
]);
|
||||
|
||||
type ResponseQueueEntry = Readonly<{
|
||||
|
@ -68,7 +69,9 @@ export class SettingsChannel {
|
|||
this.installSetting('readReceiptSetting', { setter: false });
|
||||
this.installSetting('typingIndicatorSetting', { setter: false });
|
||||
|
||||
this.installSetting('themeSetting');
|
||||
this.installSetting('themeSetting', {
|
||||
isEphemeral: true,
|
||||
});
|
||||
this.installSetting('hideMenuBar');
|
||||
this.installSetting('systemTraySetting', {
|
||||
isEphemeral: true,
|
||||
|
|
3
ts/window.d.ts
vendored
3
ts/window.d.ts
vendored
|
@ -29,7 +29,7 @@ import * as Curve from './Curve';
|
|||
import * as RemoteConfig from './RemoteConfig';
|
||||
import * as OS from './OS';
|
||||
import { getEnvironment } from './environment';
|
||||
import { LocalizerType } from './types/Util';
|
||||
import { LocalizerType, ThemeType } from './types/Util';
|
||||
import type { Receipt } from './types/Receipt';
|
||||
import { ConversationController } from './ConversationController';
|
||||
import { ReduxActions } from './state/types';
|
||||
|
@ -212,6 +212,7 @@ declare global {
|
|||
isAfterVersion: (version: string, anotherVersion: string) => boolean;
|
||||
isBeforeVersion: (version: string, anotherVersion: string) => boolean;
|
||||
isFullScreen: () => boolean;
|
||||
initialTheme?: ThemeType;
|
||||
libphonenumber: {
|
||||
util: {
|
||||
getRegionCodeForNumber: (number: string) => string;
|
||||
|
|
Loading…
Reference in a new issue