diff --git a/apps/pwa/src/app/index.tsx b/apps/pwa/src/app/index.tsx
index f491cd1c..a0c29d8f 100644
--- a/apps/pwa/src/app/index.tsx
+++ b/apps/pwa/src/app/index.tsx
@@ -5,8 +5,8 @@ import { ThemeProvider } from 'styled-components';
import { HashRouter } from 'react-router-dom';
import App from './app';
import UncaughtError from './uncaught_error';
-import theme from '../global_states/theme';
import Head from './head';
+import { useTheme } from '@/global_states/theme';
const fallback = (error: Error) => ;
@@ -14,7 +14,7 @@ function Wrapper() {
return (
-
+
diff --git a/apps/pwa/src/global_states/theme/index.ts b/apps/pwa/src/global_states/theme/index.ts
index 8bf02edd..a5b66b5d 100644
--- a/apps/pwa/src/global_states/theme/index.ts
+++ b/apps/pwa/src/global_states/theme/index.ts
@@ -1,30 +1,26 @@
import { MINI_MODE_MAX_WIDTH } from '@/constants';
-import XState from '@/utils/x_state';
import throttle from 'lodash/throttle';
import scrollbarObserver from './scrollbar_observer';
-import type { DefaultTheme } from 'styled-components';
+import { create } from 'zustand';
+import { Theme } from '@/styled';
-const theme = new XState({
+export const useTheme = create(() => ({
miniMode: window.innerWidth <= MINI_MODE_MAX_WIDTH,
autoScrollbar: scrollbarObserver.getScrollbarWidth() === 0,
-});
+}));
window.addEventListener(
'resize',
throttle(
() =>
- theme.set((t) => ({
- ...t,
+ useTheme.setState({
miniMode: window.innerWidth <= MINI_MODE_MAX_WIDTH,
- })),
+ }),
300,
),
);
scrollbarObserver.onChange(() =>
- theme.set((t) => ({
- ...t,
+ useTheme.setState({
autoScrollbar: scrollbarObserver.getScrollbarWidth() === 0,
- })),
+ }),
);
-
-export default theme;
diff --git a/apps/pwa/src/global_states/theme/scrollbar_observer.ts b/apps/pwa/src/global_states/theme/scrollbar_observer.ts
index 23fe9801..0fbb7908 100644
--- a/apps/pwa/src/global_states/theme/scrollbar_observer.ts
+++ b/apps/pwa/src/global_states/theme/scrollbar_observer.ts
@@ -3,16 +3,16 @@ import Eventin from 'eventin';
enum EventType {
RESIZE = 'resize',
}
-type EventTypeMapData = {
+interface EventTypeMapData {
[EventType.RESIZE]: null;
-};
+}
export default new (class {
outer: HTMLDivElement;
inner: HTMLDivElement;
- private eventemitter: Eventin;
+ private readonly eventemitter: Eventin;
constructor() {
this.eventemitter = new Eventin();
diff --git a/apps/pwa/src/pages/player/controller/controller.tsx b/apps/pwa/src/pages/player/controller/controller.tsx
index 795ef3b0..90089aa1 100644
--- a/apps/pwa/src/pages/player/controller/controller.tsx
+++ b/apps/pwa/src/pages/player/controller/controller.tsx
@@ -1,5 +1,4 @@
import styled, { css } from 'styled-components';
-import theme from '@/global_states/theme';
import { useContext } from 'react';
import getResizedImage from '@/server/asset/get_resized_image';
import { type QueueMusic, ZIndex } from '../constants';
@@ -12,6 +11,7 @@ import Context from '../context';
import playerEventemitter, {
EventType as PlayerEventType,
} from '../eventemitter';
+import { useTheme } from '@/global_states/theme';
const toggleLyric = () =>
playerEventemitter.emit(PlayerEventType.TOGGLE_LYRIC_PANEL, { open: true });
@@ -68,7 +68,7 @@ function Controller() {
| QueueMusic
| undefined;
- const { miniMode } = theme.useState();
+ const { miniMode } = useTheme();
return (