diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 1509958f1..8186d1ad0 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -305,6 +305,10 @@ "message": "Theme", "description": "Theme" }, + "theme_system": { + "message": "System", + "description": "Theme that follows the system light/dark setting" + }, "theme_light": { "message": "Light", "description": "Light theme" diff --git a/src/components/Popup.vue b/src/components/Popup.vue index 5ef9d0fd8..e3c91cae5 100644 --- a/src/components/Popup.vue +++ b/src/components/Popup.vue @@ -3,16 +3,16 @@ v-cloak v-bind:class="{ 'theme-normal': - theme !== 'accessibility' && - theme !== 'dark' && - theme !== 'simple' && - theme !== 'compact' && - theme !== 'flat', - 'theme-accessibility': theme === 'accessibility', - 'theme-dark': theme === 'dark', - 'theme-simple': theme === 'simple', - 'theme-compact': theme === 'compact', - 'theme-flat': theme === 'flat', + effectiveTheme !== 'accessibility' && + effectiveTheme !== 'dark' && + effectiveTheme !== 'simple' && + effectiveTheme !== 'compact' && + effectiveTheme !== 'flat', + 'theme-accessibility': effectiveTheme === 'accessibility', + 'theme-dark': effectiveTheme === 'dark', + 'theme-simple': effectiveTheme === 'simple', + 'theme-compact': effectiveTheme === 'compact', + 'theme-flat': effectiveTheme === 'flat', hideoutline, }" v-on:mousedown="hideoutline = true" @@ -88,14 +88,35 @@ for (const module of computedPrototype) { Object.assign(computed, module); } +Object.assign(computed, { + effectiveTheme(this: { theme: string; systemDark: boolean }) { + if (this.theme === "system") { + return this.systemDark ? "dark" : "normal"; + } + return this.theme; + }, +}); + +const darkQuery = window.matchMedia("(prefers-color-scheme: dark)"); + export default Vue.extend({ data: function () { return { hideoutline: true, + systemDark: darkQuery.matches, }; }, computed, + created() { + darkQuery.addEventListener("change", this.onSystemThemeChange); + }, + beforeDestroy() { + darkQuery.removeEventListener("change", this.onSystemThemeChange); + }, methods: { + onSystemThemeChange(event: MediaQueryListEvent) { + this.systemDark = event.matches; + }, hideQr() { this.$store.commit("style/hideQr"); }, diff --git a/src/components/Popup/PreferencesPage.vue b/src/components/Popup/PreferencesPage.vue index 299b9d8d1..71d0e80d0 100644 --- a/src/components/Popup/PreferencesPage.vue +++ b/src/components/Popup/PreferencesPage.vue @@ -5,6 +5,7 @@ v-model="theme" style="margin-left: 10px" > + diff --git a/src/store/Menu.ts b/src/store/Menu.ts index 48487d6ed..2af149119 100644 --- a/src/store/Menu.ts +++ b/src/store/Menu.ts @@ -13,7 +13,7 @@ export class Menu implements Module { useAutofill: UserSettings.items.autofill === true, smartFilter: UserSettings.items.smartFilter === true, enableContextMenu: UserSettings.items.enableContextMenu === true, - theme: UserSettings.items.theme || (isSafari ? "flat" : "normal"), + theme: UserSettings.items.theme || (isSafari ? "flat" : "system"), autolock: Number(UserSettings.items.autolock) || 30, backupDisabled: await ManagedStorage.get("disableBackup", false), exportDisabled: await ManagedStorage.get("disableExport", false),