xref: /MusicFree/src/entry/bootstrap.ts (revision b3a3a048036932fa4574c45563c1cac326b1d628)
1import MusicQueue from '@/core/musicQueue';
2import MusicSheet from '@/core/musicSheet';
3import {check, PERMISSIONS, request} from 'react-native-permissions';
4import TrackPlayer, {Capability} from 'react-native-track-player';
5import 'react-native-get-random-values';
6import Config from '@/core/config';
7import RNBootSplash from 'react-native-bootsplash';
8import pathConst from '@/constants/pathConst';
9import {checkAndCreateDir} from '@/utils/fileUtils';
10import {errorLog, trace} from '@/utils/log';
11import MediaMeta from '@/core/mediaMeta';
12import Cache from '@/core/cache';
13import PluginManager from '@/core/pluginManager';
14import Network from '@/core/network';
15import {ImgAsset} from '@/constants/assetsConst';
16import LocalMusicSheet from '@/core/localMusicSheet';
17import {StatusBar} from 'react-native';
18import Theme from '@/core/theme';
19import LyricManager from '@/core/lyricManager';
20import {getStorage, setStorage} from '@/utils/storage';
21
22/** app加载前执行
23 * 1. 检查权限
24 * 2. 数据初始化
25 * 3.
26 */
27async function _bootstrap() {
28    // 1. 检查权限
29    const [readStoragePermission, writeStoragePermission] = await Promise.all([
30        check(PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE),
31        check(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE),
32    ]);
33    if (
34        !(
35            readStoragePermission === 'granted' &&
36            writeStoragePermission === 'granted'
37        )
38    ) {
39        await request(PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE);
40        await request(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE);
41    }
42
43    // 2. 数据初始化
44    /** 初始化路径 */
45    await setupFolder();
46    trace('文件夹初始化完成');
47    // 加载配置
48    await Promise.all([
49        Config.setup(),
50        MediaMeta.setup(),
51        MusicSheet.setup(),
52        Network.setup(),
53    ]);
54    trace('配置初始化完成');
55    // 加载插件
56    try {
57        await TrackPlayer.setupPlayer({
58            maxCacheSize:
59                Config.get('setting.basic.maxCacheSize') ?? 1024 * 1024 * 512,
60        });
61    } catch (e: any) {
62        if (
63            e?.message !==
64            'The player has already been initialized via setupPlayer.'
65        ) {
66            throw e;
67        }
68    }
69    await TrackPlayer.updateOptions({
70        icon: ImgAsset.logoTransparent,
71        alwaysPauseOnInterruption: true,
72        progressUpdateEventInterval: 1,
73        capabilities: [
74            Capability.Play,
75            Capability.Pause,
76            Capability.SkipToNext,
77            Capability.SkipToPrevious,
78        ],
79        compactCapabilities: [
80            Capability.Play,
81            Capability.Pause,
82            Capability.SkipToNext,
83            Capability.SkipToPrevious,
84        ],
85        notificationCapabilities: [
86            Capability.Play,
87            Capability.Pause,
88            Capability.SkipToNext,
89            Capability.SkipToPrevious,
90        ],
91    });
92    trace('播放器初始化完成');
93    await Cache.setup();
94    trace('缓存初始化完成');
95    await PluginManager.setup();
96    trace('插件初始化完成');
97    await MusicQueue.setup();
98    trace('播放列表初始化完成');
99    await LocalMusicSheet.setup();
100    trace('本地音乐初始化完成');
101    Theme.setup();
102    trace('主题初始化完成');
103    await LyricManager.setup();
104
105    StatusBar.setBackgroundColor('transparent');
106    StatusBar.setTranslucent(true);
107    // Linking.addEventListener('url', (data) => {
108    //     console.log(data);
109    // })
110
111    extraMakeup();
112    ErrorUtils.setGlobalHandler(error => {
113        errorLog('未捕获的错误', error);
114    });
115}
116
117/** 初始化 */
118async function setupFolder() {
119    await Promise.all([
120        checkAndCreateDir(pathConst.dataPath),
121        checkAndCreateDir(pathConst.logPath),
122        checkAndCreateDir(pathConst.cachePath),
123        checkAndCreateDir(pathConst.pluginPath),
124        checkAndCreateDir(pathConst.lrcCachePath),
125        checkAndCreateDir(pathConst.downloadPath).then(() => {
126            checkAndCreateDir(pathConst.downloadMusicPath);
127        }),
128    ]);
129}
130
131export default async function () {
132    try {
133        await _bootstrap();
134    } catch (e) {
135        errorLog('初始化出错', e);
136    }
137    // 隐藏开屏动画
138    console.log('HIDE');
139    RNBootSplash.hide({fade: true});
140}
141
142/** 不需要阻塞的 */
143async function extraMakeup() {
144    try {
145        if (Config.get('setting.basic.autoUpdatePlugin')) {
146            const lastUpdated =
147                (await getStorage('pluginLastupdatedTime')) || 0;
148            const now = Date.now();
149            if (Math.abs(now - lastUpdated) > 86400000) {
150                setStorage('pluginLastupdatedTime', now);
151                const plugins = PluginManager.getValidPlugins();
152                for (let i = 0; i < plugins.length; ++i) {
153                    const srcUrl = plugins[i].instance.srcUrl;
154                    if (srcUrl) {
155                        await PluginManager.installPluginFromUrl(srcUrl);
156                    }
157                }
158            }
159        }
160    } catch {}
161}
162