Add "system" theme setting for MacOS

This commit is contained in:
Ken Powers 2019-05-16 15:32:38 -07:00 committed by Scott Nonnenberg
parent 089a232a60
commit fd36720079
13 changed files with 174 additions and 35 deletions

View File

@ -1625,6 +1625,10 @@
"message": "Dark",
"description": "Label text for dark theme"
},
"themeSystem": {
"message": "System",
"description": "Label text for system theme"
},
"noteToSelf": {
"message": "Note to Self",
"description": "Name for the conversation with your own phone number"

View File

@ -208,6 +208,7 @@
switch (theme) {
case 'dark':
case 'light':
case 'system':
return theme;
case 'android-dark':
return 'dark';
@ -231,7 +232,11 @@
window.Events = {
getDeviceName: () => textsecure.storage.user.getDeviceName(),
getThemeSetting: () => storage.get('theme-setting', 'light'),
getThemeSetting: () =>
storage.get(
'theme-setting',
window.platform === 'darwin' ? 'system' : 'light'
),
setThemeSetting: value => {
storage.put('theme-setting', value);
onChangeTheme();
@ -326,6 +331,19 @@
`New version detected: ${currentVersion}; previous: ${lastVersion}`
);
const themeSetting = window.Events.getThemeSetting();
const newThemeSetting = mapOldThemeToNew(themeSetting);
if (
window.isBeforeVersion(lastVersion, 'v1.25.0') &&
window.platform === 'darwin' &&
newThemeSetting === window.systemTheme
) {
window.Events.setThemeSetting('system');
} else {
window.Events.setThemeSetting(newThemeSetting);
}
if (window.isBeforeVersion(lastVersion, 'v1.25.0')) {
// Stickers flags
await Promise.all([
@ -334,6 +352,7 @@
]);
}
// This one should always be last - it could restart the app
if (window.isBeforeVersion(lastVersion, 'v1.15.0-beta.5')) {
await window.Signal.Logs.deleteAll();
window.restart();
@ -411,10 +430,6 @@
};
startSpellCheck();
const themeSetting = window.Events.getThemeSetting();
const newThemeSetting = mapOldThemeToNew(themeSetting);
window.Events.setThemeSetting(newThemeSetting);
try {
await Promise.all([
ConversationController.load(),

View File

@ -9,7 +9,23 @@ $(document).on('keyup', e => {
});
const $body = $(document.body);
$body.addClass(`${window.theme}-theme`);
async function applyTheme() {
'use strict';
const theme = await window.getThemeSetting();
$body.removeClass('light-theme');
$body.removeClass('dark-theme');
$body.addClass(`${theme === 'system' ? window.systemTheme : theme}-theme`);
}
applyTheme();
window.subscribeToSystemThemeChange(() => {
'use strict';
applyTheme();
});
window.view = new Whisper.ConfirmationDialogView({
message: i18n('audioPermissionNeeded'),

View File

@ -9,7 +9,23 @@ $(document).on('keyup', e => {
});
const $body = $(document.body);
$body.addClass(`${window.theme}-theme`);
async function applyTheme() {
'use strict';
const theme = await window.getThemeSetting();
$body.removeClass('light-theme');
$body.removeClass('dark-theme');
$body.addClass(`${theme === 'system' ? window.systemTheme : theme}-theme`);
}
applyTheme();
window.subscribeToSystemThemeChange(() => {
'use strict';
applyTheme();
});
// eslint-disable-next-line strict
const getInitialData = async () => ({

View File

@ -8,6 +8,14 @@
window.Whisper = window.Whisper || {};
function resolveTheme() {
const theme = storage.get('theme-setting') || 'light';
if (window.platform === 'darwin' && theme === 'system') {
return window.systemTheme;
}
return theme;
}
Whisper.AppView = Backbone.View.extend({
initialize() {
this.inboxView = null;
@ -15,14 +23,18 @@
this.applyTheme();
this.applyHideMenu();
window.subscribeToSystemThemeChange(() => {
this.applyTheme();
});
},
events: {
'click .openInstaller': 'openInstaller', // NetworkStatusView has this button
openInbox: 'openInbox',
},
applyTheme() {
const theme = resolveTheme();
const iOS = storage.get('userAgent') === 'OWI';
const theme = storage.get('theme-setting') || 'light';
this.$el
.removeClass('light-theme')
.removeClass('dark-theme')

View File

@ -88,7 +88,9 @@
$(document.body)
.removeClass('dark-theme')
.removeClass('light-theme')
.addClass(`${theme}-theme`);
.addClass(
`${theme === 'system' ? window.systemTheme : theme}-theme`
);
window.setThemeSetting(theme);
},
});
@ -143,8 +145,10 @@
audioNotificationDescription: i18n('audioNotificationDescription'),
isAudioNotificationSupported: Settings.isAudioNotificationSupported(),
isHideMenuBarSupported: Settings.isHideMenuBarSupported(),
hasSystemTheme: window.platform === 'darwin',
themeLight: i18n('themeLight'),
themeDark: i18n('themeDark'),
themeSystem: i18n('themeSystem'),
hideMenuBar: i18n('hideMenuBar'),
clearDataHeader: i18n('clearDataHeader'),
clearDataButton: i18n('clearDataButton'),

View File

@ -507,7 +507,6 @@ async function showSettingsWindow() {
return;
}
const theme = await pify(getDataFromMainWindow)('theme-setting');
const size = mainWindow.getSize();
const options = {
width: Math.min(500, size[0]),
@ -532,7 +531,7 @@ async function showSettingsWindow() {
captureClicks(settingsWindow);
settingsWindow.loadURL(prepareURL([__dirname, 'settings.html'], { theme }));
settingsWindow.loadURL(prepareURL([__dirname, 'settings.html']));
settingsWindow.on('closed', () => {
removeDarkOverlay();

View File

@ -181,6 +181,7 @@
"mac": {
"artifactName": "${name}-mac-${version}.${ext}",
"category": "public.app-category.social-networking",
"darkModeSupport": true,
"icon": "build/icons/mac/icon.icns",
"publish": [
{

View File

@ -1,9 +1,11 @@
/* global window */
const { ipcRenderer } = require('electron');
const { ipcRenderer, remote } = require('electron');
const url = require('url');
const i18n = require('./js/modules/i18n');
const { systemPreferences } = remote.require('electron');
const config = url.parse(window.location.toString(), true).query;
const { locale } = config;
const localeMessages = ipcRenderer.sendSync('locale-data');
@ -12,6 +14,25 @@ window.getVersion = () => config.version;
window.theme = config.theme;
window.i18n = i18n.setup(locale, localeMessages);
function setSystemTheme() {
window.systemTheme = systemPreferences.isDarkMode() ? 'dark' : 'light';
}
setSystemTheme();
window.subscribeToSystemThemeChange = fn => {
if (!systemPreferences.subscribeNotification) {
return;
}
systemPreferences.subscribeNotification(
'AppleInterfaceThemeChangedNotification',
() => {
setSystemTheme();
fn();
}
);
};
require('./js/logging');
window.closePermissionsPopup = () =>
@ -19,6 +40,8 @@ window.closePermissionsPopup = () =>
window.getMediaPermissions = makeGetter('media-permissions');
window.setMediaPermissions = makeSetter('media-permissions');
window.getThemeSetting = makeGetter('theme-setting');
window.setThemeSetting = makeSetter('theme-setting');
function makeGetter(name) {
return () =>

View File

@ -7,6 +7,7 @@ const semver = require('semver');
const { deferredToPromise } = require('./js/modules/deferred_to_promise');
const { app } = electron.remote;
const { systemPreferences } = electron.remote.require('electron');
window.PROTO_ROOT = 'protos';
const config = require('url').parse(window.location.toString(), true).query;
@ -31,6 +32,25 @@ window.getHostName = () => config.hostname;
window.getServerTrustRoot = () => config.serverTrustRoot;
window.isBehindProxy = () => Boolean(config.proxyUrl);
function setSystemTheme() {
window.systemTheme = systemPreferences.isDarkMode() ? 'dark' : 'light';
}
setSystemTheme();
window.subscribeToSystemThemeChange = fn => {
if (!systemPreferences.subscribeNotification) {
return;
}
systemPreferences.subscribeNotification(
'AppleInterfaceThemeChangedNotification',
() => {
setSystemTheme();
fn();
}
);
};
window.isBeforeVersion = (toCheck, baseVersion) => {
try {
return semver.lt(toCheck, baseVersion);

View File

@ -44,6 +44,12 @@
<hr>
<div class='theme-settings'>
<h3>{{ theme }}</h3>
{{#hasSystemTheme}}
<div>
<input type='radio' name='theme' id='theme-setting-system' value='system'>
<label for='theme-setting-system'>{{ themeSystem }}</label>
</div>
{{/hasSystemTheme}}
<div>
<input type='radio' name='theme' id='theme-setting-light' value='light'>
<label for='theme-setting-light'>{{ themeLight }}</label>

View File

@ -1,6 +1,7 @@
/* global window */
const { ipcRenderer } = require('electron');
const { ipcRenderer, remote } = require('electron');
const url = require('url');
const i18n = require('./js/modules/i18n');
@ -8,9 +9,31 @@ const config = url.parse(window.location.toString(), true).query;
const { locale } = config;
const localeMessages = ipcRenderer.sendSync('locale-data');
const { systemPreferences } = remote.require('electron');
window.platform = process.platform;
window.theme = config.theme;
window.i18n = i18n.setup(locale, localeMessages);
function setSystemTheme() {
window.systemTheme = systemPreferences.isDarkMode() ? 'dark' : 'light';
}
setSystemTheme();
window.subscribeToSystemThemeChange = fn => {
if (!systemPreferences.subscribeNotification) {
return;
}
systemPreferences.subscribeNotification(
'AppleInterfaceThemeChangedNotification',
() => {
setSystemTheme();
fn();
}
);
};
window.getEnvironment = () => config.environment;
window.getVersion = () => config.version;
window.getAppInstance = () => config.appInstance;

View File

@ -257,7 +257,7 @@
"rule": "jQuery-appendTo(",
"path": "js/permissions_popup_start.js",
"line": "window.view.$el.appendTo($body);",
"lineNumber": 26,
"lineNumber": 42,
"reasonCategory": "usageTrusted",
"updated": "2018-09-19T18:13:29.628Z",
"reasonDetail": "Interacting with already-existing DOM nodes"
@ -284,7 +284,7 @@
"rule": "jQuery-appendTo(",
"path": "js/settings_start.js",
"line": " window.view.$el.appendTo($body);",
"lineNumber": 41,
"lineNumber": 57,
"reasonCategory": "usageTrusted",
"updated": "2018-09-19T18:13:29.628Z",
"reasonDetail": "Interacting with already-existing DOM nodes"
@ -317,7 +317,7 @@
"rule": "DOM-innerHTML",
"path": "js/views/app_view.js",
"line": " this.el.innerHTML = '';",
"lineNumber": 43,
"lineNumber": 55,
"reasonCategory": "usageTrusted",
"updated": "2018-09-15T00:38:04.183Z",
"reasonDetail": "Hard-coded string"
@ -326,7 +326,7 @@
"rule": "jQuery-append(",
"path": "js/views/app_view.js",
"line": " this.el.append(view.el);",
"lineNumber": 44,
"lineNumber": 56,
"reasonCategory": "usageTrusted",
"updated": "2018-09-19T18:13:29.628Z",
"reasonDetail": "Interacting with already-existing DOM nodes"
@ -335,7 +335,7 @@
"rule": "jQuery-appendTo(",
"path": "js/views/app_view.js",
"line": " this.debugLogView.$el.appendTo(this.el);",
"lineNumber": 50,
"lineNumber": 62,
"reasonCategory": "usageTrusted",
"updated": "2018-09-19T18:13:29.628Z",
"reasonDetail": "Interacting with already-existing DOM nodes"
@ -1008,7 +1008,7 @@
"rule": "jQuery-$(",
"path": "js/views/settings_view.js",
"line": " el: this.$('.audio-notification-setting'),",
"lineNumber": 97,
"lineNumber": 99,
"reasonCategory": "usageTrusted",
"updated": "2018-09-19T21:59:32.770Z",
"reasonDetail": "Protected from arbitrary input"
@ -1017,7 +1017,7 @@
"rule": "jQuery-$(",
"path": "js/views/settings_view.js",
"line": " el: this.$('.spell-check-setting'),",
"lineNumber": 104,
"lineNumber": 106,
"reasonCategory": "usageTrusted",
"updated": "2018-09-19T21:59:32.770Z",
"reasonDetail": "Protected from arbitrary input"
@ -1026,7 +1026,7 @@
"rule": "jQuery-$(",
"path": "js/views/settings_view.js",
"line": " el: this.$('.menu-bar-setting'),",
"lineNumber": 111,
"lineNumber": 113,
"reasonCategory": "usageTrusted",
"updated": "2019-04-08T18:24:35.255Z",
"reasonDetail": "Protected from arbitrary input"
@ -1035,7 +1035,7 @@
"rule": "jQuery-$(",
"path": "js/views/settings_view.js",
"line": " el: this.$('.media-permissions'),",
"lineNumber": 118,
"lineNumber": 120,
"reasonCategory": "usageTrusted",
"updated": "2018-09-19T21:59:32.770Z",
"reasonDetail": "Protected from arbitrary input"
@ -1044,7 +1044,7 @@
"rule": "jQuery-$(",
"path": "js/views/settings_view.js",
"line": " this.$('.sync-setting').append(syncView.el);",
"lineNumber": 124,
"lineNumber": 126,
"reasonCategory": "usageTrusted",
"updated": "2018-09-19T21:59:32.770Z",
"reasonDetail": "Protected from arbitrary input"
@ -1053,7 +1053,7 @@
"rule": "jQuery-append(",
"path": "js/views/settings_view.js",
"line": " this.$('.sync-setting').append(syncView.el);",
"lineNumber": 124,
"lineNumber": 126,
"reasonCategory": "usageTrusted",
"updated": "2018-09-19T18:13:29.628Z",
"reasonDetail": "Interacting with already-existing DOM nodes"
@ -1062,25 +1062,25 @@
"rule": "jQuery-$(",
"path": "js/views/settings_view.js",
"line": " this.$('.sync').text(i18n('syncNow'));",
"lineNumber": 179,
"reasonCategory": "usageTrusted",
"updated": "2018-09-19T21:59:32.770Z",
"reasonDetail": "Protected from arbitrary input"
},
{
"rule": "jQuery-$(",
"path": "js/views/settings_view.js",
"line": " this.$('.sync').attr('disabled', 'disabled');",
"lineNumber": 183,
"reasonCategory": "usageTrusted",
"updated": "2018-09-19T21:59:32.770Z",
"reasonDetail": "Protected from arbitrary input"
},
{
"rule": "jQuery-$(",
"path": "js/views/settings_view.js",
"line": " this.$('.sync').attr('disabled', 'disabled');",
"lineNumber": 187,
"reasonCategory": "usageTrusted",
"updated": "2018-09-19T21:59:32.770Z",
"reasonDetail": "Protected from arbitrary input"
},
{
"rule": "jQuery-$(",
"path": "js/views/settings_view.js",
"line": " this.$('.synced_at').hide();",
"lineNumber": 195,
"lineNumber": 199,
"reasonCategory": "usageTrusted",
"updated": "2018-09-19T21:59:32.770Z",
"reasonDetail": "Protected from arbitrary input"
@ -1089,7 +1089,7 @@
"rule": "jQuery-$(",
"path": "js/views/settings_view.js",
"line": " this.$('.sync_failed').hide();",
"lineNumber": 200,
"lineNumber": 204,
"reasonCategory": "usageTrusted",
"updated": "2018-09-19T21:59:32.770Z",
"reasonDetail": "Protected from arbitrary input"