diff --git a/src/App.vue b/src/App.vue index a752977607..3ec5a05472 100644 --- a/src/App.vue +++ b/src/App.vue @@ -155,11 +155,21 @@ export default { e.preventDefault(); return 'You may have unsaved edits. Are you sure you want to exit the page?'; }, + /* Detect and apply theme based on OS preference */ + applyThemeBasedOnOSPreference() { + const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; + const osTheme = prefersDark ? this.appConfig.nightTheme : this.appConfig.dayTheme; + if (osTheme) { + this.$store.commit(Keys.SET_THEME, osTheme); + this.updateTheme(osTheme); + } + }, }, /* Basic initialization tasks on app load */ async mounted() { await this.$store.dispatch(Keys.INITIALIZE_CONFIG); // Initialize config before moving on this.applyLanguage(); // Apply users local language + this.applyThemeBasedOnOSPreference(); // Apply theme based on OS preference this.hideSplash(); // Hide the splash screen, if visible if (this.appConfig.customCss) { // Inject users custom CSS, if present const cleanedCss = this.appConfig.customCss.replace(/<\/?[^>]+(>|$)/g, ''); diff --git a/src/mixins/ThemingMixin.js b/src/mixins/ThemingMixin.js index 64e21e7d7f..7659f351c4 100644 --- a/src/mixins/ThemingMixin.js +++ b/src/mixins/ThemingMixin.js @@ -136,6 +136,14 @@ const ThemingMixin = { } else if (hasExternal) { this.applyRemoteTheme(this.externalThemes[initialTheme]); } + + // Detect OS theme preference and apply the corresponding theme + const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; + const osTheme = prefersDark ? this.appConfig.nightTheme : this.appConfig.dayTheme; + if (osTheme) { + this.$store.commit(Keys.SET_THEME, osTheme); + this.updateTheme(osTheme); + } }, }, };