xref: /MusicFree/src/core/theme.ts (revision 41ddce918e1138d8f16e522cc7c19ac86ceca698)
1*41ddce91Smaotoumaoimport Config from "@/core/config.ts";
2a27adc20S猫头猫
3*41ddce91Smaotoumaoimport { DarkTheme as _DarkTheme, DefaultTheme as _DefaultTheme } from "@react-navigation/native";
4*41ddce91Smaotoumaoimport { GlobalState } from "@/utils/stateMapper";
5*41ddce91Smaotoumaoimport { CustomizedColors } from "@/hooks/useColors";
6*41ddce91Smaotoumaoimport Color from "color";
7a27adc20S猫头猫
8a27adc20S猫头猫export const lightTheme = {
9a27adc20S猫头猫    id: 'p-light',
10a27adc20S猫头猫    ..._DefaultTheme,
11a27adc20S猫头猫    colors: {
12a27adc20S猫头猫        ..._DefaultTheme.colors,
13a27adc20S猫头猫        background: 'transparent',
14a27adc20S猫头猫        text: '#333333',
15277c5280S猫头猫        textSecondary: Color('#333333').alpha(0.7).toString(),
16277c5280S猫头猫        primary: '#f17d34',
17277c5280S猫头猫        pageBackground: '#fafafa',
18277c5280S猫头猫        shadow: '#000',
19277c5280S猫头猫        appBar: '#f17d34',
20277c5280S猫头猫        appBarText: '#fefefe',
21277c5280S猫头猫        musicBar: '#f2f2f2',
22277c5280S猫头猫        musicBarText: '#333333',
23277c5280S猫头猫        divider: 'rgba(0,0,0,0.1)',
24a27adc20S猫头猫        listActive: 'rgba(0,0,0,0.1)', // 在手机上表现是ripple
25a27adc20S猫头猫        mask: 'rgba(51,51,51,0.2)',
26a27adc20S猫头猫        backdrop: '#f0f0f0',
27277c5280S猫头猫        tabBar: '#f0f0f0',
28a27adc20S猫头猫        placeholder: '#eaeaea',
29a27adc20S猫头猫        success: '#08A34C',
30a27adc20S猫头猫        danger: '#FC5F5F',
31a27adc20S猫头猫        info: '#0A95C8',
32f90698e4S猫头猫        card: '#e2e2e288',
33a27adc20S猫头猫    },
34a27adc20S猫头猫};
35a27adc20S猫头猫
36a27adc20S猫头猫export const darkTheme = {
37a27adc20S猫头猫    id: 'p-dark',
38a27adc20S猫头猫    ..._DarkTheme,
39a27adc20S猫头猫    colors: {
40a27adc20S猫头猫        ..._DarkTheme.colors,
41a27adc20S猫头猫        background: 'transparent',
42a27adc20S猫头猫        text: '#fcfcfc',
43277c5280S猫头猫        textSecondary: Color('#fcfcfc').alpha(0.7).toString(),
44277c5280S猫头猫        primary: '#3FA3B5',
45277c5280S猫头猫        pageBackground: '#202020',
46277c5280S猫头猫        shadow: '#999',
47277c5280S猫头猫        appBar: '#262626',
48277c5280S猫头猫        appBarText: '#fcfcfc',
49277c5280S猫头猫        musicBar: '#262626',
50277c5280S猫头猫        musicBarText: '#fcfcfc',
51277c5280S猫头猫        divider: 'rgba(255,255,255,0.1)',
52a27adc20S猫头猫        listActive: 'rgba(255,255,255,0.1)', // 在手机上表现是ripple
53a27adc20S猫头猫        mask: 'rgba(33,33,33,0.8)',
54a27adc20S猫头猫        backdrop: '#303030',
55277c5280S猫头猫        tabBar: '#303030',
56a27adc20S猫头猫        placeholder: '#424242',
57a27adc20S猫头猫        success: '#08A34C',
58a27adc20S猫头猫        danger: '#FC5F5F',
59a27adc20S猫头猫        info: '#0A95C8',
60f90698e4S猫头猫        card: '#33333388',
61a27adc20S猫头猫    },
62a27adc20S猫头猫};
63a27adc20S猫头猫
64a27adc20S猫头猫interface IBackgroundInfo {
65a27adc20S猫头猫    url?: string;
66a27adc20S猫头猫    blur?: number;
67a27adc20S猫头猫    opacity?: number;
68a27adc20S猫头猫}
69a27adc20S猫头猫
70a27adc20S猫头猫const themeStore = new GlobalState(darkTheme);
71a27adc20S猫头猫const backgroundStore = new GlobalState<IBackgroundInfo | null>(null);
72a27adc20S猫头猫
73a27adc20S猫头猫function setup() {
74*41ddce91Smaotoumao    const currentTheme = Config.getConfig('theme.selectedTheme') ?? 'p-dark';
75a27adc20S猫头猫
76a27adc20S猫头猫    if (currentTheme === 'p-dark') {
77a27adc20S猫头猫        themeStore.setValue(darkTheme);
78a27adc20S猫头猫    } else if (currentTheme === 'p-light') {
79a27adc20S猫头猫        themeStore.setValue(lightTheme);
80a27adc20S猫头猫    } else {
81a27adc20S猫头猫        themeStore.setValue({
82a27adc20S猫头猫            id: currentTheme,
83a27adc20S猫头猫            dark: true,
84a27adc20S猫头猫            // @ts-ignore
85a27adc20S猫头猫            colors:
86*41ddce91Smaotoumao                (Config.getConfig('theme.colors') as CustomizedColors) ??
87a27adc20S猫头猫                darkTheme.colors,
88a27adc20S猫头猫        });
89a27adc20S猫头猫    }
90a27adc20S猫头猫
91*41ddce91Smaotoumao    const bgUrl = Config.getConfig('theme.background');
92*41ddce91Smaotoumao    const bgBlur = Config.getConfig('theme.backgroundBlur');
93*41ddce91Smaotoumao    const bgOpacity = Config.getConfig('theme.backgroundOpacity');
94a27adc20S猫头猫
95a27adc20S猫头猫    backgroundStore.setValue({
96a27adc20S猫头猫        url: bgUrl,
97a27adc20S猫头猫        blur: bgBlur ?? 20,
98a27adc20S猫头猫        opacity: bgOpacity ?? 0.6,
99a27adc20S猫头猫    });
100a27adc20S猫头猫}
101a27adc20S猫头猫
102a27adc20S猫头猫function setTheme(
103a27adc20S猫头猫    themeName: string,
104a27adc20S猫头猫    extra?: {
105b4a87dd6S猫头猫        colors?: Partial<CustomizedColors>;
106a27adc20S猫头猫        background?: IBackgroundInfo;
107a27adc20S猫头猫    },
108a27adc20S猫头猫) {
109a27adc20S猫头猫    if (themeName === 'p-light') {
110a27adc20S猫头猫        themeStore.setValue(lightTheme);
111a27adc20S猫头猫    } else if (themeName === 'p-dark') {
112a27adc20S猫头猫        themeStore.setValue(darkTheme);
113a27adc20S猫头猫    } else {
114a27adc20S猫头猫        themeStore.setValue({
115a27adc20S猫头猫            id: themeName,
116a27adc20S猫头猫            dark: true,
117a27adc20S猫头猫            colors: {
118a27adc20S猫头猫                ...darkTheme.colors,
119a27adc20S猫头猫                ...(extra?.colors ?? {}),
120a27adc20S猫头猫            },
121a27adc20S猫头猫        });
122a27adc20S猫头猫    }
123a27adc20S猫头猫
124*41ddce91Smaotoumao    Config.setConfig('theme.selectedTheme', themeName);
125*41ddce91Smaotoumao    Config.setConfig('theme.colors', themeStore.getValue().colors);
126a27adc20S猫头猫
127a27adc20S猫头猫    if (extra?.background) {
128a27adc20S猫头猫        const currentBg = backgroundStore.getValue();
129b4a87dd6S猫头猫        let newBg: IBackgroundInfo = {
130a27adc20S猫头猫            blur: 20,
131a27adc20S猫头猫            opacity: 0.6,
132a27adc20S猫头猫            ...(currentBg ?? {}),
133a27adc20S猫头猫            url: undefined,
134a27adc20S猫头猫        };
1350843c497STheo        if (typeof extra.background.blur === 'number') {
136a27adc20S猫头猫            newBg.blur = extra.background.blur;
137a27adc20S猫头猫        }
1380843c497STheo        if (typeof extra.background.opacity === 'number') {
139a27adc20S猫头猫            newBg.opacity = extra.background.opacity;
140a27adc20S猫头猫        }
141b4a87dd6S猫头猫        if (extra.background.url) {
142b4a87dd6S猫头猫            newBg.url = extra.background.url;
143b4a87dd6S猫头猫        }
144a27adc20S猫头猫
145*41ddce91Smaotoumao        Config.setConfig('theme.background', newBg.url);
146*41ddce91Smaotoumao        Config.setConfig('theme.backgroundBlur', newBg.blur);
147*41ddce91Smaotoumao        Config.setConfig('theme.backgroundOpacity', newBg.opacity);
148a27adc20S猫头猫
149a27adc20S猫头猫        backgroundStore.setValue(newBg);
150a27adc20S猫头猫    }
151a27adc20S猫头猫}
152a27adc20S猫头猫
153a27adc20S猫头猫function setColors(colors: Partial<CustomizedColors>) {
154a27adc20S猫头猫    const currentTheme = themeStore.getValue();
155a27adc20S猫头猫    if (currentTheme.id !== 'p-light' && currentTheme.id !== 'p-dark') {
156a27adc20S猫头猫        const newTheme = {
157a27adc20S猫头猫            ...currentTheme,
158a27adc20S猫头猫            colors: {
159a27adc20S猫头猫                ...currentTheme.colors,
160a27adc20S猫头猫                ...colors,
161a27adc20S猫头猫            },
162a27adc20S猫头猫        };
163*41ddce91Smaotoumao        Config.setConfig('theme.customColors', newTheme.colors);
164*41ddce91Smaotoumao        Config.setConfig('theme.colors', newTheme.colors);
165a27adc20S猫头猫        themeStore.setValue(newTheme);
166a27adc20S猫头猫    }
167a27adc20S猫头猫}
168a27adc20S猫头猫
169a27adc20S猫头猫function setBackground(backgroundInfo: Partial<IBackgroundInfo>) {
170a27adc20S猫头猫    const currentBackgroundInfo = backgroundStore.getValue();
171a27adc20S猫头猫    let newBgInfo = {
172a27adc20S猫头猫        ...(currentBackgroundInfo ?? {
173a27adc20S猫头猫            opacity: 0.6,
174a27adc20S猫头猫            blur: 20,
175a27adc20S猫头猫        }),
176a27adc20S猫头猫    };
17719003909STheo    if (typeof backgroundInfo.blur === 'number') {
178*41ddce91Smaotoumao        Config.setConfig('theme.backgroundBlur', backgroundInfo.blur);
179a27adc20S猫头猫        newBgInfo.blur = backgroundInfo.blur;
180a27adc20S猫头猫    }
18119003909STheo    if (typeof backgroundInfo.opacity === 'number') {
182*41ddce91Smaotoumao        Config.setConfig('theme.backgroundOpacity', backgroundInfo.opacity);
183a27adc20S猫头猫        newBgInfo.opacity = backgroundInfo.opacity;
184a27adc20S猫头猫    }
185a27adc20S猫头猫    if (backgroundInfo.url !== undefined) {
186*41ddce91Smaotoumao        Config.setConfig('theme.background', backgroundInfo.url);
187a27adc20S猫头猫        newBgInfo.url = backgroundInfo.url;
188a27adc20S猫头猫    }
189a27adc20S猫头猫    backgroundStore.setValue(newBgInfo);
190a27adc20S猫头猫}
191a27adc20S猫头猫
192a27adc20S猫头猫const configableColorKey: Array<keyof CustomizedColors> = [
193277c5280S猫头猫    'primary',
194f643c584S猫头猫    'text',
195277c5280S猫头猫    'appBar',
196277c5280S猫头猫    'appBarText',
197277c5280S猫头猫    'musicBar',
198277c5280S猫头猫    'musicBarText',
199277c5280S猫头猫    'pageBackground',
200277c5280S猫头猫    'backdrop',
201277c5280S猫头猫    'card',
202277c5280S猫头猫    'placeholder',
203a27adc20S猫头猫];
204a27adc20S猫头猫
205a27adc20S猫头猫const colorDesc: Record<string, string> = {
206a27adc20S猫头猫    text: '文字颜色',
207a27adc20S猫头猫    primary: '主题色',
208277c5280S猫头猫    appBar: '标题栏背景色',
209277c5280S猫头猫    appBarText: '标题栏文字颜色',
210277c5280S猫头猫    musicBar: '音乐栏背景色',
211277c5280S猫头猫    musicBarText: '音乐栏文字颜色',
212277c5280S猫头猫    pageBackground: '页面背景色',
213277c5280S猫头猫    backdrop: '弹窗、浮层背景色',
214277c5280S猫头猫    card: '卡片背景色',
215277c5280S猫头猫    placeholder: '输入框背景色',
216a27adc20S猫头猫};
217a27adc20S猫头猫
218a27adc20S猫头猫const Theme = {
219a27adc20S猫头猫    setup,
220a27adc20S猫头猫    setTheme,
221a27adc20S猫头猫    setBackground,
222a27adc20S猫头猫    setColors,
223a27adc20S猫头猫    useTheme: themeStore.useValue,
224fdcf4127S猫头猫    getTheme: themeStore.getValue,
225a27adc20S猫头猫    useBackground: backgroundStore.useValue,
226a27adc20S猫头猫    configableColorKey,
227a27adc20S猫头猫    colorDesc,
228a27adc20S猫头猫};
229a27adc20S猫头猫
230a27adc20S猫头猫export default Theme;
231