132683ee6Smaotoumaoimport { check, PERMISSIONS, request } from "react-native-permissions"; 232683ee6Smaotoumaoimport RNTrackPlayer, { AppKilledPlaybackBehavior, Capability } from "react-native-track-player"; 332683ee6Smaotoumaoimport "react-native-get-random-values"; 432683ee6Smaotoumaoimport Config from "@/core/config"; 532683ee6Smaotoumaoimport pathConst from "@/constants/pathConst"; 632683ee6Smaotoumaoimport { checkAndCreateDir } from "@/utils/fileUtils"; 732683ee6Smaotoumaoimport { errorLog, trace } from "@/utils/log"; 832683ee6Smaotoumaoimport PluginManager from "@/core/pluginManager"; 932683ee6Smaotoumaoimport Network from "@/core/network"; 1032683ee6Smaotoumaoimport { ImgAsset } from "@/constants/assetsConst"; 1132683ee6Smaotoumaoimport LocalMusicSheet from "@/core/localMusicSheet"; 1232683ee6Smaotoumaoimport { Linking, Platform } from "react-native"; 1332683ee6Smaotoumaoimport Theme from "@/core/theme"; 1432683ee6Smaotoumaoimport LyricManager from "@/core/lyricManager"; 1532683ee6Smaotoumaoimport Toast from "@/utils/toast"; 1632683ee6Smaotoumaoimport { localPluginHash, supportLocalMediaType } from "@/constants/commonConst"; 1732683ee6Smaotoumaoimport TrackPlayer from "@/core/trackPlayer"; 1832683ee6Smaotoumaoimport musicHistory from "@/core/musicHistory"; 19*819a9075Smaotoumaoimport PersistStatus from "@/core/persistStatus.ts"; 2032683ee6Smaotoumaoimport { perfLogger } from "@/utils/perfLogger"; 2132683ee6Smaotoumaoimport * as SplashScreen from "expo-splash-screen"; 2232683ee6Smaotoumaoimport MusicSheet from "@/core/musicSheet"; 2332683ee6Smaotoumaoimport NativeUtils from "@/native/utils"; 2432683ee6Smaotoumaoimport { showDialog } from "@/components/dialogs/useDialog.ts"; 25bf6e62f2S猫头猫 268b88e961S猫头猫/** app加载前执行 278b88e961S猫头猫 * 1. 检查权限 288b88e961S猫头猫 * 2. 数据初始化 298b88e961S猫头猫 * 3. 308b88e961S猫头猫 */ 3191eb8fa8S猫头猫 3294a1b1fcS猫头猫async function _bootstrap() { 335589cdf3S猫头猫 await SplashScreen.preventAutoHideAsync() 345589cdf3S猫头猫 .then(result => 355589cdf3S猫头猫 console.log( 365589cdf3S猫头猫 `SplashScreen.preventAutoHideAsync() succeeded: ${result}`, 375589cdf3S猫头猫 ), 385589cdf3S猫头猫 ) 395589cdf3S猫头猫 .catch(console.warn); // it's good to explicitly catch and inspect any error 4091eb8fa8S猫头猫 const logger = perfLogger(); 41927dbe93S猫头猫 // 1. 检查权限 42740e3947S猫头猫 if (Platform.OS === 'android' && Platform.Version >= 30) { 43740e3947S猫头猫 const hasPermission = await NativeUtils.checkStoragePermission(); 44740e3947S猫头猫 if ( 45740e3947S猫头猫 !hasPermission && 46*819a9075Smaotoumao !PersistStatus.get('app.skipBootstrapStorageDialog') 47740e3947S猫头猫 ) { 48740e3947S猫头猫 showDialog('CheckStorage'); 49740e3947S猫头猫 } 50740e3947S猫头猫 } else { 51740e3947S猫头猫 const [readStoragePermission, writeStoragePermission] = 52740e3947S猫头猫 await Promise.all([ 53bf6e62f2S猫头猫 check(PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE), 54bf6e62f2S猫头猫 check(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE), 55bf6e62f2S猫头猫 ]); 56bf6e62f2S猫头猫 if ( 57bf6e62f2S猫头猫 !( 58bf6e62f2S猫头猫 readStoragePermission === 'granted' && 59bf6e62f2S猫头猫 writeStoragePermission === 'granted' 60bf6e62f2S猫头猫 ) 61bf6e62f2S猫头猫 ) { 62bf6e62f2S猫头猫 await request(PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE); 63bf6e62f2S猫头猫 await request(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE); 64bf6e62f2S猫头猫 } 65740e3947S猫头猫 } 6691eb8fa8S猫头猫 logger.mark('权限检查完成'); 67bf6e62f2S猫头猫 68927dbe93S猫头猫 // 2. 数据初始化 696780f402S猫头猫 /** 初始化路径 */ 706780f402S猫头猫 await setupFolder(); 711e263108S猫头猫 trace('文件夹初始化完成'); 7291eb8fa8S猫头猫 logger.mark('文件夹初始化完成'); 7391eb8fa8S猫头猫 74bf6e62f2S猫头猫 // 加载配置 75ef714860S猫头猫 await Promise.all([ 7691eb8fa8S猫头猫 Config.setup().then(() => { 7791eb8fa8S猫头猫 logger.mark('Config'); 7891eb8fa8S猫头猫 }), 7991eb8fa8S猫头猫 MusicSheet.setup().then(() => { 8091eb8fa8S猫头猫 logger.mark('MusicSheet'); 8191eb8fa8S猫头猫 }), 8291eb8fa8S猫头猫 musicHistory.setupMusicHistory().then(() => { 8391eb8fa8S猫头猫 logger.mark('musicHistory'); 8491eb8fa8S猫头猫 }), 85ef714860S猫头猫 ]); 861e263108S猫头猫 trace('配置初始化完成'); 8791eb8fa8S猫头猫 logger.mark('配置初始化完成'); 8891eb8fa8S猫头猫 89bf6e62f2S猫头猫 // 加载插件 9094a1b1fcS猫头猫 try { 915500cea7S猫头猫 await RNTrackPlayer.setupPlayer({ 92b882a19dS猫头猫 maxCacheSize: 93b882a19dS猫头猫 Config.get('setting.basic.maxCacheSize') ?? 1024 * 1024 * 512, 94cfa0fc07S猫头猫 }); 9594a1b1fcS猫头猫 } catch (e: any) { 9694a1b1fcS猫头猫 if ( 974060c00aS猫头猫 e?.message !== 984060c00aS猫头猫 'The player has already been initialized via setupPlayer.' 9994a1b1fcS猫头猫 ) { 10094a1b1fcS猫头猫 throw e; 10194a1b1fcS猫头猫 } 10294a1b1fcS猫头猫 } 10391eb8fa8S猫头猫 logger.mark('加载播放器'); 10466e1d5fcS猫头猫 10566e1d5fcS猫头猫 const capabilities = Config.get('setting.basic.showExitOnNotification') 10666e1d5fcS猫头猫 ? [ 10766e1d5fcS猫头猫 Capability.Play, 10866e1d5fcS猫头猫 Capability.Pause, 10966e1d5fcS猫头猫 Capability.SkipToNext, 11066e1d5fcS猫头猫 Capability.SkipToPrevious, 11166e1d5fcS猫头猫 Capability.Stop, 11266e1d5fcS猫头猫 ] 11366e1d5fcS猫头猫 : [ 11466e1d5fcS猫头猫 Capability.Play, 11566e1d5fcS猫头猫 Capability.Pause, 11666e1d5fcS猫头猫 Capability.SkipToNext, 11766e1d5fcS猫头猫 Capability.SkipToPrevious, 11866e1d5fcS猫头猫 ]; 1195500cea7S猫头猫 await RNTrackPlayer.updateOptions({ 1202aa88193S猫头猫 icon: ImgAsset.logoTransparent, 121e2257bd6S猫头猫 progressUpdateEventInterval: 1, 1225500cea7S猫头猫 android: { 1235500cea7S猫头猫 alwaysPauseOnInterruption: true, 1245500cea7S猫头猫 appKilledPlaybackBehavior: 1255500cea7S猫头猫 AppKilledPlaybackBehavior.ContinuePlayback, 1265500cea7S猫头猫 }, 12766e1d5fcS猫头猫 capabilities: capabilities, 12866e1d5fcS猫头猫 compactCapabilities: capabilities, 12966e1d5fcS猫头猫 notificationCapabilities: [...capabilities, Capability.SeekTo], 1300d39db21S猫头猫 }); 13191eb8fa8S猫头猫 logger.mark('播放器初始化完成'); 1321e263108S猫头猫 trace('播放器初始化完成'); 13391eb8fa8S猫头猫 1348b88e961S猫头猫 await PluginManager.setup(); 13591eb8fa8S猫头猫 logger.mark('插件初始化完成'); 13691eb8fa8S猫头猫 1371e263108S猫头猫 trace('插件初始化完成'); 1385500cea7S猫头猫 await TrackPlayer.setupTrackPlayer(); 1391e263108S猫头猫 trace('播放列表初始化完成'); 14091eb8fa8S猫头猫 logger.mark('播放列表初始化完成'); 14191eb8fa8S猫头猫 1420e4173cdS猫头猫 await LocalMusicSheet.setup(); 1430e4173cdS猫头猫 trace('本地音乐初始化完成'); 14491eb8fa8S猫头猫 logger.mark('本地音乐初始化完成'); 14591eb8fa8S猫头猫 146a27adc20S猫头猫 Theme.setup(); 147a27adc20S猫头猫 trace('主题初始化完成'); 14891eb8fa8S猫头猫 logger.mark('主题初始化完成'); 14991eb8fa8S猫头猫 15057277364S猫头猫 await LyricManager.setup(); 1518b88e961S猫头猫 15291eb8fa8S猫头猫 logger.mark('歌词初始化完成'); 15391eb8fa8S猫头猫 154b3a3a048S猫头猫 extraMakeup(); 155c79c8a57S猫头猫 ErrorUtils.setGlobalHandler(error => { 156c79c8a57S猫头猫 errorLog('未捕获的错误', error); 157c79c8a57S猫头猫 }); 158bf6e62f2S猫头猫} 1596c6f45bdS猫头猫 1606c6f45bdS猫头猫/** 初始化 */ 1616c6f45bdS猫头猫async function setupFolder() { 1626780f402S猫头猫 await Promise.all([ 163be0a3650S猫头猫 checkAndCreateDir(pathConst.dataPath), 1647f771613S猫头猫 checkAndCreateDir(pathConst.logPath), 1657f771613S猫头猫 checkAndCreateDir(pathConst.cachePath), 166c79c8a57S猫头猫 checkAndCreateDir(pathConst.pluginPath), 16794a1b1fcS猫头猫 checkAndCreateDir(pathConst.lrcCachePath), 16842a9f3e6Smaotoumao checkAndCreateDir(pathConst.downloadCachePath), 16926f32636S猫头猫 checkAndCreateDir(pathConst.localLrcPath), 1700e4173cdS猫头猫 checkAndCreateDir(pathConst.downloadPath).then(() => { 1710e4173cdS猫头猫 checkAndCreateDir(pathConst.downloadMusicPath); 1720e4173cdS猫头猫 }), 1736780f402S猫头猫 ]); 1746c6f45bdS猫头猫} 17594a1b1fcS猫头猫 17694a1b1fcS猫头猫export default async function () { 17794a1b1fcS猫头猫 try { 17894a1b1fcS猫头猫 await _bootstrap(); 17994a1b1fcS猫头猫 } catch (e) { 18094a1b1fcS猫头猫 errorLog('初始化出错', e); 18194a1b1fcS猫头猫 } 18294a1b1fcS猫头猫 // 隐藏开屏动画 18394a1b1fcS猫头猫 console.log('HIDE'); 1845589cdf3S猫头猫 await SplashScreen.hideAsync(); 18594a1b1fcS猫头猫} 186b3a3a048S猫头猫 187b3a3a048S猫头猫/** 不需要阻塞的 */ 188b3a3a048S猫头猫async function extraMakeup() { 189a84a85c5S猫头猫 // 自动更新 190b3a3a048S猫头猫 try { 19191eb8fa8S猫头猫 // 初始化网络状态 19291eb8fa8S猫头猫 Network.setup(); 19391eb8fa8S猫头猫 194b3a3a048S猫头猫 if (Config.get('setting.basic.autoUpdatePlugin')) { 195*819a9075Smaotoumao const lastUpdated = PersistStatus.get('app.pluginUpdateTime') || 0; 196b3a3a048S猫头猫 const now = Date.now(); 197b3a3a048S猫头猫 if (Math.abs(now - lastUpdated) > 86400000) { 198*819a9075Smaotoumao PersistStatus.set('app.pluginUpdateTime', now); 199b3a3a048S猫头猫 const plugins = PluginManager.getValidPlugins(); 200b3a3a048S猫头猫 for (let i = 0; i < plugins.length; ++i) { 201b3a3a048S猫头猫 const srcUrl = plugins[i].instance.srcUrl; 202b3a3a048S猫头猫 if (srcUrl) { 203b3a3a048S猫头猫 await PluginManager.installPluginFromUrl(srcUrl); 204b3a3a048S猫头猫 } 205b3a3a048S猫头猫 } 206b3a3a048S猫头猫 } 207b3a3a048S猫头猫 } 208b3a3a048S猫头猫 } catch {} 209a84a85c5S猫头猫 210a84a85c5S猫头猫 async function handleLinkingUrl(url: string) { 211a84a85c5S猫头猫 // 插件 212a84a85c5S猫头猫 try { 213eea2f34fS猫头猫 if (url.startsWith('musicfree://install/')) { 214eea2f34fS猫头猫 const plugins = url 215eea2f34fS猫头猫 .slice(20) 216eea2f34fS猫头猫 .split(',') 217eea2f34fS猫头猫 .map(decodeURIComponent); 218eea2f34fS猫头猫 await Promise.all( 219eea2f34fS猫头猫 plugins.map(it => 220eea2f34fS猫头猫 PluginManager.installPluginFromUrl(it).catch(() => {}), 221eea2f34fS猫头猫 ), 222eea2f34fS猫头猫 ); 223eea2f34fS猫头猫 Toast.success('安装成功~'); 224eea2f34fS猫头猫 } else if (url.endsWith('.js')) { 225e36e2599S猫头猫 PluginManager.installPlugin(url, { 226e36e2599S猫头猫 notCheckVersion: Config.get( 227e36e2599S猫头猫 'setting.basic.notCheckPluginVersion', 228e36e2599S猫头猫 ), 229e36e2599S猫头猫 }) 230a84a85c5S猫头猫 .then(res => { 231a84a85c5S猫头猫 Toast.success(`插件「${res.name}」安装成功~`); 232a84a85c5S猫头猫 }) 233a84a85c5S猫头猫 .catch(e => { 234a84a85c5S猫头猫 console.log(e); 235a84a85c5S猫头猫 Toast.warn(e?.message ?? '无法识别此插件'); 236a84a85c5S猫头猫 }); 237a84a85c5S猫头猫 } else if (supportLocalMediaType.some(it => url.endsWith(it))) { 238a84a85c5S猫头猫 // 本地播放 239a84a85c5S猫头猫 const musicItem = await PluginManager.getByHash( 240a84a85c5S猫头猫 localPluginHash, 241a84a85c5S猫头猫 )?.instance?.importMusicItem?.(url); 242a84a85c5S猫头猫 console.log(musicItem); 243a84a85c5S猫头猫 if (musicItem) { 2445500cea7S猫头猫 TrackPlayer.play(musicItem); 245a84a85c5S猫头猫 } 246a84a85c5S猫头猫 } 247a84a85c5S猫头猫 } catch {} 248a84a85c5S猫头猫 } 249a84a85c5S猫头猫 250a84a85c5S猫头猫 // 开启监听 251a84a85c5S猫头猫 Linking.addEventListener('url', data => { 252a84a85c5S猫头猫 if (data.url) { 253a84a85c5S猫头猫 handleLinkingUrl(data.url); 254a84a85c5S猫头猫 } 255a84a85c5S猫头猫 }); 256a84a85c5S猫头猫 const initUrl = await Linking.getInitialURL(); 257a84a85c5S猫头猫 if (initUrl) { 258a84a85c5S猫头猫 handleLinkingUrl(initUrl); 259a84a85c5S猫头猫 } 260aaa0db32S猫头猫 261aaa0db32S猫头猫 if (Config.get('setting.basic.autoPlayWhenAppStart')) { 2625500cea7S猫头猫 TrackPlayer.play(); 263aaa0db32S猫头猫 } 264b3a3a048S猫头猫} 265