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