fix: web app dark mode (#131)
* fix: web app dark mode Signed-off-by: Innei <i@innei.in> * update electron logic Signed-off-by: Innei <i@innei.in> --------- Signed-off-by: Innei <i@innei.in>
This commit is contained in:
parent
b2d6797d42
commit
19796d9220
|
|
@ -177,7 +177,14 @@ export const router = {
|
|||
setAppearance: t.procedure
|
||||
.input<"light" | "dark" | "system">()
|
||||
.action(async ({ input }) => {
|
||||
nativeTheme.themeSource = input
|
||||
// NOTE: Temporarily changing to system to get the color mode that system is in at the moment may cause a bit of a problem.
|
||||
// On macos, there is a bug, traffic lights flicker
|
||||
nativeTheme.themeSource = "system"
|
||||
const systemColorMode = nativeTheme.shouldUseDarkColors ?
|
||||
"dark" :
|
||||
"light"
|
||||
|
||||
nativeTheme.themeSource = systemColorMode === input ? "system" : input
|
||||
}),
|
||||
setMacOSBadge: t.procedure.input<number>().action(async ({ input }) => {
|
||||
if (app.dock) {
|
||||
|
|
|
|||
|
|
@ -1,24 +1,68 @@
|
|||
import { jotaiStore } from "@renderer/lib/jotai"
|
||||
import { getStorageNS } from "@renderer/lib/ns"
|
||||
import { atom, useAtomValue } from "jotai"
|
||||
import { useLayoutEffect } from "react"
|
||||
import { atomWithStorage } from "jotai/utils"
|
||||
import { useCallback, useLayoutEffect } from "react"
|
||||
import { useMediaQuery } from "usehooks-ts"
|
||||
|
||||
const darkAtom = atom(false)
|
||||
export function useDark() {
|
||||
return useAtomValue(darkAtom)
|
||||
const useDarkQuery = () => useMediaQuery("(prefers-color-scheme: dark)")
|
||||
type ColorMode = "light" | "dark" | "system"
|
||||
const darkAtom = !window.electron ?
|
||||
atomWithStorage(
|
||||
getStorageNS("color-mode"),
|
||||
"system" as ColorMode,
|
||||
undefined,
|
||||
{
|
||||
getOnInit: true,
|
||||
},
|
||||
) :
|
||||
atom("system" as ColorMode)
|
||||
function useDarkElectron() {
|
||||
return useAtomValue(darkAtom) === "dark"
|
||||
}
|
||||
function useDarkWebApp() {
|
||||
const systemIsDark = useDarkQuery()
|
||||
const mode = useAtomValue(darkAtom)
|
||||
return mode === "dark" || (mode === "system" && systemIsDark)
|
||||
}
|
||||
export const useDark = window.electron ? useDarkElectron : useDarkWebApp
|
||||
|
||||
export const useSyncDark = () => {
|
||||
const isDark = useMediaQuery("(prefers-color-scheme: dark)")
|
||||
const useSyncDarkElectron = () => {
|
||||
const appIsDark = useDarkQuery()
|
||||
|
||||
useLayoutEffect(() => {
|
||||
jotaiStore.set(darkAtom, isDark)
|
||||
document.documentElement.dataset.theme = appIsDark ? "dark" : "light"
|
||||
disableTransition(["[role=switch]>*"])
|
||||
|
||||
document.documentElement.dataset.theme = isDark ? "dark" : "light"
|
||||
disableTransition([
|
||||
"[role=switch]>*",
|
||||
])
|
||||
}, [isDark])
|
||||
jotaiStore.set(darkAtom, appIsDark ? "dark" : "light")
|
||||
}, [appIsDark])
|
||||
}
|
||||
|
||||
const useSyncDarkWebApp = () => {
|
||||
const colorMode = useAtomValue(darkAtom)
|
||||
const systemIsDark = useDarkQuery()
|
||||
useLayoutEffect(() => {
|
||||
const realColorMode: Exclude<ColorMode, "system"> =
|
||||
colorMode === "system" ? (systemIsDark ? "dark" : "light") : colorMode
|
||||
document.documentElement.dataset.theme = realColorMode
|
||||
disableTransition(["[role=switch]>*"])
|
||||
}, [colorMode, systemIsDark])
|
||||
}
|
||||
|
||||
export const useSyncDark = window.electron ?
|
||||
useSyncDarkElectron :
|
||||
useSyncDarkWebApp
|
||||
|
||||
export const useSetDarkInWebApp = () => {
|
||||
const systemColorMode = useDarkQuery() ? "dark" : "light"
|
||||
return useCallback(
|
||||
(colorMode: Exclude<ColorMode, "system">) =>
|
||||
jotaiStore.set(
|
||||
darkAtom,
|
||||
colorMode === systemColorMode ? "system" : colorMode,
|
||||
),
|
||||
[systemColorMode],
|
||||
)
|
||||
}
|
||||
|
||||
function disableTransition(disableTransitionExclude: string[] = []) {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {
|
|||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@renderer/components/ui/select"
|
||||
import { useDark } from "@renderer/hooks/common"
|
||||
import { useDark, useSetDarkInWebApp } from "@renderer/hooks/common"
|
||||
import { tipcClient } from "@renderer/lib/client"
|
||||
import { getOS } from "@renderer/lib/utils"
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
|
|
@ -26,6 +26,8 @@ const SettingBuilder = createSettingBuilder(useUISettingValue)
|
|||
export const SettingAppearance = () => {
|
||||
const isDark = useDark()
|
||||
|
||||
const setDarkInWebApp = useSetDarkInWebApp()
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingsTitle />
|
||||
|
|
@ -41,7 +43,11 @@ export const SettingAppearance = () => {
|
|||
label="Dark Mode"
|
||||
checked={isDark}
|
||||
onCheckedChange={(e) => {
|
||||
tipcClient?.setAppearance(e ? "dark" : "light")
|
||||
if (window.electron) {
|
||||
tipcClient?.setAppearance(e ? "dark" : "light")
|
||||
} else {
|
||||
setDarkInWebApp(e ? "dark" : "light")
|
||||
}
|
||||
}}
|
||||
/>,
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue