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',
|
START_POWER_SAVE_BLOCKER: 'start-power-save-blocker',
|
||||||
CREATE_NEW_WINDOW: 'create-new-window',
|
CREATE_NEW_WINDOW: 'create-new-window',
|
||||||
OPEN_IN_EXTERNAL_PLAYER: 'open-in-external-player',
|
OPEN_IN_EXTERNAL_PLAYER: 'open-in-external-player',
|
||||||
|
NATIVE_THEME_UPDATE: 'native-theme-update',
|
||||||
|
|
||||||
DB_SETTINGS: 'db-settings',
|
DB_SETTINGS: 'db-settings',
|
||||||
DB_HISTORY: 'db-history',
|
DB_HISTORY: 'db-history',
|
||||||
|
|
|
@ -27,6 +27,10 @@ class Settings {
|
||||||
return db.settings.findOne({ _id: 'bounds' })
|
return db.settings.findOne({ _id: 'bounds' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static _findTheme() {
|
||||||
|
return db.settings.findOne({ _id: 'baseTheme' })
|
||||||
|
}
|
||||||
|
|
||||||
static _updateBounds(value) {
|
static _updateBounds(value) {
|
||||||
return db.settings.update({ _id: 'bounds' }, { _id: 'bounds', value }, { upsert: true })
|
return db.settings.update({ _id: 'bounds' }, { _id: 'bounds', value }, { upsert: true })
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<% } %>
|
<% } %>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="dark mainRed secBlue">
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<!-- Set `__static` path to static files in production -->
|
<!-- Set `__static` path to static files in production -->
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {
|
import {
|
||||||
app, BrowserWindow, dialog, Menu, ipcMain,
|
app, BrowserWindow, dialog, Menu, ipcMain,
|
||||||
powerSaveBlocker, screen, session, shell
|
powerSaveBlocker, screen, session, shell, nativeTheme
|
||||||
} from 'electron'
|
} from 'electron'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import cp from 'child_process'
|
import cp from 'child_process'
|
||||||
|
@ -35,6 +35,7 @@ function runApp() {
|
||||||
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true'
|
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true'
|
||||||
const isDev = process.env.NODE_ENV === 'development'
|
const isDev = process.env.NODE_ENV === 'development'
|
||||||
const isDebug = process.argv.includes('--debug')
|
const isDebug = process.argv.includes('--debug')
|
||||||
|
|
||||||
let mainWindow
|
let mainWindow
|
||||||
let startupUrl
|
let startupUrl
|
||||||
|
|
||||||
|
@ -172,11 +173,33 @@ function runApp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createWindow({ replaceMainWindow = true, windowStartupUrl = null, showWindowNow = false } = { }) {
|
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
|
* Initial window options
|
||||||
*/
|
*/
|
||||||
const commonBrowserWindowOptions = {
|
const commonBrowserWindowOptions = {
|
||||||
backgroundColor: '#212121',
|
backgroundColor: windowBackground,
|
||||||
|
darkTheme: nativeTheme.shouldUseDarkColors,
|
||||||
icon: isDev
|
icon: isDev
|
||||||
? path.join(__dirname, '../../_icons/iconColor.png')
|
? path.join(__dirname, '../../_icons/iconColor.png')
|
||||||
/* eslint-disable-next-line */
|
/* eslint-disable-next-line */
|
||||||
|
@ -191,6 +214,7 @@ function runApp() {
|
||||||
contextIsolation: false
|
contextIsolation: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const newWindow = new BrowserWindow(
|
const newWindow = new BrowserWindow(
|
||||||
Object.assign(
|
Object.assign(
|
||||||
{
|
{
|
||||||
|
@ -241,6 +265,7 @@ function runApp() {
|
||||||
height: bounds.height
|
height: bounds.height
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maximized) {
|
if (maximized) {
|
||||||
newWindow.maximize()
|
newWindow.maximize()
|
||||||
}
|
}
|
||||||
|
@ -345,6 +370,14 @@ function runApp() {
|
||||||
app.quit()
|
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) => {
|
ipcMain.on(IpcChannels.ENABLE_PROXY, (_, url) => {
|
||||||
console.log(url)
|
console.log(url)
|
||||||
session.defaultSession.setProxy({
|
session.defaultSession.setProxy({
|
||||||
|
|
|
@ -12,6 +12,7 @@ import FtProgressBar from './components/ft-progress-bar/ft-progress-bar.vue'
|
||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
import { marked } from 'marked'
|
import { marked } from 'marked'
|
||||||
import Parser from 'rss-parser'
|
import Parser from 'rss-parser'
|
||||||
|
import { IpcChannels } from '../constants'
|
||||||
|
|
||||||
let ipcRenderer = null
|
let ipcRenderer = null
|
||||||
|
|
||||||
|
@ -113,6 +114,10 @@ export default Vue.extend({
|
||||||
return this.$store.getters.getSecColor
|
return this.$store.getters.getSecColor
|
||||||
},
|
},
|
||||||
|
|
||||||
|
systemTheme: function () {
|
||||||
|
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
||||||
|
},
|
||||||
|
|
||||||
externalLinkOpeningPromptNames: function () {
|
externalLinkOpeningPromptNames: function () {
|
||||||
return [
|
return [
|
||||||
this.$t('Yes'),
|
this.$t('Yes'),
|
||||||
|
@ -140,11 +145,13 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
this.checkThemeSettings()
|
this.setBodyTheme()
|
||||||
this.setWindowTitle()
|
this.setWindowTitle()
|
||||||
},
|
},
|
||||||
mounted: function () {
|
mounted: function () {
|
||||||
this.grabUserSettings().then(async () => {
|
this.grabUserSettings().then(async () => {
|
||||||
|
this.checkThemeSettings()
|
||||||
|
|
||||||
await this.fetchInvidiousInstances({ isDev: this.isDev })
|
await this.fetchInvidiousInstances({ isDev: this.isDev })
|
||||||
if (this.defaultInvidiousInstance === '') {
|
if (this.defaultInvidiousInstance === '') {
|
||||||
await this.setRandomCurrentInvidiousInstance()
|
await this.setRandomCurrentInvidiousInstance()
|
||||||
|
@ -161,6 +168,7 @@ export default Vue.extend({
|
||||||
this.activateKeyboardShortcuts()
|
this.activateKeyboardShortcuts()
|
||||||
this.openAllLinksExternally()
|
this.openAllLinksExternally()
|
||||||
this.enableOpenUrl()
|
this.enableOpenUrl()
|
||||||
|
this.watchSystemTheme()
|
||||||
await this.checkExternalPlayer()
|
await this.checkExternalPlayer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,9 +199,8 @@ export default Vue.extend({
|
||||||
updateTheme: function (theme) {
|
updateTheme: function (theme) {
|
||||||
console.group('updateTheme')
|
console.group('updateTheme')
|
||||||
console.log('Theme: ', theme)
|
console.log('Theme: ', theme)
|
||||||
const className = `${theme.baseTheme} main${theme.mainColor} sec${theme.secColor}`
|
document.body.className = `${theme.baseTheme} main${theme.mainColor} sec${theme.secColor}`
|
||||||
const body = document.getElementsByTagName('body')[0]
|
document.body.dataset.systemTheme = this.systemTheme
|
||||||
body.className = className
|
|
||||||
console.groupEnd()
|
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 () {
|
enableOpenUrl: function () {
|
||||||
ipcRenderer.on('openUrl', (event, url) => {
|
ipcRenderer.on('openUrl', (event, url) => {
|
||||||
if (url) {
|
if (url) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
|
v-if="dataReady"
|
||||||
id="app"
|
id="app"
|
||||||
:class="{
|
:class="{
|
||||||
hideOutlines: hideOutlines,
|
hideOutlines: hideOutlines,
|
||||||
|
|
|
@ -29,6 +29,7 @@ export default Vue.extend({
|
||||||
'no'
|
'no'
|
||||||
],
|
],
|
||||||
baseThemeValues: [
|
baseThemeValues: [
|
||||||
|
'system',
|
||||||
'light',
|
'light',
|
||||||
'dark',
|
'dark',
|
||||||
'black',
|
'black',
|
||||||
|
@ -111,6 +112,7 @@ export default Vue.extend({
|
||||||
|
|
||||||
baseThemeNames: function () {
|
baseThemeNames: function () {
|
||||||
return [
|
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.Light'),
|
||||||
this.$t('Settings.Theme Settings.Base Theme.Dark'),
|
this.$t('Settings.Theme Settings.Base Theme.Dark'),
|
||||||
this.$t('Settings.Theme Settings.Base Theme.Black'),
|
this.$t('Settings.Theme Settings.Base Theme.Black'),
|
||||||
|
|
|
@ -167,7 +167,7 @@ const state = {
|
||||||
barColor: false,
|
barColor: false,
|
||||||
checkForBlogPosts: true,
|
checkForBlogPosts: true,
|
||||||
checkForUpdates: true,
|
checkForUpdates: true,
|
||||||
baseTheme: 'dark',
|
baseTheme: 'system',
|
||||||
mainColor: 'Red',
|
mainColor: 'Red',
|
||||||
secColor: 'Blue',
|
secColor: 'Blue',
|
||||||
defaultCaptionSettings: '{}',
|
defaultCaptionSettings: '{}',
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.light {
|
.system[data-system-theme*='light'], .light {
|
||||||
--primary-text-color: #212121;
|
--primary-text-color: #212121;
|
||||||
--secondary-text-color: #424242;
|
--secondary-text-color: #424242;
|
||||||
--tertiary-text-color: #757575;
|
--tertiary-text-color: #757575;
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
--logo-text: url("~../../_icons/textColorSmall.png");
|
--logo-text: url("~../../_icons/textColorSmall.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.system[data-system-theme*='dark'], .dark {
|
||||||
--primary-text-color: #EEEEEE;
|
--primary-text-color: #EEEEEE;
|
||||||
--secondary-text-color: #ddd;
|
--secondary-text-color: #ddd;
|
||||||
--tertiary-text-color: #999;
|
--tertiary-text-color: #999;
|
||||||
|
|
|
@ -167,6 +167,7 @@ Settings:
|
||||||
Base Theme: Base Theme
|
Base Theme: Base Theme
|
||||||
Black: Black
|
Black: Black
|
||||||
Dark: Dark
|
Dark: Dark
|
||||||
|
System Default: System Default
|
||||||
Light: Light
|
Light: Light
|
||||||
Dracula: Dracula
|
Dracula: Dracula
|
||||||
Main Color Theme:
|
Main Color Theme:
|
||||||
|
|
|
@ -162,6 +162,7 @@ Settings:
|
||||||
Base Theme: 'Base theme'
|
Base Theme: 'Base theme'
|
||||||
Black: 'Black'
|
Black: 'Black'
|
||||||
Dark: 'Dark'
|
Dark: 'Dark'
|
||||||
|
System Default: 'System Default'
|
||||||
Light: 'Light'
|
Light: 'Light'
|
||||||
Dracula: 'Dracula'
|
Dracula: 'Dracula'
|
||||||
Main Color Theme:
|
Main Color Theme:
|
||||||
|
|
Loading…
Reference in New Issue