perf: theme mode is compatible with website themes by default
This commit is contained in:
parent
c6301a826e
commit
6222e3f8af
8 changed files with 31 additions and 17 deletions
|
@ -14,7 +14,7 @@ import { Toaster } from 'sonner'
|
||||||
import DanmakuContainer from './components/DanmakuContainer'
|
import DanmakuContainer from './components/DanmakuContainer'
|
||||||
import DanmakuDomain from '@/domain/Danmaku'
|
import DanmakuDomain from '@/domain/Danmaku'
|
||||||
import AppStatusDomain from '@/domain/AppStatus'
|
import AppStatusDomain from '@/domain/AppStatus'
|
||||||
import { cn } from '@/utils'
|
import { checkDarkMode, cn } from '@/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fix requestAnimationFrame error in jest
|
* Fix requestAnimationFrame error in jest
|
||||||
|
@ -52,8 +52,6 @@ export default function App() {
|
||||||
}
|
}
|
||||||
}, [userInfoSetFinished, messageListLoadFinished])
|
}, [userInfoSetFinished, messageListLoadFinished])
|
||||||
|
|
||||||
const danmakuContainerRef = useRef<HTMLDivElement>(null)
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
danmakuIsEnabled && send(danmakuDomain.command.MountCommand(danmakuContainerRef.current!))
|
danmakuIsEnabled && send(danmakuDomain.command.MountCommand(danmakuContainerRef.current!))
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -61,8 +59,17 @@ export default function App() {
|
||||||
}
|
}
|
||||||
}, [danmakuIsEnabled])
|
}, [danmakuIsEnabled])
|
||||||
|
|
||||||
|
const themeMode =
|
||||||
|
userInfo?.themeMode === 'system'
|
||||||
|
? checkDarkMode()
|
||||||
|
? 'dark'
|
||||||
|
: 'light'
|
||||||
|
: (userInfo?.themeMode ?? (checkDarkMode() ? 'dark' : 'light'))
|
||||||
|
|
||||||
|
const danmakuContainerRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="app" className={cn('contents', userInfo?.themeMode)}>
|
<div id="app" className={cn('contents', themeMode)}>
|
||||||
{appStatusLoadIsFinished && (
|
{appStatusLoadIsFinished && (
|
||||||
<>
|
<>
|
||||||
<AppMain>
|
<AppMain>
|
||||||
|
@ -72,7 +79,7 @@ export default function App() {
|
||||||
{notUserInfo && <Setup></Setup>}
|
{notUserInfo && <Setup></Setup>}
|
||||||
<Toaster
|
<Toaster
|
||||||
richColors
|
richColors
|
||||||
theme={userInfo?.themeMode}
|
theme={themeMode}
|
||||||
offset="70px"
|
offset="70px"
|
||||||
visibleToasts={1}
|
visibleToasts={1}
|
||||||
toastOptions={{
|
toastOptions={{
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { Button } from '@/components/ui/Button'
|
||||||
import { EVENT } from '@/constants/event'
|
import { EVENT } from '@/constants/event'
|
||||||
import UserInfoDomain from '@/domain/UserInfo'
|
import UserInfoDomain from '@/domain/UserInfo'
|
||||||
import useTriggerAway from '@/hooks/useTriggerAway'
|
import useTriggerAway from '@/hooks/useTriggerAway'
|
||||||
import { checkSystemDarkMode, cn } from '@/utils'
|
import { checkDarkMode, cn } from '@/utils'
|
||||||
import LogoIcon0 from '@/assets/images/logo-0.svg'
|
import LogoIcon0 from '@/assets/images/logo-0.svg'
|
||||||
import LogoIcon1 from '@/assets/images/logo-1.svg'
|
import LogoIcon1 from '@/assets/images/logo-1.svg'
|
||||||
import LogoIcon2 from '@/assets/images/logo-2.svg'
|
import LogoIcon2 from '@/assets/images/logo-2.svg'
|
||||||
|
@ -36,8 +36,7 @@ const AppButton: FC<AppButtonProps> = ({ className }) => {
|
||||||
|
|
||||||
const DayLogo = [LogoIcon0, LogoIcon1, LogoIcon2, LogoIcon3, LogoIcon4, LogoIcon5, LogoIcon6][getDay(Date())]
|
const DayLogo = [LogoIcon0, LogoIcon1, LogoIcon2, LogoIcon3, LogoIcon4, LogoIcon5, LogoIcon6][getDay(Date())]
|
||||||
|
|
||||||
const isDarkMode =
|
const isDarkMode = userInfo?.themeMode === 'dark' ? true : userInfo?.themeMode === 'light' ? false : checkDarkMode()
|
||||||
userInfo?.themeMode === 'dark' ? true : userInfo?.themeMode === 'light' ? false : checkSystemDarkMode()
|
|
||||||
|
|
||||||
const [menuOpen, setMenuOpen] = useState(false)
|
const [menuOpen, setMenuOpen] = useState(false)
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/Avatar'
|
||||||
import { MAX_AVATAR_SIZE } from '@/constants/config'
|
import { MAX_AVATAR_SIZE } from '@/constants/config'
|
||||||
import MessageListDomain, { Message, MessageType } from '@/domain/MessageList'
|
import MessageListDomain, { Message, MessageType } from '@/domain/MessageList'
|
||||||
import UserInfoDomain, { UserInfo } from '@/domain/UserInfo'
|
import UserInfoDomain, { UserInfo } from '@/domain/UserInfo'
|
||||||
import { checkSystemDarkMode, generateRandomAvatar, generateRandomName } from '@/utils'
|
import { generateRandomAvatar, generateRandomName } from '@/utils'
|
||||||
import { UserIcon } from 'lucide-react'
|
import { UserIcon } from 'lucide-react'
|
||||||
import { nanoid } from 'nanoid'
|
import { nanoid } from 'nanoid'
|
||||||
import { FC, useEffect, useState } from 'react'
|
import { FC, useEffect, useState } from 'react'
|
||||||
|
@ -39,7 +39,7 @@ const generateUserInfo = async (): Promise<UserInfo> => {
|
||||||
name: generateRandomName(),
|
name: generateRandomName(),
|
||||||
avatar: await generateRandomAvatar(MAX_AVATAR_SIZE),
|
avatar: await generateRandomAvatar(MAX_AVATAR_SIZE),
|
||||||
createTime: Date.now(),
|
createTime: Date.now(),
|
||||||
themeMode: checkSystemDarkMode() ? 'dark' : 'system',
|
themeMode: 'system',
|
||||||
danmakuEnabled: true,
|
danmakuEnabled: true,
|
||||||
notificationEnabled: true,
|
notificationEnabled: true,
|
||||||
notificationType: 'all'
|
notificationType: 'all'
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { Button } from '@/components/ui/Button'
|
||||||
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/Form'
|
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/Form'
|
||||||
import { Input } from '@/components/ui/Input'
|
import { Input } from '@/components/ui/Input'
|
||||||
import UserInfoDomain, { type UserInfo } from '@/domain/UserInfo'
|
import UserInfoDomain, { type UserInfo } from '@/domain/UserInfo'
|
||||||
import { checkSystemDarkMode, cn, generateRandomAvatar } from '@/utils'
|
import { cn, generateRandomAvatar } from '@/utils'
|
||||||
import { RadioGroup, RadioGroupItem } from '@/components/ui/RadioGroup'
|
import { RadioGroup, RadioGroupItem } from '@/components/ui/RadioGroup'
|
||||||
import { Label } from '@/components/ui/Label'
|
import { Label } from '@/components/ui/Label'
|
||||||
import { RefreshCcwIcon } from 'lucide-react'
|
import { RefreshCcwIcon } from 'lucide-react'
|
||||||
|
@ -24,7 +24,7 @@ const defaultUserInfo: UserInfo = {
|
||||||
name: '',
|
name: '',
|
||||||
avatar: '',
|
avatar: '',
|
||||||
createTime: Date.now(),
|
createTime: Date.now(),
|
||||||
themeMode: checkSystemDarkMode() ? 'dark' : 'system',
|
themeMode: 'system',
|
||||||
danmakuEnabled: true,
|
danmakuEnabled: true,
|
||||||
notificationEnabled: true,
|
notificationEnabled: true,
|
||||||
notificationType: 'all'
|
notificationType: 'all'
|
||||||
|
|
|
@ -13,7 +13,7 @@ const ToastDomain = Remesh.domain({
|
||||||
name: 'Toast.OnRoomSelfJoinRoomEffect',
|
name: 'Toast.OnRoomSelfJoinRoomEffect',
|
||||||
impl: ({ fromEvent }) => {
|
impl: ({ fromEvent }) => {
|
||||||
const onRoomJoin$ = fromEvent(roomDomain.event.SelfJoinRoomEvent).pipe(
|
const onRoomJoin$ = fromEvent(roomDomain.event.SelfJoinRoomEvent).pipe(
|
||||||
map(() => toastModule.command.LoadingCommand('Connected to the chat.'))
|
map(() => toastModule.command.LoadingCommand({ message: 'Connected to the chat.', duration: 3000 }))
|
||||||
)
|
)
|
||||||
|
|
||||||
return onRoomJoin$
|
return onRoomJoin$
|
||||||
|
|
11
src/utils/checkDarkMode.ts
Normal file
11
src/utils/checkDarkMode.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
const checkDarkMode = () => {
|
||||||
|
const colorScheme = document.documentElement.style.getPropertyValue('color-scheme').trim()
|
||||||
|
|
||||||
|
if (colorScheme === 'dark') {
|
||||||
|
return true // Prefer the website's color-scheme property value
|
||||||
|
}
|
||||||
|
|
||||||
|
return window.matchMedia('(prefers-color-scheme: dark)').matches // Otherwise, check the system theme
|
||||||
|
}
|
||||||
|
|
||||||
|
export default checkDarkMode
|
|
@ -1,3 +0,0 @@
|
||||||
const checkSystemDarkMode = () => window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
||||||
|
|
||||||
export default checkSystemDarkMode
|
|
|
@ -4,7 +4,7 @@ export { default as createElement } from './createElement'
|
||||||
export { default as getSiteInfo } from './getSiteInfo'
|
export { default as getSiteInfo } from './getSiteInfo'
|
||||||
export { default as compressImage } from './compressImage'
|
export { default as compressImage } from './compressImage'
|
||||||
export { default as isNullish } from './isNullish'
|
export { default as isNullish } from './isNullish'
|
||||||
export { default as checkSystemDarkMode } from './checkSystemDarkMode'
|
export { default as checkDarkMode } from './checkDarkMode'
|
||||||
export { default as stringToHex } from './stringToHex'
|
export { default as stringToHex } from './stringToHex'
|
||||||
export { default as debounce } from './debounce'
|
export { default as debounce } from './debounce'
|
||||||
export { default as throttle } from './throttle'
|
export { default as throttle } from './throttle'
|
||||||
|
|
Loading…
Reference in a new issue