Skip to content

Commit

Permalink
fix: set app dark mode instead of renderer (#130)
Browse files Browse the repository at this point in the history
* fix: set app dark mode instead of renderer

Signed-off-by: Innei <[email protected]>

* chore: remove jotai-dark

Signed-off-by: Innei <[email protected]>

---------

Signed-off-by: Innei <[email protected]>
  • Loading branch information
Innei authored Jul 11, 2024
1 parent 20f95dc commit 70df41f
Show file tree
Hide file tree
Showing 11 changed files with 86 additions and 89 deletions.
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@
"idb-keyval": "6.2.1",
"immer": "10.1.1",
"jotai": "2.8.4",
"jotai-dark": "0.4.0",
"jotai-effect": "1.0.0",
"lethargy": "1.0.9",
"lodash-es": "4.17.21",
"lowdb": "7.0.1",
Expand Down
35 changes: 0 additions & 35 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion src/main/tipc.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { createRequire } from "node:module"

import { getRendererHandlers, tipc } from "@egoist/tipc/main"
import { callGlobalContextMethod } from "@shared/bridge"
import type { BrowserWindow, MessageBoxOptions } from "electron"
import { app, dialog, Menu, ShareMenu } from "electron"
import { app, dialog, Menu, nativeTheme, ShareMenu } from "electron"

import { downloadFile } from "./lib/download"
import type { RendererHandlers } from "./renderer-handlers"
Expand All @@ -10,6 +12,7 @@ import { createSettingWindow, createWindow, getMainWindow } from "./window"

const t = tipc.create()

const require = createRequire(import.meta.url)
export const router = {
inspectElement: t.procedure
.input<{ x: number, y: number }>()
Expand Down Expand Up @@ -171,6 +174,11 @@ export const router = {
})
}),
),
setAppearance: t.procedure
.input<"light" | "dark" | "system">()
.action(async ({ input }) => {
nativeTheme.themeSource = input
}),
setMacOSBadge: t.procedure.input<number>().action(async ({ input }) => {
if (app.dock) {
if (input === 0) {
Expand Down
2 changes: 0 additions & 2 deletions src/renderer/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@ import { Outlet } from "react-router-dom"
import { useAppIsReady } from "./atoms/app"
import { useUISettingKey } from "./atoms/settings/ui"
import { Logo } from "./components/icons/logo"
import { useDark } from "./hooks/common/useDark"
import { tipcClient } from "./lib/client"
import { appLog } from "./lib/log"
import { getOS } from "./lib/utils"
import { RootProviders } from "./providers/root-providers"
import { handlers } from "./tipc"

function App() {
useDark()
useEffect(() => {
const cleanup = handlers?.invalidateQuery.listen((queryKey) => {
queryClient.invalidateQueries({
Expand Down
7 changes: 1 addition & 6 deletions src/renderer/src/components/ui/background/vibrancy.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { useUISettingKey } from "@renderer/atoms/settings/ui"
import { useDark } from "@renderer/hooks/common"
import { cn } from "@renderer/lib/utils"
import { useMediaQuery } from "usehooks-ts"

export const Vibrancy: Component<
React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
Expand All @@ -11,15 +9,12 @@ export const Vibrancy: Component<
window.electron &&
window.electron.process.platform === "darwin" &&
!opaqueSidebar
const systemDark = useMediaQuery("(prefers-color-scheme: dark)")
const { isDark } = useDark()

return (
<div
className={cn(
canVibrancy ? "bg-native/50 dark:bg-native/10" : "bg-native",
// NOTE: if the system is light and the app is dark, we need to apply a background to the vibrancy, otherwise it will be transparent
systemDark !== isDark && "!bg-native/75",

className,
)}
{...rest}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useDark } from "@renderer/hooks/common"

export const useShikiDefaultTheme = () => {
const { isDark } = useDark()
const isDark = useDark()

return isDark ? "github-dark" : "github-light"
}
38 changes: 18 additions & 20 deletions src/renderer/src/components/ui/sonner.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
import { useDark } from "@renderer/hooks/common"
import { Toaster as Sonner } from "sonner"

type ToasterProps = React.ComponentProps<typeof Sonner>

const Toaster = ({ ...props }: ToasterProps) => {
const { theme } = useDark()

return (
<Sonner
theme={theme as ToasterProps["theme"]}
className="toaster group"
toastOptions={{
classNames: {
toast: "group toast group-[.toaster]:bg-theme-background group-[.toaster]:text-theme-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
description: "group-[.toast]:text-muted-foreground",
actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
},
}}
{...props}
/>
)
}
const Toaster = ({ ...props }: ToasterProps) => (
<Sonner
theme="system"
className="toaster group"
toastOptions={{
classNames: {
toast:
"group toast group-[.toaster]:bg-theme-background group-[.toaster]:text-theme-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
description: "group-[.toast]:text-muted-foreground",
actionButton:
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
cancelButton:
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
},
}}
{...props}
/>
)

export { Toaster }
59 changes: 46 additions & 13 deletions src/renderer/src/hooks/common/useDark.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,50 @@
import { useAtom } from "jotai"
import { atomDark } from "jotai-dark"

const isDarkAtom = atomDark({
storageKey: "theme",
disableTransition: true,
mode: "data-theme",
})
import { jotaiStore } from "@renderer/lib/jotai"
import { atom, useAtomValue } from "jotai"
import { useLayoutEffect } from "react"
import { useMediaQuery } from "usehooks-ts"

const darkAtom = atom(false)
export function useDark() {
const [isDark, setIsDark] = useAtom(isDarkAtom)
return {
isDark,
toggleDark: setIsDark as () => void,
theme: (isDark ? "dark" : "light") as "dark" | "light",
return useAtomValue(darkAtom)
}

export const useSyncDark = () => {
const isDark = useMediaQuery("(prefers-color-scheme: dark)")

useLayoutEffect(() => {
jotaiStore.set(darkAtom, isDark)

document.documentElement.dataset.theme = isDark ? "dark" : "light"
disableTransition([
"[role=switch]>*",
])
}, [isDark])
}

function disableTransition(disableTransitionExclude: string[] = []) {
const css = document.createElement("style")
css.append(
document.createTextNode(
`
*${disableTransitionExclude.map((s) => `:not(${s})`).join("")} {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
-ms-transition: none !important;
transition: none !important;
}
`,
),
)
document.head.append(css)

return () => {
// Force restyle
(() => window.getComputedStyle(document.body))()

// Wait for next tick before removing
setTimeout(() => {
css.remove()
}, 1)
}
}
10 changes: 4 additions & 6 deletions src/renderer/src/modules/settings/tabs/apperance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { useDark } from "@renderer/hooks/common"
import { tipcClient } from "@renderer/lib/client"
import { getOS } from "@renderer/lib/utils"
import { useQuery } from "@tanstack/react-query"
import { useCallback } from "react"
import { bundledThemes } from "shiki/themes"

import { SettingSwitch } from "../control"
Expand All @@ -25,10 +24,7 @@ import { SettingsTitle } from "../title"
const SettingBuilder = createSettingBuilder(useUISettingValue)

export const SettingAppearance = () => {
const { isDark, toggleDark } = useDark()
const saveDarkSetting = useCallback(() => {
toggleDark()
}, [])
const isDark = useDark()

return (
<>
Expand All @@ -44,7 +40,9 @@ export const SettingAppearance = () => {
key="darkMode"
label="Dark Mode"
checked={isDark}
onCheckedChange={saveDarkSetting}
onCheckedChange={(e) => {
tipcClient?.setAppearance(e ? "dark" : "light")
}}
/>,
{
label: "Opaque Sidebars",
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/src/providers/root-providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { FC, PropsWithChildren } from "react"

import { StableRouterProvider } from "./biz-router-provider"
import { ContextMenuProvider } from "./context-menu-provider"
import { SettingSync } from "./ui-setting-Initialize"
import { SettingSync } from "./ui-setting-sync"
import { UserProvider } from "./user-provider"

const loadFeatures = () =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import { useUISettingValue } from "@renderer/atoms/settings/ui"
import { useSyncDark } from "@renderer/hooks/common"
import { tipcClient } from "@renderer/lib/client"
import { feedUnreadActions } from "@renderer/store/unread"
import { useEffect, useInsertionEffect } from "react"

const useUISettingSync = () => {
const setting = useUISettingValue()

useSyncDark()
useInsertionEffect(() => {
const root = document.documentElement
root.style.fontSize = `${setting.uiTextSize}px`
}, [setting.uiTextSize])

useEffect(() => {
if (setting.showDockBadge) {
return feedUnreadActions.subscribeUnreadCount((count) => tipcClient?.setMacOSBadge(count), true)
return feedUnreadActions.subscribeUnreadCount(
(count) => tipcClient?.setMacOSBadge(count),
true,
)
} else {
tipcClient?.setMacOSBadge(0)
}
Expand Down

0 comments on commit 70df41f

Please sign in to comment.