xref: /MusicFree/src/entry/bootstrap.ts (revision 5589cdf32b2bb0f641e5ac7bf1f6152cd6b9b70e)
1e14deecfS猫头猫import MusicSheet from '@/core/musicSheet';
2bf6e62f2S猫头猫import {check, PERMISSIONS, request} from 'react-native-permissions';
35500cea7S猫头猫import RNTrackPlayer, {
45500cea7S猫头猫    AppKilledPlaybackBehavior,
55500cea7S猫头猫    Capability,
65500cea7S猫头猫} from 'react-native-track-player';
7bf6e62f2S猫头猫import 'react-native-get-random-values';
8e22d5e4fS猫头猫import Config from '@/core/config';
96780f402S猫头猫import pathConst from '@/constants/pathConst';
10be0a3650S猫头猫import {checkAndCreateDir} from '@/utils/fileUtils';
111e263108S猫头猫import {errorLog, trace} from '@/utils/log';
1243eb30bfS猫头猫import MediaMeta from '@/core/mediaMeta.old';
13927dbe93S猫头猫import PluginManager from '@/core/pluginManager';
14ef714860S猫头猫import Network from '@/core/network';
15c30d30e1S猫头猫import {ImgAsset} from '@/constants/assetsConst';
160e4173cdS猫头猫import LocalMusicSheet from '@/core/localMusicSheet';
179c72192fS猫头猫import {Linking} from 'react-native';
18a27adc20S猫头猫import Theme from '@/core/theme';
1957277364S猫头猫import LyricManager from '@/core/lyricManager';
20a84a85c5S猫头猫import Toast from '@/utils/toast';
21a84a85c5S猫头猫import {localPluginHash, supportLocalMediaType} from '@/constants/commonConst';
225500cea7S猫头猫import TrackPlayer from '@/core/trackPlayer';
235500cea7S猫头猫import musicHistory from '@/core/musicHistory';
240dd58d38S猫头猫import PersistStatus from '@/core/persistStatus';
2591eb8fa8S猫头猫import {perfLogger} from '@/utils/perfLogger';
26*5589cdf3S猫头猫import * as SplashScreen from 'expo-splash-screen';
27bf6e62f2S猫头猫
288b88e961S猫头猫/** app加载前执行
298b88e961S猫头猫 * 1. 检查权限
308b88e961S猫头猫 * 2. 数据初始化
318b88e961S猫头猫 * 3.
328b88e961S猫头猫 */
3391eb8fa8S猫头猫
3494a1b1fcS猫头猫async function _bootstrap() {
35*5589cdf3S猫头猫    await SplashScreen.preventAutoHideAsync()
36*5589cdf3S猫头猫        .then(result =>
37*5589cdf3S猫头猫            console.log(
38*5589cdf3S猫头猫                `SplashScreen.preventAutoHideAsync() succeeded: ${result}`,
39*5589cdf3S猫头猫            ),
40*5589cdf3S猫头猫        )
41*5589cdf3S猫头猫        .catch(console.warn); // it's good to explicitly catch and inspect any error
4291eb8fa8S猫头猫    const logger = perfLogger();
43927dbe93S猫头猫    // 1. 检查权限
44bf6e62f2S猫头猫    const [readStoragePermission, writeStoragePermission] = await Promise.all([
45bf6e62f2S猫头猫        check(PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE),
46bf6e62f2S猫头猫        check(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE),
47bf6e62f2S猫头猫    ]);
48bf6e62f2S猫头猫    if (
49bf6e62f2S猫头猫        !(
50bf6e62f2S猫头猫            readStoragePermission === 'granted' &&
51bf6e62f2S猫头猫            writeStoragePermission === 'granted'
52bf6e62f2S猫头猫        )
53bf6e62f2S猫头猫    ) {
54bf6e62f2S猫头猫        await request(PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE);
55bf6e62f2S猫头猫        await request(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE);
56bf6e62f2S猫头猫    }
5791eb8fa8S猫头猫    logger.mark('权限检查完成');
58bf6e62f2S猫头猫
59927dbe93S猫头猫    // 2. 数据初始化
606780f402S猫头猫    /** 初始化路径 */
616780f402S猫头猫    await setupFolder();
621e263108S猫头猫    trace('文件夹初始化完成');
6391eb8fa8S猫头猫    logger.mark('文件夹初始化完成');
6491eb8fa8S猫头猫
65bf6e62f2S猫头猫    // 加载配置
66ef714860S猫头猫    await Promise.all([
6791eb8fa8S猫头猫        Config.setup().then(() => {
6891eb8fa8S猫头猫            logger.mark('Config');
6991eb8fa8S猫头猫        }),
7091eb8fa8S猫头猫        MediaMeta.setup().then(() => {
7191eb8fa8S猫头猫            logger.mark('MediaMeta');
7291eb8fa8S猫头猫        }),
7391eb8fa8S猫头猫        MusicSheet.setup().then(() => {
7491eb8fa8S猫头猫            logger.mark('MusicSheet');
7591eb8fa8S猫头猫        }),
7691eb8fa8S猫头猫        musicHistory.setupMusicHistory().then(() => {
7791eb8fa8S猫头猫            logger.mark('musicHistory');
7891eb8fa8S猫头猫        }),
79ef714860S猫头猫    ]);
801e263108S猫头猫    trace('配置初始化完成');
8191eb8fa8S猫头猫    logger.mark('配置初始化完成');
8291eb8fa8S猫头猫
83bf6e62f2S猫头猫    // 加载插件
8494a1b1fcS猫头猫    try {
855500cea7S猫头猫        await RNTrackPlayer.setupPlayer({
86b882a19dS猫头猫            maxCacheSize:
87b882a19dS猫头猫                Config.get('setting.basic.maxCacheSize') ?? 1024 * 1024 * 512,
88cfa0fc07S猫头猫        });
8994a1b1fcS猫头猫    } catch (e: any) {
9094a1b1fcS猫头猫        if (
914060c00aS猫头猫            e?.message !==
924060c00aS猫头猫            'The player has already been initialized via setupPlayer.'
9394a1b1fcS猫头猫        ) {
9494a1b1fcS猫头猫            throw e;
9594a1b1fcS猫头猫        }
9694a1b1fcS猫头猫    }
9791eb8fa8S猫头猫    logger.mark('加载播放器');
9866e1d5fcS猫头猫
9966e1d5fcS猫头猫    const capabilities = Config.get('setting.basic.showExitOnNotification')
10066e1d5fcS猫头猫        ? [
10166e1d5fcS猫头猫              Capability.Play,
10266e1d5fcS猫头猫              Capability.Pause,
10366e1d5fcS猫头猫              Capability.SkipToNext,
10466e1d5fcS猫头猫              Capability.SkipToPrevious,
10566e1d5fcS猫头猫              Capability.Stop,
10666e1d5fcS猫头猫          ]
10766e1d5fcS猫头猫        : [
10866e1d5fcS猫头猫              Capability.Play,
10966e1d5fcS猫头猫              Capability.Pause,
11066e1d5fcS猫头猫              Capability.SkipToNext,
11166e1d5fcS猫头猫              Capability.SkipToPrevious,
11266e1d5fcS猫头猫          ];
1135500cea7S猫头猫    await RNTrackPlayer.updateOptions({
1142aa88193S猫头猫        icon: ImgAsset.logoTransparent,
115e2257bd6S猫头猫        progressUpdateEventInterval: 1,
1165500cea7S猫头猫        android: {
1175500cea7S猫头猫            alwaysPauseOnInterruption: true,
1185500cea7S猫头猫            appKilledPlaybackBehavior:
1195500cea7S猫头猫                AppKilledPlaybackBehavior.ContinuePlayback,
1205500cea7S猫头猫        },
12166e1d5fcS猫头猫        capabilities: capabilities,
12266e1d5fcS猫头猫        compactCapabilities: capabilities,
12366e1d5fcS猫头猫        notificationCapabilities: [...capabilities, Capability.SeekTo],
1240d39db21S猫头猫    });
12591eb8fa8S猫头猫    logger.mark('播放器初始化完成');
1261e263108S猫头猫    trace('播放器初始化完成');
12791eb8fa8S猫头猫
1288b88e961S猫头猫    await PluginManager.setup();
12991eb8fa8S猫头猫    logger.mark('插件初始化完成');
13091eb8fa8S猫头猫
1311e263108S猫头猫    trace('插件初始化完成');
1325500cea7S猫头猫    await TrackPlayer.setupTrackPlayer();
1331e263108S猫头猫    trace('播放列表初始化完成');
13491eb8fa8S猫头猫    logger.mark('播放列表初始化完成');
13591eb8fa8S猫头猫
1360e4173cdS猫头猫    await LocalMusicSheet.setup();
1370e4173cdS猫头猫    trace('本地音乐初始化完成');
13891eb8fa8S猫头猫    logger.mark('本地音乐初始化完成');
13991eb8fa8S猫头猫
140a27adc20S猫头猫    Theme.setup();
141a27adc20S猫头猫    trace('主题初始化完成');
14291eb8fa8S猫头猫    logger.mark('主题初始化完成');
14391eb8fa8S猫头猫
14457277364S猫头猫    await LyricManager.setup();
1458b88e961S猫头猫
14691eb8fa8S猫头猫    logger.mark('歌词初始化完成');
14791eb8fa8S猫头猫
148b3a3a048S猫头猫    extraMakeup();
149c79c8a57S猫头猫    ErrorUtils.setGlobalHandler(error => {
150c79c8a57S猫头猫        errorLog('未捕获的错误', error);
151c79c8a57S猫头猫    });
152bf6e62f2S猫头猫}
1536c6f45bdS猫头猫
1546c6f45bdS猫头猫/** 初始化 */
1556c6f45bdS猫头猫async function setupFolder() {
1566780f402S猫头猫    await Promise.all([
157be0a3650S猫头猫        checkAndCreateDir(pathConst.dataPath),
1587f771613S猫头猫        checkAndCreateDir(pathConst.logPath),
1597f771613S猫头猫        checkAndCreateDir(pathConst.cachePath),
160c79c8a57S猫头猫        checkAndCreateDir(pathConst.pluginPath),
16194a1b1fcS猫头猫        checkAndCreateDir(pathConst.lrcCachePath),
1620e4173cdS猫头猫        checkAndCreateDir(pathConst.downloadPath).then(() => {
1630e4173cdS猫头猫            checkAndCreateDir(pathConst.downloadMusicPath);
1640e4173cdS猫头猫        }),
1656780f402S猫头猫    ]);
1666c6f45bdS猫头猫}
16794a1b1fcS猫头猫
16894a1b1fcS猫头猫export default async function () {
16994a1b1fcS猫头猫    try {
17094a1b1fcS猫头猫        await _bootstrap();
17194a1b1fcS猫头猫    } catch (e) {
17294a1b1fcS猫头猫        errorLog('初始化出错', e);
17394a1b1fcS猫头猫    }
17494a1b1fcS猫头猫    // 隐藏开屏动画
17594a1b1fcS猫头猫    console.log('HIDE');
176*5589cdf3S猫头猫    await SplashScreen.hideAsync();
177*5589cdf3S猫头猫    // RNBootSplash.hide({fade: true});
17894a1b1fcS猫头猫}
179b3a3a048S猫头猫
180b3a3a048S猫头猫/** 不需要阻塞的 */
181b3a3a048S猫头猫async function extraMakeup() {
182a84a85c5S猫头猫    // 自动更新
183b3a3a048S猫头猫    try {
18491eb8fa8S猫头猫        // 初始化网络状态
18591eb8fa8S猫头猫        Network.setup();
18691eb8fa8S猫头猫
187b3a3a048S猫头猫        if (Config.get('setting.basic.autoUpdatePlugin')) {
1880dd58d38S猫头猫            const lastUpdated = PersistStatus.get('app.pluginUpdateTime') || 0;
189b3a3a048S猫头猫            const now = Date.now();
190b3a3a048S猫头猫            if (Math.abs(now - lastUpdated) > 86400000) {
1910dd58d38S猫头猫                PersistStatus.set('app.pluginUpdateTime', now);
192b3a3a048S猫头猫                const plugins = PluginManager.getValidPlugins();
193b3a3a048S猫头猫                for (let i = 0; i < plugins.length; ++i) {
194b3a3a048S猫头猫                    const srcUrl = plugins[i].instance.srcUrl;
195b3a3a048S猫头猫                    if (srcUrl) {
196b3a3a048S猫头猫                        await PluginManager.installPluginFromUrl(srcUrl);
197b3a3a048S猫头猫                    }
198b3a3a048S猫头猫                }
199b3a3a048S猫头猫            }
200b3a3a048S猫头猫        }
201b3a3a048S猫头猫    } catch {}
202a84a85c5S猫头猫
203a84a85c5S猫头猫    async function handleLinkingUrl(url: string) {
204a84a85c5S猫头猫        // 插件
205a84a85c5S猫头猫        try {
206eea2f34fS猫头猫            if (url.startsWith('musicfree://install/')) {
207eea2f34fS猫头猫                const plugins = url
208eea2f34fS猫头猫                    .slice(20)
209eea2f34fS猫头猫                    .split(',')
210eea2f34fS猫头猫                    .map(decodeURIComponent);
211eea2f34fS猫头猫                await Promise.all(
212eea2f34fS猫头猫                    plugins.map(it =>
213eea2f34fS猫头猫                        PluginManager.installPluginFromUrl(it).catch(() => {}),
214eea2f34fS猫头猫                    ),
215eea2f34fS猫头猫                );
216eea2f34fS猫头猫                Toast.success('安装成功~');
217eea2f34fS猫头猫            } else if (url.endsWith('.js')) {
218e36e2599S猫头猫                PluginManager.installPlugin(url, {
219e36e2599S猫头猫                    notCheckVersion: Config.get(
220e36e2599S猫头猫                        'setting.basic.notCheckPluginVersion',
221e36e2599S猫头猫                    ),
222e36e2599S猫头猫                })
223a84a85c5S猫头猫                    .then(res => {
224a84a85c5S猫头猫                        Toast.success(`插件「${res.name}」安装成功~`);
225a84a85c5S猫头猫                    })
226a84a85c5S猫头猫                    .catch(e => {
227a84a85c5S猫头猫                        console.log(e);
228a84a85c5S猫头猫                        Toast.warn(e?.message ?? '无法识别此插件');
229a84a85c5S猫头猫                    });
230a84a85c5S猫头猫            } else if (supportLocalMediaType.some(it => url.endsWith(it))) {
231a84a85c5S猫头猫                // 本地播放
232a84a85c5S猫头猫                const musicItem = await PluginManager.getByHash(
233a84a85c5S猫头猫                    localPluginHash,
234a84a85c5S猫头猫                )?.instance?.importMusicItem?.(url);
235a84a85c5S猫头猫                console.log(musicItem);
236a84a85c5S猫头猫                if (musicItem) {
2375500cea7S猫头猫                    TrackPlayer.play(musicItem);
238a84a85c5S猫头猫                }
239a84a85c5S猫头猫            }
240a84a85c5S猫头猫        } catch {}
241a84a85c5S猫头猫    }
242a84a85c5S猫头猫
243a84a85c5S猫头猫    // 开启监听
244a84a85c5S猫头猫    Linking.addEventListener('url', data => {
245a84a85c5S猫头猫        if (data.url) {
246a84a85c5S猫头猫            handleLinkingUrl(data.url);
247a84a85c5S猫头猫        }
248a84a85c5S猫头猫    });
249a84a85c5S猫头猫    const initUrl = await Linking.getInitialURL();
250a84a85c5S猫头猫    if (initUrl) {
251a84a85c5S猫头猫        handleLinkingUrl(initUrl);
252a84a85c5S猫头猫    }
253aaa0db32S猫头猫
254aaa0db32S猫头猫    if (Config.get('setting.basic.autoPlayWhenAppStart')) {
2555500cea7S猫头猫        TrackPlayer.play();
256aaa0db32S猫头猫    }
257b3a3a048S猫头猫}
258