From 6127b65d8c6d836a0cf143828751513982b6e65e Mon Sep 17 00:00:00 2001 From: kadiryazici Date: Wed, 28 Feb 2024 18:20:59 +0300 Subject: [PATCH] Extract theme to a composable --- src/App.vue | 5 ++++- src/components/AppScroller.vue | 6 ++++-- src/composables/useTheme.ts | 26 ++++++++++++++++++++++++++ src/constants.ts | 3 --- src/stores/store.ts | 19 +------------------ src/utils/common.ts | 10 +++------- 6 files changed, 38 insertions(+), 31 deletions(-) create mode 100644 src/composables/useTheme.ts diff --git a/src/App.vue b/src/App.vue index b45da03..7c3d46e 100644 --- a/src/App.vue +++ b/src/App.vue @@ -12,6 +12,7 @@ import { AppStorage } from './storage' import { Page, useRoute } from './stores/route' import ContextMenu from './components/ContextMenu.vue' import { useContextmenu } from './stores/contextmenu' +import { useTheme } from './composables/useTheme' const store = useStore() const route = useRoute() @@ -22,8 +23,10 @@ useInterval(() => { store.fetchNotifications() }, FETCH_INTERVAL_DURATION) +const { theme } = useTheme() + watchEffect(() => { - if (store.theme === ColorPreference.Dark) + if (theme.value === ColorPreference.Dark) document.documentElement.classList.remove('light-theme') else document.documentElement.classList.add('light-theme') diff --git a/src/components/AppScroller.vue b/src/components/AppScroller.vue index adf5cc6..787cd03 100644 --- a/src/components/AppScroller.vue +++ b/src/components/AppScroller.vue @@ -9,8 +9,8 @@ import type { Option } from '../types' import { batchFn } from '../utils/batch' import { ColorPreference } from '../constants' import { useRoute } from '../stores/route' +import { useTheme } from '../composables/useTheme' -const store = useStore() const route = useRoute() const scrollView = ref>(null) @@ -28,10 +28,12 @@ watch(() => route.currentPage, () => { element.scrollTop = 0 }, { flush: 'post' }) +const { theme } = useTheme() + const options = computedEager(() => ({ scrollbars: { autoHide: 'scroll', - theme: store.theme === ColorPreference.Dark ? 'os-theme-light' : 'os-theme-dark', + theme: theme.value === ColorPreference.Dark ? 'os-theme-light' : 'os-theme-dark', }, })) diff --git a/src/composables/useTheme.ts b/src/composables/useTheme.ts new file mode 100644 index 0000000..2b7a1c2 --- /dev/null +++ b/src/composables/useTheme.ts @@ -0,0 +1,26 @@ +import { computed } from 'vue' +import { useMediaQuery } from '@vueuse/core' +import { singleton } from '../utils/common' +import { AppStorage } from '../storage' +import { ColorPreference } from '../constants' + +export const useTheme = singleton(() => { + const prefersDark = useMediaQuery('(prefers-color-scheme: dark)') + + const theme = computed(() => { + const preference = AppStorage.get('colorPreference') + + let theme: ColorPreference.Dark | ColorPreference.Light + + if (preference === ColorPreference.Dark) + theme = ColorPreference.Dark + else if (preference === ColorPreference.Light) + theme = ColorPreference.Light + else + theme = prefersDark.value ? ColorPreference.Dark : ColorPreference.Light + + return theme + }) + + return { theme, prefersDark } +}) diff --git a/src/constants.ts b/src/constants.ts index 6ece3b3..cedd20c 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,9 +1,6 @@ import { Mutex } from 'async-mutex' -import { useMediaQuery } from '@vueuse/core' import { Icons } from './components/Icons' -export const prefersDark = useMediaQuery('(prefers-color-scheme: dark)') - export enum CheckedNotificationProcess { Unsubscribe, MarkAsRead, diff --git a/src/stores/store.ts b/src/stores/store.ts index 78185fa..8ef4d94 100644 --- a/src/stores/store.ts +++ b/src/stores/store.ts @@ -5,9 +5,8 @@ import { ref, shallowRef, triggerRef, watchEffect } from 'vue' import pAll from 'p-all' import { type UpdateManifest, installUpdate } from '@tauri-apps/api/updater' import { relaunch } from '@tauri-apps/api/process' -import { computedEager } from '@vueuse/core' import { type MinimalRepository, type Thread, getNotifications, markNotificationAsRead, unsubscribeNotification } from '../api/notifications' -import { CheckedNotificationProcess, ColorPreference, InvokeCommand, notificationApiMutex, prefersDark } from '../constants' +import { CheckedNotificationProcess, InvokeCommand, notificationApiMutex } from '../constants' import { AppStorage } from '../storage' import type { NotificationList, Option } from '../types' import { filterNewThreads, isRepository, isThread, toNotificationList } from '../utils/notification' @@ -195,21 +194,6 @@ export const useStore = defineStore('store', () => { } } - const theme = computedEager(() => { - const preference = AppStorage.get('colorPreference') - - let theme: ColorPreference.Dark | ColorPreference.Light - - if (preference === ColorPreference.Dark) - theme = ColorPreference.Dark - else if (preference === ColorPreference.Light) - theme = ColorPreference.Light - else - theme = prefersDark.value ? ColorPreference.Dark : ColorPreference.Light - - return theme - }) - function isChecked(item: MinimalRepository | Thread | null) { if (item == null || !isCheckable(item)) return false @@ -301,7 +285,6 @@ export const useStore = defineStore('store', () => { failedLoadingNotifications, checkedItems, installingUpate, - theme, mutateNotifications, getThreadsOfRepository, isChecked, diff --git a/src/utils/common.ts b/src/utils/common.ts index 1c1b882..d48933b 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -1,8 +1,4 @@ -import type { Ref, UnwrapRef } from 'vue' - -/** - * Just returns value of passed ref, used for reactivity tracking. - */ -export function trackRef>(ref: T): UnwrapRef { - return ref.value +export function singleton(fn: () => T): () => T { + const instance = fn() + return () => instance }