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'; 90d39db21S猫头猫import RNBootSplash from 'react-native-bootsplash'; 106780f402S猫头猫import pathConst from '@/constants/pathConst'; 11be0a3650S猫头猫import {checkAndCreateDir} from '@/utils/fileUtils'; 121e263108S猫头猫import {errorLog, trace} from '@/utils/log'; 1343eb30bfS猫头猫import MediaMeta from '@/core/mediaMeta.old'; 1443eb30bfS猫头猫import Cache from '@/core/cache.old'; 15927dbe93S猫头猫import PluginManager from '@/core/pluginManager'; 16ef714860S猫头猫import Network from '@/core/network'; 17c30d30e1S猫头猫import {ImgAsset} from '@/constants/assetsConst'; 180e4173cdS猫头猫import LocalMusicSheet from '@/core/localMusicSheet'; 199c72192fS猫头猫import {Linking} from 'react-native'; 20a27adc20S猫头猫import Theme from '@/core/theme'; 2157277364S猫头猫import LyricManager from '@/core/lyricManager'; 22a84a85c5S猫头猫import Toast from '@/utils/toast'; 23a84a85c5S猫头猫import {localPluginHash, supportLocalMediaType} from '@/constants/commonConst'; 245500cea7S猫头猫import TrackPlayer from '@/core/trackPlayer'; 255500cea7S猫头猫import musicHistory from '@/core/musicHistory'; 260dd58d38S猫头猫import PersistStatus from '@/core/persistStatus'; 27*91eb8fa8S猫头猫import {perfLogger} from '@/utils/perfLogger'; 28bf6e62f2S猫头猫 298b88e961S猫头猫/** app加载前执行 308b88e961S猫头猫 * 1. 检查权限 318b88e961S猫头猫 * 2. 数据初始化 328b88e961S猫头猫 * 3. 338b88e961S猫头猫 */ 34*91eb8fa8S猫头猫 3594a1b1fcS猫头猫async function _bootstrap() { 36*91eb8fa8S猫头猫 const logger = perfLogger(); 37927dbe93S猫头猫 // 1. 检查权限 38bf6e62f2S猫头猫 const [readStoragePermission, writeStoragePermission] = await Promise.all([ 39bf6e62f2S猫头猫 check(PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE), 40bf6e62f2S猫头猫 check(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE), 41bf6e62f2S猫头猫 ]); 42bf6e62f2S猫头猫 if ( 43bf6e62f2S猫头猫 !( 44bf6e62f2S猫头猫 readStoragePermission === 'granted' && 45bf6e62f2S猫头猫 writeStoragePermission === 'granted' 46bf6e62f2S猫头猫 ) 47bf6e62f2S猫头猫 ) { 48bf6e62f2S猫头猫 await request(PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE); 49bf6e62f2S猫头猫 await request(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE); 50bf6e62f2S猫头猫 } 51*91eb8fa8S猫头猫 logger.mark('权限检查完成'); 52bf6e62f2S猫头猫 53927dbe93S猫头猫 // 2. 数据初始化 546780f402S猫头猫 /** 初始化路径 */ 556780f402S猫头猫 await setupFolder(); 561e263108S猫头猫 trace('文件夹初始化完成'); 57*91eb8fa8S猫头猫 logger.mark('文件夹初始化完成'); 58*91eb8fa8S猫头猫 59bf6e62f2S猫头猫 // 加载配置 60ef714860S猫头猫 await Promise.all([ 61*91eb8fa8S猫头猫 Config.setup().then(() => { 62*91eb8fa8S猫头猫 logger.mark('Config'); 63*91eb8fa8S猫头猫 }), 64*91eb8fa8S猫头猫 MediaMeta.setup().then(() => { 65*91eb8fa8S猫头猫 logger.mark('MediaMeta'); 66*91eb8fa8S猫头猫 }), 67*91eb8fa8S猫头猫 MusicSheet.setup().then(() => { 68*91eb8fa8S猫头猫 logger.mark('MusicSheet'); 69*91eb8fa8S猫头猫 }), 70*91eb8fa8S猫头猫 musicHistory.setupMusicHistory().then(() => { 71*91eb8fa8S猫头猫 logger.mark('musicHistory'); 72*91eb8fa8S猫头猫 }), 73ef714860S猫头猫 ]); 741e263108S猫头猫 trace('配置初始化完成'); 75*91eb8fa8S猫头猫 logger.mark('配置初始化完成'); 76*91eb8fa8S猫头猫 77bf6e62f2S猫头猫 // 加载插件 7894a1b1fcS猫头猫 try { 795500cea7S猫头猫 await RNTrackPlayer.setupPlayer({ 80b882a19dS猫头猫 maxCacheSize: 81b882a19dS猫头猫 Config.get('setting.basic.maxCacheSize') ?? 1024 * 1024 * 512, 82cfa0fc07S猫头猫 }); 8394a1b1fcS猫头猫 } catch (e: any) { 8494a1b1fcS猫头猫 if ( 854060c00aS猫头猫 e?.message !== 864060c00aS猫头猫 'The player has already been initialized via setupPlayer.' 8794a1b1fcS猫头猫 ) { 8894a1b1fcS猫头猫 throw e; 8994a1b1fcS猫头猫 } 9094a1b1fcS猫头猫 } 91*91eb8fa8S猫头猫 logger.mark('加载播放器'); 9266e1d5fcS猫头猫 9366e1d5fcS猫头猫 const capabilities = Config.get('setting.basic.showExitOnNotification') 9466e1d5fcS猫头猫 ? [ 9566e1d5fcS猫头猫 Capability.Play, 9666e1d5fcS猫头猫 Capability.Pause, 9766e1d5fcS猫头猫 Capability.SkipToNext, 9866e1d5fcS猫头猫 Capability.SkipToPrevious, 9966e1d5fcS猫头猫 Capability.Stop, 10066e1d5fcS猫头猫 ] 10166e1d5fcS猫头猫 : [ 10266e1d5fcS猫头猫 Capability.Play, 10366e1d5fcS猫头猫 Capability.Pause, 10466e1d5fcS猫头猫 Capability.SkipToNext, 10566e1d5fcS猫头猫 Capability.SkipToPrevious, 10666e1d5fcS猫头猫 ]; 1075500cea7S猫头猫 await RNTrackPlayer.updateOptions({ 1082aa88193S猫头猫 icon: ImgAsset.logoTransparent, 109e2257bd6S猫头猫 progressUpdateEventInterval: 1, 1105500cea7S猫头猫 android: { 1115500cea7S猫头猫 alwaysPauseOnInterruption: true, 1125500cea7S猫头猫 appKilledPlaybackBehavior: 1135500cea7S猫头猫 AppKilledPlaybackBehavior.ContinuePlayback, 1145500cea7S猫头猫 }, 11566e1d5fcS猫头猫 capabilities: capabilities, 11666e1d5fcS猫头猫 compactCapabilities: capabilities, 11766e1d5fcS猫头猫 notificationCapabilities: [...capabilities, Capability.SeekTo], 1180d39db21S猫头猫 }); 119*91eb8fa8S猫头猫 logger.mark('播放器初始化完成'); 1201e263108S猫头猫 trace('播放器初始化完成'); 1214060c00aS猫头猫 await Cache.setup(); 122*91eb8fa8S猫头猫 logger.mark('缓存初始化完成'); 123*91eb8fa8S猫头猫 1241e263108S猫头猫 trace('缓存初始化完成'); 1258b88e961S猫头猫 await PluginManager.setup(); 126*91eb8fa8S猫头猫 logger.mark('插件初始化完成'); 127*91eb8fa8S猫头猫 1281e263108S猫头猫 trace('插件初始化完成'); 1295500cea7S猫头猫 await TrackPlayer.setupTrackPlayer(); 1301e263108S猫头猫 trace('播放列表初始化完成'); 131*91eb8fa8S猫头猫 logger.mark('播放列表初始化完成'); 132*91eb8fa8S猫头猫 1330e4173cdS猫头猫 await LocalMusicSheet.setup(); 1340e4173cdS猫头猫 trace('本地音乐初始化完成'); 135*91eb8fa8S猫头猫 logger.mark('本地音乐初始化完成'); 136*91eb8fa8S猫头猫 137a27adc20S猫头猫 Theme.setup(); 138a27adc20S猫头猫 trace('主题初始化完成'); 139*91eb8fa8S猫头猫 logger.mark('主题初始化完成'); 140*91eb8fa8S猫头猫 14157277364S猫头猫 await LyricManager.setup(); 1428b88e961S猫头猫 143*91eb8fa8S猫头猫 logger.mark('歌词初始化完成'); 144*91eb8fa8S猫头猫 145b3a3a048S猫头猫 extraMakeup(); 146c79c8a57S猫头猫 ErrorUtils.setGlobalHandler(error => { 147c79c8a57S猫头猫 errorLog('未捕获的错误', error); 148c79c8a57S猫头猫 }); 149bf6e62f2S猫头猫} 1506c6f45bdS猫头猫 1516c6f45bdS猫头猫/** 初始化 */ 1526c6f45bdS猫头猫async function setupFolder() { 1536780f402S猫头猫 await Promise.all([ 154be0a3650S猫头猫 checkAndCreateDir(pathConst.dataPath), 1557f771613S猫头猫 checkAndCreateDir(pathConst.logPath), 1567f771613S猫头猫 checkAndCreateDir(pathConst.cachePath), 157c79c8a57S猫头猫 checkAndCreateDir(pathConst.pluginPath), 15894a1b1fcS猫头猫 checkAndCreateDir(pathConst.lrcCachePath), 1590e4173cdS猫头猫 checkAndCreateDir(pathConst.downloadPath).then(() => { 1600e4173cdS猫头猫 checkAndCreateDir(pathConst.downloadMusicPath); 1610e4173cdS猫头猫 }), 1626780f402S猫头猫 ]); 1636c6f45bdS猫头猫} 16494a1b1fcS猫头猫 16594a1b1fcS猫头猫export default async function () { 16694a1b1fcS猫头猫 try { 16794a1b1fcS猫头猫 await _bootstrap(); 16894a1b1fcS猫头猫 } catch (e) { 16994a1b1fcS猫头猫 errorLog('初始化出错', e); 17094a1b1fcS猫头猫 } 17194a1b1fcS猫头猫 // 隐藏开屏动画 17294a1b1fcS猫头猫 console.log('HIDE'); 17394a1b1fcS猫头猫 RNBootSplash.hide({fade: true}); 17494a1b1fcS猫头猫} 175b3a3a048S猫头猫 176b3a3a048S猫头猫/** 不需要阻塞的 */ 177b3a3a048S猫头猫async function extraMakeup() { 178a84a85c5S猫头猫 // 自动更新 179b3a3a048S猫头猫 try { 180*91eb8fa8S猫头猫 // 初始化网络状态 181*91eb8fa8S猫头猫 Network.setup(); 182*91eb8fa8S猫头猫 183b3a3a048S猫头猫 if (Config.get('setting.basic.autoUpdatePlugin')) { 1840dd58d38S猫头猫 const lastUpdated = PersistStatus.get('app.pluginUpdateTime') || 0; 185b3a3a048S猫头猫 const now = Date.now(); 186b3a3a048S猫头猫 if (Math.abs(now - lastUpdated) > 86400000) { 1870dd58d38S猫头猫 PersistStatus.set('app.pluginUpdateTime', now); 188b3a3a048S猫头猫 const plugins = PluginManager.getValidPlugins(); 189b3a3a048S猫头猫 for (let i = 0; i < plugins.length; ++i) { 190b3a3a048S猫头猫 const srcUrl = plugins[i].instance.srcUrl; 191b3a3a048S猫头猫 if (srcUrl) { 192b3a3a048S猫头猫 await PluginManager.installPluginFromUrl(srcUrl); 193b3a3a048S猫头猫 } 194b3a3a048S猫头猫 } 195b3a3a048S猫头猫 } 196b3a3a048S猫头猫 } 197b3a3a048S猫头猫 } catch {} 198a84a85c5S猫头猫 199a84a85c5S猫头猫 async function handleLinkingUrl(url: string) { 200a84a85c5S猫头猫 // 插件 201a84a85c5S猫头猫 try { 202eea2f34fS猫头猫 if (url.startsWith('musicfree://install/')) { 203eea2f34fS猫头猫 const plugins = url 204eea2f34fS猫头猫 .slice(20) 205eea2f34fS猫头猫 .split(',') 206eea2f34fS猫头猫 .map(decodeURIComponent); 207eea2f34fS猫头猫 await Promise.all( 208eea2f34fS猫头猫 plugins.map(it => 209eea2f34fS猫头猫 PluginManager.installPluginFromUrl(it).catch(() => {}), 210eea2f34fS猫头猫 ), 211eea2f34fS猫头猫 ); 212eea2f34fS猫头猫 Toast.success('安装成功~'); 213eea2f34fS猫头猫 } else if (url.endsWith('.js')) { 214e36e2599S猫头猫 PluginManager.installPlugin(url, { 215e36e2599S猫头猫 notCheckVersion: Config.get( 216e36e2599S猫头猫 'setting.basic.notCheckPluginVersion', 217e36e2599S猫头猫 ), 218e36e2599S猫头猫 }) 219a84a85c5S猫头猫 .then(res => { 220a84a85c5S猫头猫 Toast.success(`插件「${res.name}」安装成功~`); 221a84a85c5S猫头猫 }) 222a84a85c5S猫头猫 .catch(e => { 223a84a85c5S猫头猫 console.log(e); 224a84a85c5S猫头猫 Toast.warn(e?.message ?? '无法识别此插件'); 225a84a85c5S猫头猫 }); 226a84a85c5S猫头猫 } else if (supportLocalMediaType.some(it => url.endsWith(it))) { 227a84a85c5S猫头猫 // 本地播放 228a84a85c5S猫头猫 const musicItem = await PluginManager.getByHash( 229a84a85c5S猫头猫 localPluginHash, 230a84a85c5S猫头猫 )?.instance?.importMusicItem?.(url); 231a84a85c5S猫头猫 console.log(musicItem); 232a84a85c5S猫头猫 if (musicItem) { 2335500cea7S猫头猫 TrackPlayer.play(musicItem); 234a84a85c5S猫头猫 } 235a84a85c5S猫头猫 } 236a84a85c5S猫头猫 } catch {} 237a84a85c5S猫头猫 } 238a84a85c5S猫头猫 239a84a85c5S猫头猫 // 开启监听 240a84a85c5S猫头猫 Linking.addEventListener('url', data => { 241a84a85c5S猫头猫 if (data.url) { 242a84a85c5S猫头猫 handleLinkingUrl(data.url); 243a84a85c5S猫头猫 } 244a84a85c5S猫头猫 }); 245a84a85c5S猫头猫 const initUrl = await Linking.getInitialURL(); 246a84a85c5S猫头猫 if (initUrl) { 247a84a85c5S猫头猫 handleLinkingUrl(initUrl); 248a84a85c5S猫头猫 } 249aaa0db32S猫头猫 250aaa0db32S猫头猫 if (Config.get('setting.basic.autoPlayWhenAppStart')) { 2515500cea7S猫头猫 TrackPlayer.play(); 252aaa0db32S猫头猫 } 253b3a3a048S猫头猫} 254