diff --git a/komga-webui/package-lock.json b/komga-webui/package-lock.json index 380eee9df..f75ed7337 100644 --- a/komga-webui/package-lock.json +++ b/komga-webui/package-lock.json @@ -27,6 +27,7 @@ "vuelidate": "^0.7.5", "vuetify": "^2.3.7", "vuex": "^3.5.1", + "vuex-persistedstate": "^3.2.0", "vuex-router-sync": "^5.0.0" }, "devDependencies": { @@ -6618,7 +6619,6 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -17559,6 +17559,11 @@ "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", "dev": true }, + "node_modules/shvl": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/shvl/-/shvl-2.0.2.tgz", + "integrity": "sha512-G3KkIXPza3dgkt6Bo8zIl5K/KvAAhbG6o9KfAjhPvrIIzzAhnfc2ztv1i+iPTbNNM43MaBUqIaZwqVjkSgY/rw==" + }, "node_modules/sigmund": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", @@ -19884,6 +19889,19 @@ "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.5.1.tgz", "integrity": "sha512-w7oJzmHQs0FM9LXodfskhw9wgKBiaB+totOdb8sNzbTB2KDCEEwEs29NzBZFh/lmEK1t5tDmM1vtsO7ubG1DFw==" }, + "node_modules/vuex-persistedstate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vuex-persistedstate/-/vuex-persistedstate-3.2.0.tgz", + "integrity": "sha512-1Q4zV9cNaJtl59jN6rXbndemEtXKywZr0OFZnqgpYdwvdyy+64KNsEltKldQW+i03st5LuDwHsdOEevXIZUgdg==", + "dependencies": { + "deepmerge": "^4.2.2", + "shvl": "^2.0.2" + }, + "peerDependencies": { + "vue": "^2.0.0", + "vuex": "^2.0.0 || ^3.0.0" + } + }, "node_modules/vuex-router-sync": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/vuex-router-sync/-/vuex-router-sync-5.0.0.tgz", @@ -26653,8 +26671,7 @@ "deepmerge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" }, "default-gateway": { "version": "5.0.5", @@ -35712,6 +35729,11 @@ "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", "dev": true }, + "shvl": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/shvl/-/shvl-2.0.2.tgz", + "integrity": "sha512-G3KkIXPza3dgkt6Bo8zIl5K/KvAAhbG6o9KfAjhPvrIIzzAhnfc2ztv1i+iPTbNNM43MaBUqIaZwqVjkSgY/rw==" + }, "sigmund": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", @@ -37677,6 +37699,15 @@ "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.5.1.tgz", "integrity": "sha512-w7oJzmHQs0FM9LXodfskhw9wgKBiaB+totOdb8sNzbTB2KDCEEwEs29NzBZFh/lmEK1t5tDmM1vtsO7ubG1DFw==" }, + "vuex-persistedstate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vuex-persistedstate/-/vuex-persistedstate-3.2.0.tgz", + "integrity": "sha512-1Q4zV9cNaJtl59jN6rXbndemEtXKywZr0OFZnqgpYdwvdyy+64KNsEltKldQW+i03st5LuDwHsdOEevXIZUgdg==", + "requires": { + "deepmerge": "^4.2.2", + "shvl": "^2.0.2" + } + }, "vuex-router-sync": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/vuex-router-sync/-/vuex-router-sync-5.0.0.tgz", diff --git a/komga-webui/package.json b/komga-webui/package.json index 3bba07955..64a9b0d75 100644 --- a/komga-webui/package.json +++ b/komga-webui/package.json @@ -30,6 +30,7 @@ "vuelidate": "^0.7.5", "vuetify": "^2.3.7", "vuex": "^3.5.1", + "vuex-persistedstate": "^3.2.0", "vuex-router-sync": "^5.0.0" }, "devDependencies": { diff --git a/komga-webui/src/App.vue b/komga-webui/src/App.vue index edf698bd6..375b4f277 100644 --- a/komga-webui/src/App.vue +++ b/komga-webui/src/App.vue @@ -5,19 +5,69 @@ diff --git a/komga-webui/src/main.ts b/komga-webui/src/main.ts index 4a0c36bc7..967449d5d 100644 --- a/komga-webui/src/main.ts +++ b/komga-webui/src/main.ts @@ -28,16 +28,16 @@ Vue.use(lineClamp) Vue.use(VueCookies) Vue.use(httpPlugin) -Vue.use(komgaFileSystem, { http: Vue.prototype.$http }) -Vue.use(komgaSeries, { http: Vue.prototype.$http }) -Vue.use(komgaCollections, { http: Vue.prototype.$http }) -Vue.use(komgaReadLists, { http: Vue.prototype.$http }) -Vue.use(komgaBooks, { http: Vue.prototype.$http }) -Vue.use(komgaReferential, { http: Vue.prototype.$http }) -Vue.use(komgaClaim, { http: Vue.prototype.$http }) -Vue.use(komgaUsers, { store: store, http: Vue.prototype.$http }) -Vue.use(komgaLibraries, { store: store, http: Vue.prototype.$http }) -Vue.use(actuator, { http: Vue.prototype.$http }) +Vue.use(komgaFileSystem, {http: Vue.prototype.$http}) +Vue.use(komgaSeries, {http: Vue.prototype.$http}) +Vue.use(komgaCollections, {http: Vue.prototype.$http}) +Vue.use(komgaReadLists, {http: Vue.prototype.$http}) +Vue.use(komgaBooks, {http: Vue.prototype.$http}) +Vue.use(komgaReferential, {http: Vue.prototype.$http}) +Vue.use(komgaClaim, {http: Vue.prototype.$http}) +Vue.use(komgaUsers, {store: store, http: Vue.prototype.$http}) +Vue.use(komgaLibraries, {store: store, http: Vue.prototype.$http}) +Vue.use(actuator, {http: Vue.prototype.$http}) Vue.prototype.$_ = _ Vue.prototype.$eventHub = new Vue() diff --git a/komga-webui/src/plugins/persisted-state.ts b/komga-webui/src/plugins/persisted-state.ts new file mode 100644 index 000000000..6914a5330 --- /dev/null +++ b/komga-webui/src/plugins/persisted-state.ts @@ -0,0 +1,17 @@ +import {Module} from "vuex" +import {Theme} from "@/types/themes"; + +export const persistedModule: Module = { + state: { + locale: '', + theme: Theme.LIGHT, + }, + mutations: { + setLocale (state, val) { + state.locale = val + }, + setTheme (state, val) { + state.theme = val + }, + }, +} diff --git a/komga-webui/src/store.ts b/komga-webui/src/store.ts index a95483685..057086a8c 100644 --- a/komga-webui/src/store.ts +++ b/komga-webui/src/store.ts @@ -1,10 +1,16 @@ import Vue from 'vue' import Vuex from 'vuex' -import { BookDto } from '@/types/komga-books' -import {SeriesDto} from "@/types/komga-series"; +import {BookDto} from '@/types/komga-books' +import {SeriesDto} from "@/types/komga-series" +import createPersistedState from "vuex-persistedstate" +import {persistedModule} from './plugins/persisted-state' Vue.use(Vuex) +const persistedState = createPersistedState({ + paths: ['persistedState'], +}) + export default new Vuex.Store({ state: { // collections @@ -181,4 +187,8 @@ export default new Vuex.Store({ commit('setUpdateSeriesDialog', value) }, }, + modules: { + persistedState: persistedModule, + }, + plugins: [persistedState], }) diff --git a/komga-webui/src/views/Home.vue b/komga-webui/src/views/Home.vue index 01c57331b..e2eaffef0 100644 --- a/komga-webui/src/views/Home.vue +++ b/komga-webui/src/views/Home.vue @@ -102,9 +102,7 @@ - mdi-brightness-7 - mdi-brightness-3 - mdi-brightness-auto + {{ themeIcon }} ({text: this.$i18n.t('common.locale_name', x), value: x})), } }, @@ -173,18 +164,6 @@ export default Vue.extend({ if (this.isAdmin) { this.info = await this.$actuator.getInfo() } - - if (this.$cookies.isKey(cookieTheme)) { - const theme = this.$cookies.get(cookieTheme) - if (Object.values(Theme).includes(theme)) { - this.theme = 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[] { @@ -200,16 +179,25 @@ export default Vue.extend({ {text: this.$i18n.t(Theme.SYSTEM), value: Theme.SYSTEM}, ] }, + themeIcon(): string { + switch (this.theme) { + case Theme.LIGHT: + return 'mdi-brightness-7' + case Theme.DARK: + return 'mdi-brightness-3' + case Theme.SYSTEM: + return 'mdi-brightness-auto' + } + return '' + }, theme: { get: function (): Theme { - return this.settings.theme + return this.$store.state.persistedState.theme }, set: function (theme: Theme): void { if (Object.values(Theme).includes(theme)) { - this.settings.theme = theme - this.changeTheme(theme) - this.$cookies.set(cookieTheme, theme, Infinity) + this.$store.commit('setTheme', theme) } }, }, @@ -219,9 +207,7 @@ export default Vue.extend({ }, set: function (locale: string): void { if (this.$i18n.availableLocales.includes(locale)) { - this.$i18n.locale = locale - this.$cookies.set(cookieLocale, locale, Infinity) - this.$vuetify.rtl = (this.$t('common.locale_rtl') === 'true') + this.$store.commit('setLocale', locale) } }, }, @@ -230,26 +216,6 @@ export default Vue.extend({ toggleDrawer() { this.drawerVisible = !this.drawerVisible }, - systemThemeChange() { - if (this.theme === Theme.SYSTEM) { - this.changeTheme(this.theme) - } - }, - changeTheme(theme: Theme) { - 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') this.$router.push({name: 'login'}) diff --git a/komga-webui/src/views/Login.vue b/komga-webui/src/views/Login.vue index 7ed943a5d..1ec0d9e19 100644 --- a/komga-webui/src/views/Login.vue +++ b/komga-webui/src/views/Login.vue @@ -64,7 +64,7 @@ - + + + + + + @@ -93,8 +102,7 @@