diff --git a/src/App.vue b/src/App.vue index 6728627..c6d080c 100644 --- a/src/App.vue +++ b/src/App.vue @@ -19,34 +19,36 @@ import Navbar from './features/nav/components/Navbar.vue'; import Footer from './features/footer/components/Footer.vue'; import { updatePageTitle } from './router'; -import { useColorScheme } from './features/colorScheme/composables/useColorScheme'; -import { ref, provide, watch, watchEffect } from 'vue'; +import { useSettings } from './features/settings/composables/useSettings.js'; +import { computed, watch, watchEffect } from 'vue'; import { useRoute } from 'vue-router'; const route = useRoute(); -const { getColorScheme, updateColorScheme } = useColorScheme(); -const colorScheme = ref(null); -provide('colorScheme', colorScheme); -watch(colorScheme, (newValue) => { - updateColorScheme(newValue); +const { getSetting } = useSettings(); +const colorScheme = computed(() => getSetting(['appearance', 'colorScheme'])); + +const updateColorScheme = function updateColorScheme (newColorScheme) { document.body.style.setProperty(colorScheme, { auto: 'normal', dark: 'dark', light: 'light' }); - if (newValue === 'dark') { + if (newColorScheme === 'dark') { document.body.classList.add('dark'); } else { document.body.classList.remove('dark'); } - if (newValue === 'auto') { + if (newColorScheme === 'auto') { document.body.classList.add('color-scheme-auto'); } else { document.body.classList.remove('color-scheme-auto'); } +} +watch(colorScheme, (newColorScheme) => { + updateColorScheme(newColorScheme); }); -colorScheme.value = getColorScheme(); +updateColorScheme(colorScheme.value); watchEffect(() => updatePageTitle(route)); diff --git a/src/features/colorScheme/components/ColorSchemeButton.vue b/src/features/colorScheme/components/ColorSchemeButton.vue index 4f4c228..ed56e9d 100644 --- a/src/features/colorScheme/components/ColorSchemeButton.vue +++ b/src/features/colorScheme/components/ColorSchemeButton.vue @@ -17,12 +17,14 @@ limitations under the License. -
- {{ t('loading') }} -
-
+
- +
diff --git a/src/features/settings/views/__tests__/SettingsView.test.js b/src/features/settings/views/__tests__/SettingsView.test.js index e8584ce..446f3a1 100644 --- a/src/features/settings/views/__tests__/SettingsView.test.js +++ b/src/features/settings/views/__tests__/SettingsView.test.js @@ -16,8 +16,8 @@ limitations under the License. import SettingsView from '../SettingsView.vue'; import { mountComponent } from '@/test-utils/mountComponent.js'; -import { flushPromises } from '@vue/test-utils'; import { beforeEach, describe, expect, test, vi } from 'vitest'; +import { nextTick } from 'vue'; const settingsHoisted = vi.hoisted(() => [ { @@ -197,10 +197,8 @@ const settings = settingsHoisted.values(); const originalCurrentSection = 's0'; let currentSection = originalCurrentSection; -vi.mock('../../utils/settingsParser', () => ({ - loadSettingsConfig: vi.fn().mockResolvedValue({ - contents: settingsHoisted - }) +vi.mock('../../settings.json', () => ({ + default: { contents: settingsHoisted } })); vi.mock('vue-router', async (importOriginal) => { @@ -235,9 +233,7 @@ describe('SettingsView', () => { describe('sidebar', () => { test('shows all top-level sections', async () => { const wrapper = getWrapper(); - - await flushPromises(); - await wrapper.vm.$nextTick(); + await nextTick(); const sidebarItems = wrapper.findAll('.sidebar-sections-list > li'); settings.forEach((setting, index) => { @@ -254,47 +250,27 @@ describe('SettingsView', () => { describe('main', () => { describe('correct element', () => { - test('shows that it is loading', () => { - const wrapper = getWrapper(); - - const mainContentLoading = wrapper.find('.main-content--loading'); - const mainContentLoaded = wrapper.find('.main-content--loaded'); - const mainContentNoSection = wrapper.find('.main-content--no-section'); - - expect(mainContentLoading.exists()).toBe(true); - expect(mainContentLoaded.exists()).toBe(false); - expect(mainContentNoSection.exists()).toBe(false); - }); - test('shows that no section is selected', async () => { currentSection = ''; const wrapper = getWrapper(); + await nextTick(); - await flushPromises(); - await wrapper.vm.$nextTick(); - - const mainContentLoading = wrapper.find('.main-content--loading'); - const mainContentLoaded = wrapper.find('.main-content--loaded'); + const mainContent = wrapper.find('.settings-main-content'); const mainContentNoSection = wrapper.find('.main-content--no-section'); - expect(mainContentLoading.exists()).toBe(false); - expect(mainContentLoaded.exists()).toBe(false); + expect(mainContent.exists()).toBe(false); expect(mainContentNoSection.exists()).toBe(true); }); test('shows main content', async () => { const wrapper = getWrapper(); + await nextTick(); - await flushPromises(); - await wrapper.vm.$nextTick(); - - const mainContentLoading = wrapper.find('.main-content--loading'); - const mainContentLoaded = wrapper.find('.main-content--loaded'); + const mainContent = wrapper.find('.settings-main-content'); const mainContentNoSection = wrapper.find('.main-content--no-section'); - expect(mainContentLoading.exists()).toBe(false); - expect(mainContentLoaded.exists()).toBe(true); + expect(mainContent.exists()).toBe(true); expect(mainContentNoSection.exists()).toBe(false); }); }); diff --git a/src/locales/de.json b/src/locales/de.json index 1b82c31..93f7593 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -60,6 +60,21 @@ "option": { "ariaLabel": "Wählt die Option {option} aus" } + }, + "settings": { + "appearance": { + "title": "Erscheinungsbild", + "contents": { + "colorScheme": { + "title": "Farbschema", + "options": { + "auto": "An Systemfarbschema anpassen", + "light": "Hell", + "dark": "Dunkel" + } + } + } + } } } } \ No newline at end of file diff --git a/src/locales/en.json b/src/locales/en.json index c47a8c1..4c4c8a1 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -60,6 +60,21 @@ "option": { "ariaLabel": "Selects option {option}" } + }, + "settings": { + "appearance": { + "title": "Appearance", + "contents": { + "colorScheme": { + "title": "Color Scheme", + "options": { + "auto": "Adapt to system color scheme", + "light": "Light", + "dark": "Dark" + } + } + } + } } } } \ No newline at end of file diff --git a/src/main.js b/src/main.js index 90efd54..d7efce6 100644 --- a/src/main.js +++ b/src/main.js @@ -30,6 +30,9 @@ import rawFonts from './styles/fonts.json'; import './styles/common.css'; import './styles/variables/colors.css'; +import settings from './features/settings/settings.json'; +import { validateSettingsConfig } from './features/settings/utils/settingsValidator'; + (async () => { const fonts = rawFonts.map((font) => new FontFace( font.family ?? '', @@ -54,6 +57,8 @@ import './styles/variables/colors.css'; const pinia = createPinia(); pinia.use(piniaPluginPersistedstate); + + validateSettingsConfig(settings); createApp(App) .use(router)