diff --git a/komga-webui/src/types/themes.ts b/komga-webui/src/types/themes.ts new file mode 100644 index 000000000..3004fd73c --- /dev/null +++ b/komga-webui/src/types/themes.ts @@ -0,0 +1,5 @@ +export enum Theme { + LIGHT = 'Light', + DARK = 'Dark', + SYSTEM = 'System' +} diff --git a/komga-webui/src/views/Home.vue b/komga-webui/src/views/Home.vue index 3ceff2680..e06a8118e 100644 --- a/komga-webui/src/views/Home.vue +++ b/komga-webui/src/views/Home.vue @@ -97,20 +97,22 @@ - + - - + + - mdi-brightness-7 - mdi-brightness-3 + mdi-brightness-7 + mdi-brightness-3 + mdi-brightness-auto - - Light theme - Dark theme - + - + @@ -134,9 +136,10 @@ import Dialogs from '@/components/Dialogs.vue' import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue' import SearchBox from '@/components/SearchBox.vue' +import { Theme } from '@/types/themes' import Vue from 'vue' -const cookieDarkMode = 'darkmode' +const cookieTheme = 'theme' export default Vue.extend({ name: 'home', @@ -145,16 +148,36 @@ export default Vue.extend({ return { drawerVisible: this.$vuetify.breakpoint.lgAndUp, info: {} as ActuatorInfo, + activeTheme: Theme.LIGHT, + Theme, + themes: [ + { text: Theme.LIGHT.valueOf(), value: Theme.LIGHT }, + { text: Theme.DARK.valueOf(), value: Theme.DARK }, + { text: Theme.SYSTEM.valueOf(), value: Theme.SYSTEM }, + ], } }, + watch: { + activeTheme (val) { + this.changeTheme(val) + }, + }, async created () { if (this.isAdmin) { this.info = await this.$actuator.getInfo() } - if (this.$cookies.isKey(cookieDarkMode)) { - this.$vuetify.theme.dark = (this.$cookies.get(cookieDarkMode) === 'true') + if (this.$cookies.isKey(cookieTheme)) { + const theme = this.$cookies.get(cookieTheme) + if (Object.values(Theme).includes(theme)) { + this.activeTheme = theme as Theme + } } + + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', this.systemThemeChange) + }, + async beforeDestroy () { + window.matchMedia('(prefers-color-scheme: dark)').removeEventListener('change', this.systemThemeChange) }, computed: { libraries (): LibraryDto[] { @@ -168,9 +191,26 @@ export default Vue.extend({ toggleDrawer () { this.drawerVisible = !this.drawerVisible }, - toggleDarkMode () { - this.$vuetify.theme.dark = !this.$vuetify.theme.dark - this.$cookies.set(cookieDarkMode, this.$vuetify.theme.dark, Infinity) + systemThemeChange () { + if (this.activeTheme === Theme.SYSTEM) { + this.changeTheme(this.activeTheme) + } + }, + changeTheme (theme: Theme) { + this.$cookies.set(cookieTheme, theme.valueOf()) + switch (theme) { + case Theme.DARK: + this.$vuetify.theme.dark = true + break + + case Theme.SYSTEM: + this.$vuetify.theme.dark = (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) + break + + default: + this.$vuetify.theme.dark = false + break + } }, logout () { this.$store.dispatch('logout')