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:
parent
ea04ef0a90
commit
3dcea52b75
|
@ -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',
|
||||
|
|
|
@ -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 })
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<% } %>
|
||||
</head>
|
||||
|
||||
<body class="dark mainRed secBlue">
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<!-- Set `__static` path to static files in production -->
|
||||
<script>
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<div
|
||||
v-if="dataReady"
|
||||
id="app"
|
||||
:class="{
|
||||
hideOutlines: hideOutlines,
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -167,7 +167,7 @@ const state = {
|
|||
barColor: false,
|
||||
checkForBlogPosts: true,
|
||||
checkForUpdates: true,
|
||||
baseTheme: 'dark',
|
||||
baseTheme: 'system',
|
||||
mainColor: 'Red',
|
||||
secColor: 'Blue',
|
||||
defaultCaptionSettings: '{}',
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -167,6 +167,7 @@ Settings:
|
|||
Base Theme: Base Theme
|
||||
Black: Black
|
||||
Dark: Dark
|
||||
System Default: System Default
|
||||
Light: Light
|
||||
Dracula: Dracula
|
||||
Main Color Theme:
|
||||
|
|
|
@ -162,6 +162,7 @@ Settings:
|
|||
Base Theme: 'Base theme'
|
||||
Black: 'Black'
|
||||
Dark: 'Dark'
|
||||
System Default: 'System Default'
|
||||
Light: 'Light'
|
||||
Dracula: 'Dracula'
|
||||
Main Color Theme:
|
||||
|
|
Loading…
Reference in New Issue