mirror of
https://gitlab.dit.htwk-leipzig.de/htwk-software/htwkalender-pwa.git
synced 2025-07-16 09:38:51 +02:00
fix:#20 first fix auto dark mode switch
This commit is contained in:
@ -21,8 +21,13 @@ import MenuBar from "./components/MenuBar.vue";
|
|||||||
import { RouteRecordName, RouterView } from "vue-router";
|
import { RouteRecordName, RouterView } from "vue-router";
|
||||||
import CalendarPreview from "./components/CalendarPreview.vue";
|
import CalendarPreview from "./components/CalendarPreview.vue";
|
||||||
import moduleStore from "./store/moduleStore.ts";
|
import moduleStore from "./store/moduleStore.ts";
|
||||||
import { provide, ref } from "vue";
|
import { onMounted, provide, ref } from "vue";
|
||||||
import { VueQueryDevtools } from "@tanstack/vue-query-devtools";
|
import { VueQueryDevtools } from "@tanstack/vue-query-devtools";
|
||||||
|
import settingsStore from "@/store/settingsStore.ts";
|
||||||
|
import { setTheme } from "@/helpers/theme.ts";
|
||||||
|
import { usePrimeVue } from "primevue/config";
|
||||||
|
|
||||||
|
const primeVue = usePrimeVue();
|
||||||
|
|
||||||
const disabledPages = [
|
const disabledPages = [
|
||||||
"room-finder",
|
"room-finder",
|
||||||
@ -33,7 +38,7 @@ const disabledPages = [
|
|||||||
"edit-calendar",
|
"edit-calendar",
|
||||||
"rooms",
|
"rooms",
|
||||||
"free-rooms",
|
"free-rooms",
|
||||||
"room-schedule",
|
"room-schedule"
|
||||||
];
|
];
|
||||||
|
|
||||||
const store = moduleStore();
|
const store = moduleStore();
|
||||||
@ -51,12 +56,25 @@ const updateMobile = () => {
|
|||||||
updateMobile();
|
updateMobile();
|
||||||
|
|
||||||
window.addEventListener("resize", updateMobile);
|
window.addEventListener("resize", updateMobile);
|
||||||
|
|
||||||
|
const settings = settingsStore();
|
||||||
|
const emit = defineEmits(["dark-mode-toggled"]);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// set theme matching browser preference
|
||||||
|
setTheme(settings, primeVue, emit, (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches));
|
||||||
|
|
||||||
|
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => {
|
||||||
|
setTheme(settings, primeVue, emit, e.matches);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<MenuBar />
|
<MenuBar />
|
||||||
<RouterView v-slot="{ Component, route }">
|
<RouterView v-slot="{ Component, route }">
|
||||||
<transition name="scale" mode="out-in">
|
<transition mode="out-in" name="scale">
|
||||||
<div :key="route.name ?? ''" class="origin-near-top">
|
<div :key="route.name ?? ''" class="origin-near-top">
|
||||||
<component :is="Component" />
|
<component :is="Component" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,43 +17,19 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, onMounted } from "vue";
|
import { toggleTheme } from "@/helpers/theme.ts";
|
||||||
|
import settingsStore from "@/store/settingsStore.ts";
|
||||||
|
import { computed } from "vue";
|
||||||
import { usePrimeVue } from "primevue/config";
|
import { usePrimeVue } from "primevue/config";
|
||||||
|
|
||||||
const PrimeVue = usePrimeVue();
|
const primeVue = usePrimeVue();
|
||||||
|
|
||||||
const emit = defineEmits(["dark-mode-toggled"]);
|
const emit = defineEmits(["dark-mode-toggled"]);
|
||||||
|
|
||||||
const isDark = ref(true);
|
const store = settingsStore();
|
||||||
const darkTheme = ref("lara-dark-blue"),
|
|
||||||
lightTheme = ref("lara-light-blue");
|
|
||||||
|
|
||||||
function toggleTheme() {
|
const isDark = computed(() => store.isDark);
|
||||||
isDark.value = !isDark.value;
|
|
||||||
setTheme(isDark.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setTheme(shouldBeDark: boolean) {
|
|
||||||
isDark.value = shouldBeDark;
|
|
||||||
const newTheme = isDark.value ? darkTheme.value : lightTheme.value,
|
|
||||||
oldTheme = isDark.value ? lightTheme.value : darkTheme.value;
|
|
||||||
PrimeVue.changeTheme(oldTheme, newTheme, "theme-link", () => {});
|
|
||||||
emit("dark-mode-toggled", isDark.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// set theme matching browser preference
|
|
||||||
setTheme(
|
|
||||||
window.matchMedia &&
|
|
||||||
window.matchMedia("(prefers-color-scheme: dark)").matches,
|
|
||||||
);
|
|
||||||
|
|
||||||
window
|
|
||||||
.matchMedia("(prefers-color-scheme: dark)")
|
|
||||||
.addEventListener("change", (e) => {
|
|
||||||
setTheme(e.matches);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -63,7 +39,7 @@ onMounted(() => {
|
|||||||
class="p-button-rounded md:w-auto"
|
class="p-button-rounded md:w-auto"
|
||||||
style="margin-right: 1rem"
|
style="margin-right: 1rem"
|
||||||
:severity="isDark ? 'warning' : 'success'"
|
:severity="isDark ? 'warning' : 'success'"
|
||||||
@click="toggleTheme()"
|
@click="toggleTheme(store, primeVue, emit)"
|
||||||
>
|
>
|
||||||
<i v-if="isDark" class="pi pi-sun"></i>
|
<i v-if="isDark" class="pi pi-sun"></i>
|
||||||
<i v-else class="pi pi-moon"></i>
|
<i v-else class="pi pi-moon"></i>
|
||||||
|
@ -18,7 +18,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import localeStore from "../store/localeStore.ts";
|
import settingsStore from "../store/settingsStore.ts";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { usePrimeVue } from "primevue/config";
|
import { usePrimeVue } from "primevue/config";
|
||||||
import primeVue_de from "@/i18n/translations/primevue/prime_vue_local_de.json";
|
import primeVue_de from "@/i18n/translations/primevue/prime_vue_local_de.json";
|
||||||
@ -43,7 +43,7 @@ function displayCountry(code: string) {
|
|||||||
const primeVueConfig = usePrimeVue();
|
const primeVueConfig = usePrimeVue();
|
||||||
|
|
||||||
function updateLocale(locale: string) {
|
function updateLocale(locale: string) {
|
||||||
localeStore().setLocale(locale);
|
settingsStore().setLocale(locale);
|
||||||
|
|
||||||
if (locale === "de") {
|
if (locale === "de") {
|
||||||
primeVueConfig.config.locale = primeVue_de;
|
primeVueConfig.config.locale = primeVue_de;
|
||||||
@ -54,7 +54,7 @@ function updateLocale(locale: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLocale(localeStore().locale);
|
updateLocale(settingsStore().locale);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
|
35
frontend/src/helpers/theme.ts
Normal file
35
frontend/src/helpers/theme.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
//Calendar implementation for the HTWK Leipzig timetable. Evaluation and display of the individual dates in iCal format.
|
||||||
|
//Copyright (C) 2024 HTWKalender support@htwkalender.de
|
||||||
|
|
||||||
|
//This program is free software: you can redistribute it and/or modify
|
||||||
|
//it under the terms of the GNU Affero General Public License as published by
|
||||||
|
//the Free Software Foundation, either version 3 of the License, or
|
||||||
|
//(at your option) any later version.
|
||||||
|
|
||||||
|
//This program is distributed in the hope that it will be useful,
|
||||||
|
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
//GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
//You should have received a copy of the GNU Affero General Public License
|
||||||
|
//along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
const darkTheme = ref("lara-dark-blue"),
|
||||||
|
lightTheme = ref("lara-light-blue");
|
||||||
|
|
||||||
|
|
||||||
|
export function toggleTheme(store, primeVue, emit): void {
|
||||||
|
store.setDarkMode(!store.isDark);
|
||||||
|
setTheme(store, primeVue, emit);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setTheme(store, primeVue, emit, shouldBeDark: boolean) {
|
||||||
|
store.setDarkMode(shouldBeDark);
|
||||||
|
const isDark = ref(store.isDark);
|
||||||
|
const newTheme = isDark.value ? darkTheme.value : lightTheme.value,
|
||||||
|
oldTheme = isDark.value ? lightTheme.value : darkTheme.value;
|
||||||
|
primeVue.changeTheme(oldTheme, newTheme, "theme-link", () => {});
|
||||||
|
emit("dark-mode-toggled", isDark.value);
|
||||||
|
}
|
@ -18,7 +18,7 @@ import { createI18n } from "vue-i18n";
|
|||||||
import en from "./translations/en.json";
|
import en from "./translations/en.json";
|
||||||
import de from "./translations/de.json";
|
import de from "./translations/de.json";
|
||||||
import ja from "./translations/ja.json";
|
import ja from "./translations/ja.json";
|
||||||
import localeStore from "../store/localeStore.ts";
|
import settingsStore from "../store/settingsStore.ts";
|
||||||
|
|
||||||
// Private instance of VueI18n object
|
// Private instance of VueI18n object
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@ -27,7 +27,7 @@ let _i18n: any;
|
|||||||
function setup() {
|
function setup() {
|
||||||
_i18n = createI18n({
|
_i18n = createI18n({
|
||||||
legacy: false,
|
legacy: false,
|
||||||
locale: localeStore().locale,
|
locale: settingsStore().locale,
|
||||||
fallbackLocale: "en",
|
fallbackLocale: "en",
|
||||||
messages: {
|
messages: {
|
||||||
en,
|
en,
|
||||||
|
@ -58,6 +58,8 @@ import i18n from "./i18n";
|
|||||||
import { VueQueryPlugin } from "@tanstack/vue-query";
|
import { VueQueryPlugin } from "@tanstack/vue-query";
|
||||||
import { polyfillCountryFlagEmojis } from "country-flag-emoji-polyfill";
|
import { polyfillCountryFlagEmojis } from "country-flag-emoji-polyfill";
|
||||||
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
|
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
|
||||||
|
import { setTheme } from "@/helpers/theme.ts";
|
||||||
|
import settingsStore from "@/store/settingsStore.ts";
|
||||||
|
|
||||||
polyfillCountryFlagEmojis();
|
polyfillCountryFlagEmojis();
|
||||||
|
|
||||||
@ -70,10 +72,10 @@ app.use(VueQueryPlugin, {
|
|||||||
queryClientConfig: {
|
queryClientConfig: {
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
queries: {
|
queries: {
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(PrimeVue);
|
app.use(PrimeVue);
|
||||||
|
@ -17,17 +17,24 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { useLocalStorage } from "@vueuse/core";
|
import { useLocalStorage } from "@vueuse/core";
|
||||||
|
|
||||||
const localeStore = defineStore("localeStore", {
|
const settingsStore = defineStore("settingsStore", {
|
||||||
state: () => {
|
state: () => {
|
||||||
return {
|
return {
|
||||||
locale: useLocalStorage("locale", "en"), //useLocalStorage takes in a key of 'count' and default value of 0
|
locale: useLocalStorage("locale", "en"), //useLocalStorage takes in a key of 'count' and default value of 0
|
||||||
|
isDark: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
setLocale(locale: string) {
|
setLocale(locale: string) {
|
||||||
this.locale = locale;
|
this.locale = locale;
|
||||||
},
|
},
|
||||||
|
setDarkMode(isDark: boolean) {
|
||||||
|
this.isDark = isDark;
|
||||||
|
},
|
||||||
|
getDarkMode(): boolean {
|
||||||
|
return this.isDark;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default localeStore;
|
export default settingsStore;
|
Reference in New Issue
Block a user