xref: /MusicFree/src/core/config.ts (revision 41ddce918e1138d8f16e522cc7c19ac86ceca698)
1819a9075Smaotoumaoimport { CustomizedColors } from "@/hooks/useColors";
2*41ddce91Smaotoumaoimport { getStorage, removeStorage } from "@/utils/storage";
3819a9075Smaotoumaoimport { ResumeMode, SortType } from "@/constants/commonConst.ts";
4*41ddce91Smaotoumaoimport getOrCreateMMKV from "@/utils/getOrCreateMMKV.ts";
5*41ddce91Smaotoumaoimport safeStringify from "@/utils/safeStringify.ts";
6*41ddce91Smaotoumaoimport { useMMKVObject } from "react-native-mmkv";
7e22d5e4fS猫头猫
8*41ddce91Smaotoumao
9*41ddce91Smaotoumaoconst configStore = getOrCreateMMKV('App.config');
10*41ddce91Smaotoumao
11*41ddce91Smaotoumao// 新版本配置类型(扁平化结构)
12e22d5e4fS猫头猫interface IConfig {
13*41ddce91Smaotoumao    "$schema": "1";
14*41ddce91Smaotoumao    // Basic
15*41ddce91Smaotoumao    "basic.autoPlayWhenAppStart": boolean;
16*41ddce91Smaotoumao    "basic.useCelluarNetworkPlay": boolean;
17*41ddce91Smaotoumao    "basic.useCelluarNetworkDownload": boolean;
18*41ddce91Smaotoumao    "basic.maxDownload": number | string;
19*41ddce91Smaotoumao    "basic.clickMusicInSearch": '播放歌曲' | '播放歌曲并替换播放列表';
20*41ddce91Smaotoumao    "basic.clickMusicInAlbum": '播放专辑' | '播放单曲';
21*41ddce91Smaotoumao    "basic.downloadPath": string;
22*41ddce91Smaotoumao    "basic.notInterrupt": boolean;
23*41ddce91Smaotoumao    "basic.tempRemoteDuck": '暂停' | '降低音量';
24*41ddce91Smaotoumao    "basic.autoStopWhenError": boolean;
25*41ddce91Smaotoumao    "basic.pluginCacheControl": string;
26*41ddce91Smaotoumao    "basic.maxCacheSize": number;
27*41ddce91Smaotoumao    "basic.defaultPlayQuality": IMusic.IQualityKey;
28*41ddce91Smaotoumao    "basic.playQualityOrder": 'asc' | 'desc';
29*41ddce91Smaotoumao    "basic.defaultDownloadQuality": IMusic.IQualityKey;
30*41ddce91Smaotoumao    "basic.downloadQualityOrder": 'asc' | 'desc';
31*41ddce91Smaotoumao    "basic.musicDetailDefault": 'album' | 'lyric';
32*41ddce91Smaotoumao    "basic.musicDetailAwake": boolean;
33*41ddce91Smaotoumao    "basic.maxHistoryLen": number;
34*41ddce91Smaotoumao    "basic.autoUpdatePlugin": boolean;
35*41ddce91Smaotoumao    "basic.notCheckPluginVersion": boolean;
36*41ddce91Smaotoumao    "basic.associateLyricType": 'input' | 'search';
37*41ddce91Smaotoumao    "basic.showExitOnNotification": boolean;
38*41ddce91Smaotoumao    "basic.musicOrderInLocalSheet": SortType;
39*41ddce91Smaotoumao    "basic.tryChangeSourceWhenPlayFail": boolean;
40e22d5e4fS猫头猫
41*41ddce91Smaotoumao    // Lyric
42*41ddce91Smaotoumao    "lyric.showStatusBarLyric": boolean;
43*41ddce91Smaotoumao    "lyric.topPercent": number;
44*41ddce91Smaotoumao    "lyric.leftPercent": number;
45*41ddce91Smaotoumao    "lyric.align": number;
46*41ddce91Smaotoumao    "lyric.color": string;
47*41ddce91Smaotoumao    "lyric.backgroundColor": string;
48*41ddce91Smaotoumao    "lyric.widthPercent": number;
49*41ddce91Smaotoumao    "lyric.fontSize": number;
50*41ddce91Smaotoumao    "lyric.detailFontSize": number;
51*41ddce91Smaotoumao    "lyric.autoSearchLyric": boolean;
528b7ddca8S猫头猫
53*41ddce91Smaotoumao    // Theme
54*41ddce91Smaotoumao    "theme.background": string;
55*41ddce91Smaotoumao    "theme.backgroundOpacity": number;
56*41ddce91Smaotoumao    "theme.backgroundBlur": number;
57*41ddce91Smaotoumao    "theme.colors": CustomizedColors;
58*41ddce91Smaotoumao    "theme.customColors"?: CustomizedColors;
59*41ddce91Smaotoumao    "theme.followSystem": boolean;
60*41ddce91Smaotoumao    "theme.selectedTheme": string;
61a7b42a4cS猫头猫
62*41ddce91Smaotoumao    // Backup
63*41ddce91Smaotoumao    "backup.resumeMode": ResumeMode;
64*41ddce91Smaotoumao
65*41ddce91Smaotoumao    // Plugin
66*41ddce91Smaotoumao    "plugin.subscribeUrl": string;
67*41ddce91Smaotoumao
68*41ddce91Smaotoumao    // WebDAV
69*41ddce91Smaotoumao    "webdav.url": string;
70*41ddce91Smaotoumao    "webdav.username": string;
71*41ddce91Smaotoumao    "webdav.password": string;
72*41ddce91Smaotoumao
73*41ddce91Smaotoumao    // Debug(保持嵌套结构)
74*41ddce91Smaotoumao    "debug.errorLog": boolean;
75*41ddce91Smaotoumao    "debug.traceLog": boolean;
76*41ddce91Smaotoumao    "debug.devLog": boolean;
77e22d5e4fS猫头猫}
78e22d5e4fS猫头猫
79e22d5e4fS猫头猫
80*41ddce91Smaotoumaoexport type ConfigKey = keyof IConfig;
81e22d5e4fS猫头猫
82*41ddce91Smaotoumao// 迁移函数
83*41ddce91Smaotoumaoasync function migrateConfig(): Promise<void> {
84*41ddce91Smaotoumao    // 检查是否已经迁移
85*41ddce91Smaotoumao    if (configStore.contains('$schema')) {
86e22d5e4fS猫头猫        return;
87e22d5e4fS猫头猫    }
88e22d5e4fS猫头猫
89*41ddce91Smaotoumao    // 获取旧配置
90*41ddce91Smaotoumao    const oldConfig = await getStorage('local-config');
91e22d5e4fS猫头猫
92*41ddce91Smaotoumao    // 如果没有旧配置,直接初始化新配置
93*41ddce91Smaotoumao    if (!oldConfig) {
94*41ddce91Smaotoumao        configStore.set('$schema', '1');
95*41ddce91Smaotoumao        return;
96e22d5e4fS猫头猫    }
97e22d5e4fS猫头猫
98*41ddce91Smaotoumao    // 迁移每个字段
99*41ddce91Smaotoumao    const mapping: [string, ConfigKey][] = [
100*41ddce91Smaotoumao        // Basic
101*41ddce91Smaotoumao        ['setting.basic.autoPlayWhenAppStart', 'basic.autoPlayWhenAppStart'],
102*41ddce91Smaotoumao        ['setting.basic.useCelluarNetworkPlay', 'basic.useCelluarNetworkPlay'],
103*41ddce91Smaotoumao        ['setting.basic.useCelluarNetworkDownload', 'basic.useCelluarNetworkDownload'],
104*41ddce91Smaotoumao        ['setting.basic.maxDownload', 'basic.maxDownload'],
105*41ddce91Smaotoumao        ['setting.basic.clickMusicInSearch', 'basic.clickMusicInSearch'],
106*41ddce91Smaotoumao        ['setting.basic.clickMusicInAlbum', 'basic.clickMusicInAlbum'],
107*41ddce91Smaotoumao        ['setting.basic.downloadPath', 'basic.downloadPath'],
108*41ddce91Smaotoumao        ['setting.basic.notInterrupt', 'basic.notInterrupt'],
109*41ddce91Smaotoumao        ['setting.basic.tempRemoteDuck', 'basic.tempRemoteDuck'],
110*41ddce91Smaotoumao        ['setting.basic.autoStopWhenError', 'basic.autoStopWhenError'],
111*41ddce91Smaotoumao        ['setting.basic.pluginCacheControl', 'basic.pluginCacheControl'],
112*41ddce91Smaotoumao        ['setting.basic.maxCacheSize', 'basic.maxCacheSize'],
113*41ddce91Smaotoumao        ['setting.basic.defaultPlayQuality', 'basic.defaultPlayQuality'],
114*41ddce91Smaotoumao        ['setting.basic.playQualityOrder', 'basic.playQualityOrder'],
115*41ddce91Smaotoumao        ['setting.basic.defaultDownloadQuality', 'basic.defaultDownloadQuality'],
116*41ddce91Smaotoumao        ['setting.basic.downloadQualityOrder', 'basic.downloadQualityOrder'],
117*41ddce91Smaotoumao        ['setting.basic.musicDetailDefault', 'basic.musicDetailDefault'],
118*41ddce91Smaotoumao        ['setting.basic.musicDetailAwake', 'basic.musicDetailAwake'],
119*41ddce91Smaotoumao        ['setting.basic.debug.errorLog', 'debug.errorLog'],
120*41ddce91Smaotoumao        ['setting.basic.debug.traceLog', 'debug.traceLog'],
121*41ddce91Smaotoumao        ['setting.basic.debug.devLog', 'debug.devLog'],
122*41ddce91Smaotoumao        ['setting.basic.maxHistoryLen', 'basic.maxHistoryLen'],
123*41ddce91Smaotoumao        ['setting.basic.autoUpdatePlugin', 'basic.autoUpdatePlugin'],
124*41ddce91Smaotoumao        ['setting.basic.notCheckPluginVersion', 'basic.notCheckPluginVersion'],
125*41ddce91Smaotoumao        ['setting.basic.associateLyricType', 'basic.associateLyricType'],
126*41ddce91Smaotoumao        ['setting.basic.showExitOnNotification', 'basic.showExitOnNotification'],
127*41ddce91Smaotoumao        ['setting.basic.musicOrderInLocalSheet', 'basic.musicOrderInLocalSheet'],
128*41ddce91Smaotoumao        ['setting.basic.tryChangeSourceWhenPlayFail', 'basic.tryChangeSourceWhenPlayFail'],
129e22d5e4fS猫头猫
130*41ddce91Smaotoumao        // Lyric
131*41ddce91Smaotoumao        ['setting.lyric.showStatusBarLyric', 'lyric.showStatusBarLyric'],
132*41ddce91Smaotoumao        ['setting.lyric.topPercent', 'lyric.topPercent'],
133*41ddce91Smaotoumao        ['setting.lyric.leftPercent', 'lyric.leftPercent'],
134*41ddce91Smaotoumao        ['setting.lyric.align', 'lyric.align'],
135*41ddce91Smaotoumao        ['setting.lyric.color', 'lyric.color'],
136*41ddce91Smaotoumao        ['setting.lyric.backgroundColor', 'lyric.backgroundColor'],
137*41ddce91Smaotoumao        ['setting.lyric.widthPercent', 'lyric.widthPercent'],
138*41ddce91Smaotoumao        ['setting.lyric.fontSize', 'lyric.fontSize'],
139*41ddce91Smaotoumao        ['setting.lyric.detailFontSize', 'lyric.detailFontSize'],
140*41ddce91Smaotoumao        ['setting.lyric.autoSearchLyric', 'lyric.autoSearchLyric'],
141e22d5e4fS猫头猫
142*41ddce91Smaotoumao        // Theme
143*41ddce91Smaotoumao        ['setting.theme.background', 'theme.background'],
144*41ddce91Smaotoumao        ['setting.theme.backgroundOpacity', 'theme.backgroundOpacity'],
145*41ddce91Smaotoumao        ['setting.theme.backgroundBlur', 'theme.backgroundBlur'],
146*41ddce91Smaotoumao        ['setting.theme.colors', 'theme.colors'],
147*41ddce91Smaotoumao        ['setting.theme.customColors', 'theme.customColors'],
148*41ddce91Smaotoumao        ['setting.theme.followSystem', 'theme.followSystem'],
149*41ddce91Smaotoumao        ['setting.theme.selectedTheme', 'theme.selectedTheme'],
150*41ddce91Smaotoumao
151*41ddce91Smaotoumao        // Backup
152*41ddce91Smaotoumao        ['setting.backup.resumeMode', 'backup.resumeMode'],
153*41ddce91Smaotoumao
154*41ddce91Smaotoumao        // Plugin
155*41ddce91Smaotoumao        ['setting.plugin.subscribeUrl', 'plugin.subscribeUrl'],
156*41ddce91Smaotoumao
157*41ddce91Smaotoumao        // WebDAV
158*41ddce91Smaotoumao        ['setting.webdav.url', 'webdav.url'],
159*41ddce91Smaotoumao        ['setting.webdav.username', 'webdav.username'],
160*41ddce91Smaotoumao        ['setting.webdav.password', 'webdav.password'],
161*41ddce91Smaotoumao    ];
162*41ddce91Smaotoumao
163*41ddce91Smaotoumao    // 执行迁移
164e22d5e4fS猫头猫    function getPathValue(obj: Record<string, any>, path: string) {
165e22d5e4fS猫头猫        const keys = path.split('.');
166e22d5e4fS猫头猫        let tmp = obj;
167e22d5e4fS猫头猫        for (let i = 0; i < keys.length; ++i) {
168e22d5e4fS猫头猫            tmp = tmp?.[keys[i]];
169e22d5e4fS猫头猫        }
170e22d5e4fS猫头猫        return tmp;
171e22d5e4fS猫头猫    }
172e22d5e4fS猫头猫
173*41ddce91Smaotoumao    mapping.forEach(([oldPath, newKey]) => {
174*41ddce91Smaotoumao        const value = getPathValue(oldConfig, oldPath);
175*41ddce91Smaotoumao        if (value !== undefined) {
176*41ddce91Smaotoumao            configStore.set(newKey, safeStringify(value));
177*41ddce91Smaotoumao        }
178*41ddce91Smaotoumao    });
179*41ddce91Smaotoumao
180*41ddce91Smaotoumao    // 设置版本标识
181*41ddce91Smaotoumao    configStore.set('$schema', '1');
182*41ddce91Smaotoumao
183*41ddce91Smaotoumao    // 清理旧配置
184*41ddce91Smaotoumao    await removeStorage('local-config'); // 根据需求决定是否删除旧配置
185e22d5e4fS猫头猫}
186e22d5e4fS猫头猫
187*41ddce91Smaotoumao/** 初始化config */
188*41ddce91Smaotoumaoasync function setup() {
189*41ddce91Smaotoumao    await migrateConfig();
190e22d5e4fS猫头猫}
191e22d5e4fS猫头猫
192*41ddce91Smaotoumaofunction setConfig<K extends ConfigKey>(key: K, value?: IConfig[K]) {
193*41ddce91Smaotoumao    if (value === undefined) {
194*41ddce91Smaotoumao        configStore.delete(key);
195e22d5e4fS猫头猫    } else {
196*41ddce91Smaotoumao        configStore.set(key, safeStringify(value));
197e22d5e4fS猫头猫    }
198e22d5e4fS猫头猫}
199e22d5e4fS猫头猫
200*41ddce91Smaotoumaofunction getConfig<K extends ConfigKey>(key: K): IConfig[K] | undefined {
201*41ddce91Smaotoumao    const value = configStore.getString(key);
202*41ddce91Smaotoumao    if (value === undefined) {
203*41ddce91Smaotoumao        return undefined;
204*41ddce91Smaotoumao    }
205*41ddce91Smaotoumao    return JSON.parse(value);
206*41ddce91Smaotoumao}
207*41ddce91Smaotoumao
208*41ddce91Smaotoumao
209*41ddce91Smaotoumaofunction useConfig<K extends ConfigKey>(key: K) {
210*41ddce91Smaotoumao    return useMMKVObject<IConfig[K]>(key, configStore);
211*41ddce91Smaotoumao}
212*41ddce91Smaotoumao
213*41ddce91Smaotoumaofunction useConfigValue<K extends ConfigKey>(key: K) {
214*41ddce91Smaotoumao    return useMMKVObject<IConfig[K]>(key, configStore)[0];
215*41ddce91Smaotoumao}
216*41ddce91Smaotoumao
217e22d5e4fS猫头猫const Config = {
2181f829e09S猫头猫    setup,
219*41ddce91Smaotoumao    setConfig,
220*41ddce91Smaotoumao    getConfig,
221*41ddce91Smaotoumao    useConfig,
222*41ddce91Smaotoumao    useConfigValue
223*41ddce91Smaotoumao}
224e22d5e4fS猫头猫
225e22d5e4fS猫头猫export default Config;
226