System theme preference (#1800)

* Add system preference to theme-settings

* Add watching logic to check for dark theme settings

* Add en system theme translation

* Add explicit darkTheme option to browserWindow

* Remove unnecessary themeSource line

* Fix lint errors

* Move to using main process messaging for theme change

* Add system dataset selectors for themes

* Fix lint errors

* Change system theme to system default

* Use system default for deciding background color of newWindow

* Add baseTheme to state persistance

* Use baseTheme on browserWindow creation

* Fix lint errors

* Improve window background logic

* Catch settingsDb errors

* Remove dark flash on light themes

* Fix lint issues

* Fix system default sync on multiple windows

* Load database on each new window

* Fix lint errors

* Update compatibility for shared electron storage

* Remove unused console log

* Revert unnecessary changes

* Fix window maximize white flash

* Fix handleBaseTheme usage

* Use data-system-theme instead of data-theme

* Revert window maximize changes

* Fix theme flash on new window open
This commit is contained in:
vallode 2022-05-11 16:30:40 +02:00 committed by GitHub
parent ea04ef0a90
commit 3dcea52b75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 70 additions and 10 deletions

View File

@ -12,6 +12,7 @@ const IpcChannels = {
START_POWER_SAVE_BLOCKER: 'start-power-save-blocker',
CREATE_NEW_WINDOW: 'create-new-window',
OPEN_IN_EXTERNAL_PLAYER: 'open-in-external-player',
NATIVE_THEME_UPDATE: 'native-theme-update',
DB_SETTINGS: 'db-settings',
DB_HISTORY: 'db-history',

View File

@ -27,6 +27,10 @@ class Settings {
return db.settings.findOne({ _id: 'bounds' })
}
static _findTheme() {
return db.settings.findOne({ _id: 'baseTheme' })
}
static _updateBounds(value) {
return db.settings.update({ _id: 'bounds' }, { _id: 'bounds', value }, { upsert: true })
}

View File

@ -16,7 +16,7 @@
<% } %>
</head>
<body class="dark mainRed secBlue">
<body>
<div id="app"></div>
<!-- Set `__static` path to static files in production -->
<script>

View File

@ -1,6 +1,6 @@
import {
app, BrowserWindow, dialog, Menu, ipcMain,
powerSaveBlocker, screen, session, shell
powerSaveBlocker, screen, session, shell, nativeTheme
} from 'electron'
import path from 'path'
import cp from 'child_process'
@ -35,6 +35,7 @@ function runApp() {
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true'
const isDev = process.env.NODE_ENV === 'development'
const isDebug = process.argv.includes('--debug')
let mainWindow
let startupUrl
@ -172,11 +173,33 @@ function runApp() {
}
async function createWindow({ replaceMainWindow = true, windowStartupUrl = null, showWindowNow = false } = { }) {
// Syncing new window background to theme choice.
const windowBackground = await baseHandlers.settings._findTheme().then(({ value }) => {
switch (value) {
case 'dark':
return '#212121'
case 'light':
return '#f1f1f1'
case 'black':
return '#000000'
case 'dracula':
return '#282a36'
case 'system':
default:
return nativeTheme.shouldUseDarkColors ? '#212121' : '#f1f1f1'
}
}).catch((error) => {
console.log(error)
// Default to nativeTheme settings if nothing is found.
return nativeTheme.shouldUseDarkColors ? '#212121' : '#f1f1f1'
})
/**
* Initial window options
*/
const commonBrowserWindowOptions = {
backgroundColor: '#212121',
backgroundColor: windowBackground,
darkTheme: nativeTheme.shouldUseDarkColors,
icon: isDev
? path.join(__dirname, '../../_icons/iconColor.png')
/* eslint-disable-next-line */
@ -191,6 +214,7 @@ function runApp() {
contextIsolation: false
}
}
const newWindow = new BrowserWindow(
Object.assign(
{
@ -241,6 +265,7 @@ function runApp() {
height: bounds.height
})
}
if (maximized) {
newWindow.maximize()
}
@ -345,6 +370,14 @@ function runApp() {
app.quit()
})
nativeTheme.on('updated', () => {
const allWindows = BrowserWindow.getAllWindows()
allWindows.forEach((window) => {
window.webContents.send(IpcChannels.NATIVE_THEME_UPDATE, nativeTheme.shouldUseDarkColors)
})
})
ipcMain.on(IpcChannels.ENABLE_PROXY, (_, url) => {
console.log(url)
session.defaultSession.setProxy({

View File

@ -12,6 +12,7 @@ import FtProgressBar from './components/ft-progress-bar/ft-progress-bar.vue'
import $ from 'jquery'
import { marked } from 'marked'
import Parser from 'rss-parser'
import { IpcChannels } from '../constants'
let ipcRenderer = null
@ -113,6 +114,10 @@ export default Vue.extend({
return this.$store.getters.getSecColor
},
systemTheme: function () {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
},
externalLinkOpeningPromptNames: function () {
return [
this.$t('Yes'),
@ -140,11 +145,13 @@ export default Vue.extend({
}
},
created () {
this.checkThemeSettings()
this.setBodyTheme()
this.setWindowTitle()
},
mounted: function () {
this.grabUserSettings().then(async () => {
this.checkThemeSettings()
await this.fetchInvidiousInstances({ isDev: this.isDev })
if (this.defaultInvidiousInstance === '') {
await this.setRandomCurrentInvidiousInstance()
@ -161,6 +168,7 @@ export default Vue.extend({
this.activateKeyboardShortcuts()
this.openAllLinksExternally()
this.enableOpenUrl()
this.watchSystemTheme()
await this.checkExternalPlayer()
}
@ -191,9 +199,8 @@ export default Vue.extend({
updateTheme: function (theme) {
console.group('updateTheme')
console.log('Theme: ', theme)
const className = `${theme.baseTheme} main${theme.mainColor} sec${theme.secColor}`
const body = document.getElementsByTagName('body')[0]
body.className = className
document.body.className = `${theme.baseTheme} main${theme.mainColor} sec${theme.secColor}`
document.body.dataset.systemTheme = this.systemTheme
console.groupEnd()
},
@ -441,6 +448,16 @@ export default Vue.extend({
})
},
/**
* Linux fix for dynamically updating theme preference, this works on
* all systems running the electron app.
*/
watchSystemTheme: function () {
ipcRenderer.on(IpcChannels.NATIVE_THEME_UPDATE, (event, shouldUseDarkColors) => {
document.body.dataset.systemTheme = shouldUseDarkColors ? 'dark' : 'light'
})
},
enableOpenUrl: function () {
ipcRenderer.on('openUrl', (event, url) => {
if (url) {

View File

@ -1,5 +1,6 @@
<template>
<div
v-if="dataReady"
id="app"
:class="{
hideOutlines: hideOutlines,

View File

@ -29,6 +29,7 @@ export default Vue.extend({
'no'
],
baseThemeValues: [
'system',
'light',
'dark',
'black',
@ -111,6 +112,7 @@ export default Vue.extend({
baseThemeNames: function () {
return [
this.$t('Settings.Theme Settings.Base Theme.System Default'),
this.$t('Settings.Theme Settings.Base Theme.Light'),
this.$t('Settings.Theme Settings.Base Theme.Dark'),
this.$t('Settings.Theme Settings.Base Theme.Black'),

View File

@ -167,7 +167,7 @@ const state = {
barColor: false,
checkForBlogPosts: true,
checkForUpdates: true,
baseTheme: 'dark',
baseTheme: 'system',
mainColor: 'Red',
secColor: 'Blue',
defaultCaptionSettings: '{}',

View File

@ -1,4 +1,4 @@
.light {
.system[data-system-theme*='light'], .light {
--primary-text-color: #212121;
--secondary-text-color: #424242;
--tertiary-text-color: #757575;
@ -22,7 +22,7 @@
--logo-text: url("~../../_icons/textColorSmall.png");
}
.dark {
.system[data-system-theme*='dark'], .dark {
--primary-text-color: #EEEEEE;
--secondary-text-color: #ddd;
--tertiary-text-color: #999;

View File

@ -167,6 +167,7 @@ Settings:
Base Theme: Base Theme
Black: Black
Dark: Dark
System Default: System Default
Light: Light
Dracula: Dracula
Main Color Theme:

View File

@ -162,6 +162,7 @@ Settings:
Base Theme: 'Base theme'
Black: 'Black'
Dark: 'Dark'
System Default: 'System Default'
Light: 'Light'
Dracula: 'Dracula'
Main Color Theme: