feat(webui): add system theme option

which will follow the OS theme and switch accordingly
This commit is contained in:
Shadowfied 2020-07-30 08:01:38 +02:00 committed by GitHub
parent ec3b9ba3df
commit 8f22f01b3b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 61 additions and 16 deletions

View file

@ -0,0 +1,5 @@
export enum Theme {
LIGHT = 'Light',
DARK = 'Dark',
SYSTEM = 'System'
}

View file

@ -97,20 +97,22 @@
</v-list-item> </v-list-item>
</v-list> </v-list>
<v-divider /> <v-divider/>
<v-list> <v-list>
<v-list-item @click="toggleDarkMode"> <v-list-item>
<v-list-item-icon> <v-list-item-icon>
<v-icon v-if="this.$vuetify.theme.dark">mdi-brightness-7</v-icon> <v-icon v-if="activeTheme === Theme.LIGHT">mdi-brightness-7</v-icon>
<v-icon v-else>mdi-brightness-3</v-icon> <v-icon v-if="activeTheme === Theme.DARK">mdi-brightness-3</v-icon>
<v-icon v-if="activeTheme === Theme.SYSTEM">mdi-brightness-auto</v-icon>
</v-list-item-icon> </v-list-item-icon>
<v-list-item-content> <v-select
<v-list-item-title v-if="this.$vuetify.theme.dark">Light theme</v-list-item-title> v-model="activeTheme"
<v-list-item-title v-else>Dark theme</v-list-item-title> :items="themes"
</v-list-item-content> label="Theme"
></v-select>
</v-list-item> </v-list-item>
</v-list> </v-list>
<v-spacer/> <v-spacer/>
@ -134,9 +136,10 @@
import Dialogs from '@/components/Dialogs.vue' import Dialogs from '@/components/Dialogs.vue'
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue' import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
import SearchBox from '@/components/SearchBox.vue' import SearchBox from '@/components/SearchBox.vue'
import { Theme } from '@/types/themes'
import Vue from 'vue' import Vue from 'vue'
const cookieDarkMode = 'darkmode' const cookieTheme = 'theme'
export default Vue.extend({ export default Vue.extend({
name: 'home', name: 'home',
@ -145,16 +148,36 @@ export default Vue.extend({
return { return {
drawerVisible: this.$vuetify.breakpoint.lgAndUp, drawerVisible: this.$vuetify.breakpoint.lgAndUp,
info: {} as ActuatorInfo, 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 () { async created () {
if (this.isAdmin) { if (this.isAdmin) {
this.info = await this.$actuator.getInfo() this.info = await this.$actuator.getInfo()
} }
if (this.$cookies.isKey(cookieDarkMode)) { if (this.$cookies.isKey(cookieTheme)) {
this.$vuetify.theme.dark = (this.$cookies.get(cookieDarkMode) === 'true') 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: { computed: {
libraries (): LibraryDto[] { libraries (): LibraryDto[] {
@ -168,9 +191,26 @@ export default Vue.extend({
toggleDrawer () { toggleDrawer () {
this.drawerVisible = !this.drawerVisible this.drawerVisible = !this.drawerVisible
}, },
toggleDarkMode () { systemThemeChange () {
this.$vuetify.theme.dark = !this.$vuetify.theme.dark if (this.activeTheme === Theme.SYSTEM) {
this.$cookies.set(cookieDarkMode, this.$vuetify.theme.dark, Infinity) 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 () { logout () {
this.$store.dispatch('logout') this.$store.dispatch('logout')