xref: /MusicFree/src/entry/bootstrap.ts (revision 42a9f3e6edf48cfb1acc40cd35cb6621e7f940e9)
1bf6e62f2S猫头猫import {check, PERMISSIONS, request} from 'react-native-permissions';
25500cea7S猫头猫import RNTrackPlayer, {
35500cea7S猫头猫    AppKilledPlaybackBehavior,
45500cea7S猫头猫    Capability,
55500cea7S猫头猫} from 'react-native-track-player';
6bf6e62f2S猫头猫import 'react-native-get-random-values';
7e22d5e4fS猫头猫import Config from '@/core/config';
86780f402S猫头猫import pathConst from '@/constants/pathConst';
9be0a3650S猫头猫import {checkAndCreateDir} from '@/utils/fileUtils';
101e263108S猫头猫import {errorLog, trace} from '@/utils/log';
1143eb30bfS猫头猫import MediaMeta from '@/core/mediaMeta.old';
12927dbe93S猫头猫import PluginManager from '@/core/pluginManager';
13ef714860S猫头猫import Network from '@/core/network';
14c30d30e1S猫头猫import {ImgAsset} from '@/constants/assetsConst';
150e4173cdS猫头猫import LocalMusicSheet from '@/core/localMusicSheet';
16740e3947S猫头猫import {Linking, Platform} from 'react-native';
17a27adc20S猫头猫import Theme from '@/core/theme';
1857277364S猫头猫import LyricManager from '@/core/lyricManager';
19a84a85c5S猫头猫import Toast from '@/utils/toast';
20a84a85c5S猫头猫import {localPluginHash, supportLocalMediaType} from '@/constants/commonConst';
215500cea7S猫头猫import TrackPlayer from '@/core/trackPlayer';
225500cea7S猫头猫import musicHistory from '@/core/musicHistory';
230dd58d38S猫头猫import PersistStatus from '@/core/persistStatus';
2491eb8fa8S猫头猫import {perfLogger} from '@/utils/perfLogger';
255589cdf3S猫头猫import * as SplashScreen from 'expo-splash-screen';
26740e3947S猫头猫import MusicSheet from '@/core/musicSheet';
27740e3947S猫头猫import NativeUtils from '@/native/utils';
28740e3947S猫头猫import {showDialog} from '@/components/dialogs/useDialog.ts';
29bf6e62f2S猫头猫
308b88e961S猫头猫/** app加载前执行
318b88e961S猫头猫 * 1. 检查权限
328b88e961S猫头猫 * 2. 数据初始化
338b88e961S猫头猫 * 3.
348b88e961S猫头猫 */
3591eb8fa8S猫头猫
3694a1b1fcS猫头猫async function _bootstrap() {
375589cdf3S猫头猫    await SplashScreen.preventAutoHideAsync()
385589cdf3S猫头猫        .then(result =>
395589cdf3S猫头猫            console.log(
405589cdf3S猫头猫                `SplashScreen.preventAutoHideAsync() succeeded: ${result}`,
415589cdf3S猫头猫            ),
425589cdf3S猫头猫        )
435589cdf3S猫头猫        .catch(console.warn); // it's good to explicitly catch and inspect any error
4491eb8fa8S猫头猫    const logger = perfLogger();
45927dbe93S猫头猫    // 1. 检查权限
46740e3947S猫头猫    if (Platform.OS === 'android' && Platform.Version >= 30) {
47740e3947S猫头猫        const hasPermission = await NativeUtils.checkStoragePermission();
48740e3947S猫头猫        if (
49740e3947S猫头猫            !hasPermission &&
50740e3947S猫头猫            !PersistStatus.get('app.skipBootstrapStorageDialog')
51740e3947S猫头猫        ) {
52740e3947S猫头猫            showDialog('CheckStorage');
53740e3947S猫头猫        }
54740e3947S猫头猫    } else {
55740e3947S猫头猫        const [readStoragePermission, writeStoragePermission] =
56740e3947S猫头猫            await Promise.all([
57bf6e62f2S猫头猫                check(PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE),
58bf6e62f2S猫头猫                check(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE),
59bf6e62f2S猫头猫            ]);
60bf6e62f2S猫头猫        if (
61bf6e62f2S猫头猫            !(
62bf6e62f2S猫头猫                readStoragePermission === 'granted' &&
63bf6e62f2S猫头猫                writeStoragePermission === 'granted'
64bf6e62f2S猫头猫            )
65bf6e62f2S猫头猫        ) {
66bf6e62f2S猫头猫            await request(PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE);
67bf6e62f2S猫头猫            await request(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE);
68bf6e62f2S猫头猫        }
69740e3947S猫头猫    }
7091eb8fa8S猫头猫    logger.mark('权限检查完成');
71bf6e62f2S猫头猫
72927dbe93S猫头猫    // 2. 数据初始化
736780f402S猫头猫    /** 初始化路径 */
746780f402S猫头猫    await setupFolder();
751e263108S猫头猫    trace('文件夹初始化完成');
7691eb8fa8S猫头猫    logger.mark('文件夹初始化完成');
7791eb8fa8S猫头猫
78bf6e62f2S猫头猫    // 加载配置
79ef714860S猫头猫    await Promise.all([
8091eb8fa8S猫头猫        Config.setup().then(() => {
8191eb8fa8S猫头猫            logger.mark('Config');
8291eb8fa8S猫头猫        }),
8391eb8fa8S猫头猫        MediaMeta.setup().then(() => {
8491eb8fa8S猫头猫            logger.mark('MediaMeta');
8591eb8fa8S猫头猫        }),
8691eb8fa8S猫头猫        MusicSheet.setup().then(() => {
8791eb8fa8S猫头猫            logger.mark('MusicSheet');
8891eb8fa8S猫头猫        }),
8991eb8fa8S猫头猫        musicHistory.setupMusicHistory().then(() => {
9091eb8fa8S猫头猫            logger.mark('musicHistory');
9191eb8fa8S猫头猫        }),
92ef714860S猫头猫    ]);
931e263108S猫头猫    trace('配置初始化完成');
9491eb8fa8S猫头猫    logger.mark('配置初始化完成');
9591eb8fa8S猫头猫
96bf6e62f2S猫头猫    // 加载插件
9794a1b1fcS猫头猫    try {
985500cea7S猫头猫        await RNTrackPlayer.setupPlayer({
99b882a19dS猫头猫            maxCacheSize:
100b882a19dS猫头猫                Config.get('setting.basic.maxCacheSize') ?? 1024 * 1024 * 512,
101cfa0fc07S猫头猫        });
10294a1b1fcS猫头猫    } catch (e: any) {
10394a1b1fcS猫头猫        if (
1044060c00aS猫头猫            e?.message !==
1054060c00aS猫头猫            'The player has already been initialized via setupPlayer.'
10694a1b1fcS猫头猫        ) {
10794a1b1fcS猫头猫            throw e;
10894a1b1fcS猫头猫        }
10994a1b1fcS猫头猫    }
11091eb8fa8S猫头猫    logger.mark('加载播放器');
11166e1d5fcS猫头猫
11266e1d5fcS猫头猫    const capabilities = Config.get('setting.basic.showExitOnNotification')
11366e1d5fcS猫头猫        ? [
11466e1d5fcS猫头猫              Capability.Play,
11566e1d5fcS猫头猫              Capability.Pause,
11666e1d5fcS猫头猫              Capability.SkipToNext,
11766e1d5fcS猫头猫              Capability.SkipToPrevious,
11866e1d5fcS猫头猫              Capability.Stop,
11966e1d5fcS猫头猫          ]
12066e1d5fcS猫头猫        : [
12166e1d5fcS猫头猫              Capability.Play,
12266e1d5fcS猫头猫              Capability.Pause,
12366e1d5fcS猫头猫              Capability.SkipToNext,
12466e1d5fcS猫头猫              Capability.SkipToPrevious,
12566e1d5fcS猫头猫          ];
1265500cea7S猫头猫    await RNTrackPlayer.updateOptions({
1272aa88193S猫头猫        icon: ImgAsset.logoTransparent,
128e2257bd6S猫头猫        progressUpdateEventInterval: 1,
1295500cea7S猫头猫        android: {
1305500cea7S猫头猫            alwaysPauseOnInterruption: true,
1315500cea7S猫头猫            appKilledPlaybackBehavior:
1325500cea7S猫头猫                AppKilledPlaybackBehavior.ContinuePlayback,
1335500cea7S猫头猫        },
13466e1d5fcS猫头猫        capabilities: capabilities,
13566e1d5fcS猫头猫        compactCapabilities: capabilities,
13666e1d5fcS猫头猫        notificationCapabilities: [...capabilities, Capability.SeekTo],
1370d39db21S猫头猫    });
13891eb8fa8S猫头猫    logger.mark('播放器初始化完成');
1391e263108S猫头猫    trace('播放器初始化完成');
14091eb8fa8S猫头猫
1418b88e961S猫头猫    await PluginManager.setup();
14291eb8fa8S猫头猫    logger.mark('插件初始化完成');
14391eb8fa8S猫头猫
1441e263108S猫头猫    trace('插件初始化完成');
1455500cea7S猫头猫    await TrackPlayer.setupTrackPlayer();
1461e263108S猫头猫    trace('播放列表初始化完成');
14791eb8fa8S猫头猫    logger.mark('播放列表初始化完成');
14891eb8fa8S猫头猫
1490e4173cdS猫头猫    await LocalMusicSheet.setup();
1500e4173cdS猫头猫    trace('本地音乐初始化完成');
15191eb8fa8S猫头猫    logger.mark('本地音乐初始化完成');
15291eb8fa8S猫头猫
153a27adc20S猫头猫    Theme.setup();
154a27adc20S猫头猫    trace('主题初始化完成');
15591eb8fa8S猫头猫    logger.mark('主题初始化完成');
15691eb8fa8S猫头猫
15757277364S猫头猫    await LyricManager.setup();
1588b88e961S猫头猫
15991eb8fa8S猫头猫    logger.mark('歌词初始化完成');
16091eb8fa8S猫头猫
161b3a3a048S猫头猫    extraMakeup();
162c79c8a57S猫头猫    ErrorUtils.setGlobalHandler(error => {
163c79c8a57S猫头猫        errorLog('未捕获的错误', error);
164c79c8a57S猫头猫    });
165bf6e62f2S猫头猫}
1666c6f45bdS猫头猫
1676c6f45bdS猫头猫/** 初始化 */
1686c6f45bdS猫头猫async function setupFolder() {
1696780f402S猫头猫    await Promise.all([
170be0a3650S猫头猫        checkAndCreateDir(pathConst.dataPath),
1717f771613S猫头猫        checkAndCreateDir(pathConst.logPath),
1727f771613S猫头猫        checkAndCreateDir(pathConst.cachePath),
173c79c8a57S猫头猫        checkAndCreateDir(pathConst.pluginPath),
17494a1b1fcS猫头猫        checkAndCreateDir(pathConst.lrcCachePath),
175*42a9f3e6Smaotoumao        checkAndCreateDir(pathConst.downloadCachePath),
17626f32636S猫头猫        checkAndCreateDir(pathConst.localLrcPath),
1770e4173cdS猫头猫        checkAndCreateDir(pathConst.downloadPath).then(() => {
1780e4173cdS猫头猫            checkAndCreateDir(pathConst.downloadMusicPath);
1790e4173cdS猫头猫        }),
1806780f402S猫头猫    ]);
1816c6f45bdS猫头猫}
18294a1b1fcS猫头猫
18394a1b1fcS猫头猫export default async function () {
18494a1b1fcS猫头猫    try {
18594a1b1fcS猫头猫        await _bootstrap();
18694a1b1fcS猫头猫    } catch (e) {
18794a1b1fcS猫头猫        errorLog('初始化出错', e);
18894a1b1fcS猫头猫    }
18994a1b1fcS猫头猫    // 隐藏开屏动画
19094a1b1fcS猫头猫    console.log('HIDE');
1915589cdf3S猫头猫    await SplashScreen.hideAsync();
19294a1b1fcS猫头猫}
193b3a3a048S猫头猫
194b3a3a048S猫头猫/** 不需要阻塞的 */
195b3a3a048S猫头猫async function extraMakeup() {
196a84a85c5S猫头猫    // 自动更新
197b3a3a048S猫头猫    try {
19891eb8fa8S猫头猫        // 初始化网络状态
19991eb8fa8S猫头猫        Network.setup();
20091eb8fa8S猫头猫
201b3a3a048S猫头猫        if (Config.get('setting.basic.autoUpdatePlugin')) {
2020dd58d38S猫头猫            const lastUpdated = PersistStatus.get('app.pluginUpdateTime') || 0;
203b3a3a048S猫头猫            const now = Date.now();
204b3a3a048S猫头猫            if (Math.abs(now - lastUpdated) > 86400000) {
2050dd58d38S猫头猫                PersistStatus.set('app.pluginUpdateTime', now);
206b3a3a048S猫头猫                const plugins = PluginManager.getValidPlugins();
207b3a3a048S猫头猫                for (let i = 0; i < plugins.length; ++i) {
208b3a3a048S猫头猫                    const srcUrl = plugins[i].instance.srcUrl;
209b3a3a048S猫头猫                    if (srcUrl) {
210b3a3a048S猫头猫                        await PluginManager.installPluginFromUrl(srcUrl);
211b3a3a048S猫头猫                    }
212b3a3a048S猫头猫                }
213b3a3a048S猫头猫            }
214b3a3a048S猫头猫        }
215b3a3a048S猫头猫    } catch {}
216a84a85c5S猫头猫
217a84a85c5S猫头猫    async function handleLinkingUrl(url: string) {
218a84a85c5S猫头猫        // 插件
219a84a85c5S猫头猫        try {
220eea2f34fS猫头猫            if (url.startsWith('musicfree://install/')) {
221eea2f34fS猫头猫                const plugins = url
222eea2f34fS猫头猫                    .slice(20)
223eea2f34fS猫头猫                    .split(',')
224eea2f34fS猫头猫                    .map(decodeURIComponent);
225eea2f34fS猫头猫                await Promise.all(
226eea2f34fS猫头猫                    plugins.map(it =>
227eea2f34fS猫头猫                        PluginManager.installPluginFromUrl(it).catch(() => {}),
228eea2f34fS猫头猫                    ),
229eea2f34fS猫头猫                );
230eea2f34fS猫头猫                Toast.success('安装成功~');
231eea2f34fS猫头猫            } else if (url.endsWith('.js')) {
232e36e2599S猫头猫                PluginManager.installPlugin(url, {
233e36e2599S猫头猫                    notCheckVersion: Config.get(
234e36e2599S猫头猫                        'setting.basic.notCheckPluginVersion',
235e36e2599S猫头猫                    ),
236e36e2599S猫头猫                })
237a84a85c5S猫头猫                    .then(res => {
238a84a85c5S猫头猫                        Toast.success(`插件「${res.name}」安装成功~`);
239a84a85c5S猫头猫                    })
240a84a85c5S猫头猫                    .catch(e => {
241a84a85c5S猫头猫                        console.log(e);
242a84a85c5S猫头猫                        Toast.warn(e?.message ?? '无法识别此插件');
243a84a85c5S猫头猫                    });
244a84a85c5S猫头猫            } else if (supportLocalMediaType.some(it => url.endsWith(it))) {
245a84a85c5S猫头猫                // 本地播放
246a84a85c5S猫头猫                const musicItem = await PluginManager.getByHash(
247a84a85c5S猫头猫                    localPluginHash,
248a84a85c5S猫头猫                )?.instance?.importMusicItem?.(url);
249a84a85c5S猫头猫                console.log(musicItem);
250a84a85c5S猫头猫                if (musicItem) {
2515500cea7S猫头猫                    TrackPlayer.play(musicItem);
252a84a85c5S猫头猫                }
253a84a85c5S猫头猫            }
254a84a85c5S猫头猫        } catch {}
255a84a85c5S猫头猫    }
256a84a85c5S猫头猫
257a84a85c5S猫头猫    // 开启监听
258a84a85c5S猫头猫    Linking.addEventListener('url', data => {
259a84a85c5S猫头猫        if (data.url) {
260a84a85c5S猫头猫            handleLinkingUrl(data.url);
261a84a85c5S猫头猫        }
262a84a85c5S猫头猫    });
263a84a85c5S猫头猫    const initUrl = await Linking.getInitialURL();
264a84a85c5S猫头猫    if (initUrl) {
265a84a85c5S猫头猫        handleLinkingUrl(initUrl);
266a84a85c5S猫头猫    }
267aaa0db32S猫头猫
268aaa0db32S猫头猫    if (Config.get('setting.basic.autoPlayWhenAppStart')) {
2695500cea7S猫头猫        TrackPlayer.play();
270aaa0db32S猫头猫    }
271b3a3a048S猫头猫}
272