1740e3947S猫头猫/** 2740e3947S猫头猫 * 歌单管理 3740e3947S猫头猫 */ 4740e3947S猫头猫import {Immer} from 'immer'; 5740e3947S猫头猫import {useEffect, useMemo, useState} from 'react'; 6740e3947S猫头猫import {nanoid} from 'nanoid'; 7740e3947S猫头猫import {isSameMediaItem} from '@/utils/mediaItem'; 8740e3947S猫头猫import storage from '@/core/musicSheet/storage.ts'; 9740e3947S猫头猫import migrate, {migrateV2} from '@/core/musicSheet/migrate.ts'; 10740e3947S猫头猫import {getDefaultStore, useAtomValue} from 'jotai'; 11740e3947S猫头猫import { 12740e3947S猫头猫 musicListMap, 13740e3947S猫头猫 musicSheetsBaseAtom, 14740e3947S猫头猫 starredMusicSheetsAtom, 15740e3947S猫头猫} from '@/core/musicSheet/atoms.ts'; 16*adf41771S猫头猫import {ResumeMode, SortType} from '@/constants/commonConst.ts'; 17740e3947S猫头猫import SortedMusicList from '@/core/musicSheet/sortedMusicList.ts'; 18740e3947S猫头猫import ee from '@/core/musicSheet/ee.ts'; 19740e3947S猫头猫import Config from '@/core/config.ts'; 20740e3947S猫头猫 21740e3947S猫头猫const produce = new Immer({ 22740e3947S猫头猫 autoFreeze: false, 23740e3947S猫头猫}).produce; 24740e3947S猫头猫 25740e3947S猫头猫const defaultSheet: IMusic.IMusicSheetItemBase = { 26740e3947S猫头猫 id: 'favorite', 27740e3947S猫头猫 coverImg: undefined, 28740e3947S猫头猫 title: '我喜欢', 29740e3947S猫头猫 worksNum: 0, 30740e3947S猫头猫}; 31740e3947S猫头猫 32740e3947S猫头猫async function setup() { 33740e3947S猫头猫 // 升级逻辑 - 从 AsyncStorage 升级到 MMKV 34740e3947S猫头猫 await migrate(); 35740e3947S猫头猫 try { 36740e3947S猫头猫 const allSheets: IMusic.IMusicSheetItemBase[] = storage.getSheets(); 37740e3947S猫头猫 38740e3947S猫头猫 if (!Array.isArray(allSheets)) { 39740e3947S猫头猫 throw new Error('not exist'); 40740e3947S猫头猫 } 41740e3947S猫头猫 42740e3947S猫头猫 let needRestore = false; 43740e3947S猫头猫 if (!allSheets.length) { 44740e3947S猫头猫 allSheets.push({ 45740e3947S猫头猫 ...defaultSheet, 46740e3947S猫头猫 }); 47740e3947S猫头猫 needRestore = true; 48740e3947S猫头猫 } 49740e3947S猫头猫 if (allSheets[0].id !== defaultSheet.id) { 50740e3947S猫头猫 const defaultSheetIndex = allSheets.findIndex( 51740e3947S猫头猫 it => it.id === defaultSheet.id, 52740e3947S猫头猫 ); 53740e3947S猫头猫 54740e3947S猫头猫 if (defaultSheetIndex === -1) { 55740e3947S猫头猫 allSheets.unshift({ 56740e3947S猫头猫 ...defaultSheet, 57740e3947S猫头猫 }); 58740e3947S猫头猫 } else { 59740e3947S猫头猫 const firstSheet = allSheets.splice(defaultSheetIndex, 1); 60740e3947S猫头猫 allSheets.unshift(firstSheet[0]); 61740e3947S猫头猫 } 62740e3947S猫头猫 needRestore = true; 63740e3947S猫头猫 } 64740e3947S猫头猫 65740e3947S猫头猫 if (needRestore) { 66740e3947S猫头猫 await storage.setSheets(allSheets); 67740e3947S猫头猫 } 68740e3947S猫头猫 69740e3947S猫头猫 for (let sheet of allSheets) { 70740e3947S猫头猫 const musicList = storage.getMusicList(sheet.id); 71740e3947S猫头猫 const sortType = storage.getSheetMeta(sheet.id, 'sort') as SortType; 72740e3947S猫头猫 sheet.worksNum = musicList.length; 73740e3947S猫头猫 migrateV2.migrate(sheet.id, musicList); 74740e3947S猫头猫 musicListMap.set( 75740e3947S猫头猫 sheet.id, 76740e3947S猫头猫 new SortedMusicList(musicList, sortType, true), 77740e3947S猫头猫 ); 78740e3947S猫头猫 sheet.worksNum = musicList.length; 79740e3947S猫头猫 ee.emit('UpdateMusicList', { 80740e3947S猫头猫 sheetId: sheet.id, 81740e3947S猫头猫 updateType: 'length', 82740e3947S猫头猫 }); 83740e3947S猫头猫 } 84740e3947S猫头猫 migrateV2.done(); 85740e3947S猫头猫 getDefaultStore().set(musicSheetsBaseAtom, allSheets); 86740e3947S猫头猫 setupStarredMusicSheets(); 87740e3947S猫头猫 } catch (e: any) { 88740e3947S猫头猫 if (e.message === 'not exist') { 89740e3947S猫头猫 await storage.setSheets([defaultSheet]); 90740e3947S猫头猫 await storage.setMusicList(defaultSheet.id, []); 91740e3947S猫头猫 getDefaultStore().set(musicSheetsBaseAtom, [defaultSheet]); 92740e3947S猫头猫 musicListMap.set( 93740e3947S猫头猫 defaultSheet.id, 94740e3947S猫头猫 new SortedMusicList([], SortType.None, true), 95740e3947S猫头猫 ); 96740e3947S猫头猫 } 97740e3947S猫头猫 } 98740e3947S猫头猫} 99740e3947S猫头猫 100740e3947S猫头猫// 获取音乐 101740e3947S猫头猫function getSortedMusicListBySheetId(sheetId: string) { 102740e3947S猫头猫 let musicList: SortedMusicList; 103740e3947S猫头猫 if (!musicListMap.has(sheetId)) { 104740e3947S猫头猫 musicList = new SortedMusicList([], SortType.None, true); 105740e3947S猫头猫 musicListMap.set(sheetId, musicList); 106740e3947S猫头猫 } else { 107740e3947S猫头猫 musicList = musicListMap.get(sheetId)!; 108740e3947S猫头猫 } 109740e3947S猫头猫 110740e3947S猫头猫 return musicList; 111740e3947S猫头猫} 112740e3947S猫头猫 113740e3947S猫头猫/** 114740e3947S猫头猫 * 更新基本信息 115740e3947S猫头猫 * @param sheetId 歌单ID 116740e3947S猫头猫 * @param data 歌单数据 117740e3947S猫头猫 */ 118740e3947S猫头猫async function updateMusicSheetBase( 119740e3947S猫头猫 sheetId: string, 120740e3947S猫头猫 data: Partial<IMusic.IMusicSheetItemBase>, 121740e3947S猫头猫) { 122740e3947S猫头猫 const musicSheets = getDefaultStore().get(musicSheetsBaseAtom); 123740e3947S猫头猫 const targetSheetIndex = musicSheets.findIndex(it => it.id === sheetId); 124740e3947S猫头猫 125740e3947S猫头猫 if (targetSheetIndex === -1) { 126740e3947S猫头猫 return; 127740e3947S猫头猫 } 128740e3947S猫头猫 129740e3947S猫头猫 const newMusicSheets = produce(musicSheets, draft => { 130740e3947S猫头猫 draft[targetSheetIndex] = { 131740e3947S猫头猫 ...draft[targetSheetIndex], 132740e3947S猫头猫 ...data, 133740e3947S猫头猫 id: sheetId, 134740e3947S猫头猫 }; 135740e3947S猫头猫 return draft; 136740e3947S猫头猫 }); 137740e3947S猫头猫 await storage.setSheets(newMusicSheets); 138740e3947S猫头猫 getDefaultStore().set(musicSheetsBaseAtom, newMusicSheets); 139756bc302S猫头猫 ee.emit('UpdateSheetBasic', { 140756bc302S猫头猫 sheetId, 141756bc302S猫头猫 }); 142740e3947S猫头猫} 143740e3947S猫头猫 144740e3947S猫头猫/** 145740e3947S猫头猫 * 新建歌单 146740e3947S猫头猫 * @param title 歌单名称 147740e3947S猫头猫 */ 148740e3947S猫头猫async function addSheet(title: string) { 149740e3947S猫头猫 const newId = nanoid(); 150740e3947S猫头猫 const musicSheets = getDefaultStore().get(musicSheetsBaseAtom); 151740e3947S猫头猫 152740e3947S猫头猫 const newSheets: IMusic.IMusicSheetItemBase[] = [ 153740e3947S猫头猫 musicSheets[0], 154740e3947S猫头猫 { 155740e3947S猫头猫 title, 156740e3947S猫头猫 id: newId, 157740e3947S猫头猫 coverImg: undefined, 158740e3947S猫头猫 worksNum: 0, 159740e3947S猫头猫 createAt: Date.now(), 160740e3947S猫头猫 }, 161740e3947S猫头猫 ...musicSheets.slice(1), 162740e3947S猫头猫 ]; 163740e3947S猫头猫 // 写入存储 164740e3947S猫头猫 await storage.setSheets(newSheets); 165740e3947S猫头猫 await storage.setMusicList(newId, []); 166740e3947S猫头猫 167740e3947S猫头猫 // 更新状态 168740e3947S猫头猫 getDefaultStore().set(musicSheetsBaseAtom, newSheets); 169740e3947S猫头猫 let defaultSortType = Config.get('setting.basic.musicOrderInLocalSheet'); 170740e3947S猫头猫 if ( 171740e3947S猫头猫 defaultSortType && 172740e3947S猫头猫 [ 173740e3947S猫头猫 SortType.Newest, 174740e3947S猫头猫 SortType.Artist, 175740e3947S猫头猫 SortType.Album, 176740e3947S猫头猫 SortType.Oldest, 177740e3947S猫头猫 SortType.Title, 178740e3947S猫头猫 ].includes(defaultSortType) 179740e3947S猫头猫 ) { 180740e3947S猫头猫 storage.setSheetMeta(newId, 'sort', defaultSortType); 181740e3947S猫头猫 } else { 182740e3947S猫头猫 defaultSortType = SortType.None; 183740e3947S猫头猫 } 184740e3947S猫头猫 musicListMap.set(newId, new SortedMusicList([], defaultSortType, true)); 185740e3947S猫头猫 return newId; 186740e3947S猫头猫} 187740e3947S猫头猫 188740e3947S猫头猫async function resumeSheets( 189740e3947S猫头猫 sheets: IMusic.IMusicSheetItem[], 190*adf41771S猫头猫 resumeMode: ResumeMode, 191740e3947S猫头猫) { 192*adf41771S猫头猫 if (resumeMode === ResumeMode.Append) { 193*adf41771S猫头猫 // 逆序恢复,最新创建的在最上方 194*adf41771S猫头猫 for (let i = sheets.length - 1; i >= 0; --i) { 195*adf41771S猫头猫 const newSheetId = await addSheet(sheets[i].title || ''); 196*adf41771S猫头猫 await addMusic(newSheetId, sheets[i].musicList || []); 197*adf41771S猫头猫 } 198*adf41771S猫头猫 return; 199*adf41771S猫头猫 } 200740e3947S猫头猫 // 1. 分离默认歌单和其他歌单 201740e3947S猫头猫 const defaultSheetIndex = sheets.findIndex(it => it.id === defaultSheet.id); 202740e3947S猫头猫 203740e3947S猫头猫 let exportedDefaultSheet: IMusic.IMusicSheetItem | null = null; 204740e3947S猫头猫 205740e3947S猫头猫 if (defaultSheetIndex !== -1) { 206740e3947S猫头猫 exportedDefaultSheet = sheets.splice(defaultSheetIndex, 1)[0]; 207740e3947S猫头猫 } 208740e3947S猫头猫 209*adf41771S猫头猫 // 2. 合并默认歌单 210*adf41771S猫头猫 await addMusic(defaultSheet.id, exportedDefaultSheet?.musicList || []); 211*adf41771S猫头猫 212*adf41771S猫头猫 // 3. 合并其他歌单 213*adf41771S猫头猫 if (resumeMode === ResumeMode.OverwriteDefault) { 214740e3947S猫头猫 // 逆序恢复,最新创建的在最上方 215740e3947S猫头猫 for (let i = sheets.length - 1; i >= 0; --i) { 216740e3947S猫头猫 const newSheetId = await addSheet(sheets[i].title || ''); 217740e3947S猫头猫 await addMusic(newSheetId, sheets[i].musicList || []); 218740e3947S猫头猫 } 219*adf41771S猫头猫 } else { 220*adf41771S猫头猫 // 合并同名 221*adf41771S猫头猫 const existsSheetIdMap: Record<string, string> = {}; 222*adf41771S猫头猫 const allSheets = getDefaultStore().get(musicSheetsBaseAtom); 223*adf41771S猫头猫 allSheets.forEach(it => { 224*adf41771S猫头猫 existsSheetIdMap[it.title!] = it.id; 225*adf41771S猫头猫 }); 226*adf41771S猫头猫 for (let i = sheets.length - 1; i >= 0; --i) { 227*adf41771S猫头猫 let newSheetId = existsSheetIdMap[sheets[i].title || '']; 228*adf41771S猫头猫 if (!newSheetId) { 229*adf41771S猫头猫 newSheetId = await addSheet(sheets[i].title || ''); 230*adf41771S猫头猫 } 231*adf41771S猫头猫 await addMusic(newSheetId, sheets[i].musicList || []); 232*adf41771S猫头猫 } 233*adf41771S猫头猫 } 234740e3947S猫头猫 235740e3947S猫头猫 if (overwrite) { 236740e3947S猫头猫 } else { 237740e3947S猫头猫 const newSheetId = await addSheet( 238740e3947S猫头猫 exportedDefaultSheet?.title || defaultSheet.title!, 239740e3947S猫头猫 ); 240740e3947S猫头猫 await addMusic(newSheetId, exportedDefaultSheet?.musicList || []); 241740e3947S猫头猫 } 242740e3947S猫头猫} 243740e3947S猫头猫 244740e3947S猫头猫function backupSheets() { 245740e3947S猫头猫 const allSheets = getDefaultStore().get(musicSheetsBaseAtom); 246740e3947S猫头猫 return allSheets.map(it => ({ 247740e3947S猫头猫 ...it, 248740e3947S猫头猫 musicList: musicListMap.get(it.id)?.musicList || [], 249740e3947S猫头猫 })) as IMusic.IMusicSheetItem[]; 250740e3947S猫头猫} 251740e3947S猫头猫 252740e3947S猫头猫/** 253740e3947S猫头猫 * 删除歌单 254740e3947S猫头猫 * @param sheetId 歌单id 255740e3947S猫头猫 */ 256740e3947S猫头猫async function removeSheet(sheetId: string) { 257740e3947S猫头猫 // 只能删除非默认歌单 258740e3947S猫头猫 if (sheetId === defaultSheet.id) { 259740e3947S猫头猫 return; 260740e3947S猫头猫 } 261740e3947S猫头猫 const musicSheets = getDefaultStore().get(musicSheetsBaseAtom); 262740e3947S猫头猫 263740e3947S猫头猫 // 删除后的歌单 264740e3947S猫头猫 const newSheets = musicSheets.filter(item => item.id !== sheetId); 265740e3947S猫头猫 266740e3947S猫头猫 // 写入存储 267740e3947S猫头猫 storage.removeMusicList(sheetId); 268740e3947S猫头猫 await storage.setSheets(newSheets); 269740e3947S猫头猫 270740e3947S猫头猫 // 修改状态 271740e3947S猫头猫 getDefaultStore().set(musicSheetsBaseAtom, newSheets); 272740e3947S猫头猫 musicListMap.delete(sheetId); 273740e3947S猫头猫} 274740e3947S猫头猫 275740e3947S猫头猫/** 276740e3947S猫头猫 * 向歌单内添加音乐 277740e3947S猫头猫 * @param sheetId 歌单id 278740e3947S猫头猫 * @param musicItem 音乐 279740e3947S猫头猫 */ 280740e3947S猫头猫async function addMusic( 281740e3947S猫头猫 sheetId: string, 282740e3947S猫头猫 musicItem: IMusic.IMusicItem | Array<IMusic.IMusicItem>, 283740e3947S猫头猫) { 284740e3947S猫头猫 const now = Date.now(); 285740e3947S猫头猫 if (!Array.isArray(musicItem)) { 286740e3947S猫头猫 musicItem = [musicItem]; 287740e3947S猫头猫 } 288740e3947S猫头猫 const taggedMusicItems = musicItem.map((it, index) => ({ 289740e3947S猫头猫 ...it, 290740e3947S猫头猫 $timestamp: now, 291740e3947S猫头猫 $sortIndex: musicItem.length - index, 292740e3947S猫头猫 })); 293740e3947S猫头猫 294740e3947S猫头猫 let musicList = getSortedMusicListBySheetId(sheetId); 295740e3947S猫头猫 296740e3947S猫头猫 const addedCount = musicList.add(taggedMusicItems); 297740e3947S猫头猫 298740e3947S猫头猫 // Update 299740e3947S猫头猫 if (!addedCount) { 300740e3947S猫头猫 return; 301740e3947S猫头猫 } 302740e3947S猫头猫 const musicSheets = getDefaultStore().get(musicSheetsBaseAtom); 303740e3947S猫头猫 if ( 304740e3947S猫头猫 !musicSheets 305740e3947S猫头猫 .find(_ => _.id === sheetId) 306740e3947S猫头猫 ?.coverImg?.startsWith('file://') 307740e3947S猫头猫 ) { 308740e3947S猫头猫 await updateMusicSheetBase(sheetId, { 309740e3947S猫头猫 coverImg: musicList.at(0)?.artwork, 310740e3947S猫头猫 }); 311740e3947S猫头猫 } 312740e3947S猫头猫 313740e3947S猫头猫 // 更新音乐数量 314740e3947S猫头猫 getDefaultStore().set( 315740e3947S猫头猫 musicSheetsBaseAtom, 316740e3947S猫头猫 produce(draft => { 317740e3947S猫头猫 const musicSheet = draft.find(it => it.id === sheetId); 318740e3947S猫头猫 if (musicSheet) { 319740e3947S猫头猫 musicSheet.worksNum = musicList.length; 320740e3947S猫头猫 } 321740e3947S猫头猫 }), 322740e3947S猫头猫 ); 323740e3947S猫头猫 324740e3947S猫头猫 await storage.setMusicList(sheetId, musicList.musicList); 325740e3947S猫头猫 ee.emit('UpdateMusicList', { 326740e3947S猫头猫 sheetId, 327740e3947S猫头猫 updateType: 'length', 328740e3947S猫头猫 }); 329740e3947S猫头猫} 330740e3947S猫头猫 331740e3947S猫头猫async function removeMusicByIndex(sheetId: string, indices: number | number[]) { 332740e3947S猫头猫 if (!Array.isArray(indices)) { 333740e3947S猫头猫 indices = [indices]; 334740e3947S猫头猫 } 335740e3947S猫头猫 336740e3947S猫头猫 const musicList = getSortedMusicListBySheetId(sheetId); 337740e3947S猫头猫 338740e3947S猫头猫 musicList.removeByIndex(indices); 339740e3947S猫头猫 340740e3947S猫头猫 // Update 341740e3947S猫头猫 const musicSheets = getDefaultStore().get(musicSheetsBaseAtom); 342740e3947S猫头猫 if ( 343740e3947S猫头猫 !musicSheets 344740e3947S猫头猫 .find(_ => _.id === sheetId) 345740e3947S猫头猫 ?.coverImg?.startsWith('file://') 346740e3947S猫头猫 ) { 347740e3947S猫头猫 await updateMusicSheetBase(sheetId, { 348740e3947S猫头猫 coverImg: musicList.at(0)?.artwork, 349740e3947S猫头猫 }); 350740e3947S猫头猫 } 351740e3947S猫头猫 // 更新音乐数量 352740e3947S猫头猫 getDefaultStore().set( 353740e3947S猫头猫 musicSheetsBaseAtom, 354740e3947S猫头猫 produce(draft => { 355740e3947S猫头猫 const musicSheet = draft.find(it => it.id === sheetId); 356740e3947S猫头猫 if (musicSheet) { 357740e3947S猫头猫 musicSheet.worksNum = musicList.length; 358740e3947S猫头猫 } 359740e3947S猫头猫 }), 360740e3947S猫头猫 ); 361740e3947S猫头猫 await storage.setMusicList(sheetId, musicList.musicList); 362740e3947S猫头猫 ee.emit('UpdateMusicList', { 363740e3947S猫头猫 sheetId, 364740e3947S猫头猫 updateType: 'length', 365740e3947S猫头猫 }); 366740e3947S猫头猫} 367740e3947S猫头猫 368740e3947S猫头猫async function removeMusic( 369740e3947S猫头猫 sheetId: string, 370740e3947S猫头猫 musicItems: IMusic.IMusicItem | IMusic.IMusicItem[], 371740e3947S猫头猫) { 372740e3947S猫头猫 if (!Array.isArray(musicItems)) { 373740e3947S猫头猫 musicItems = [musicItems]; 374740e3947S猫头猫 } 375740e3947S猫头猫 376740e3947S猫头猫 const musicList = getSortedMusicListBySheetId(sheetId); 377740e3947S猫头猫 musicList.remove(musicItems); 378740e3947S猫头猫 379740e3947S猫头猫 // Update 380740e3947S猫头猫 const musicSheets = getDefaultStore().get(musicSheetsBaseAtom); 381915d90f1S猫头猫 382915d90f1S猫头猫 let patchData: Partial<IMusic.IMusicSheetItemBase> = {}; 383740e3947S猫头猫 if ( 384740e3947S猫头猫 !musicSheets 385740e3947S猫头猫 .find(_ => _.id === sheetId) 386740e3947S猫头猫 ?.coverImg?.startsWith('file://') 387740e3947S猫头猫 ) { 388915d90f1S猫头猫 patchData.coverImg = musicList.at(0)?.artwork; 389915d90f1S猫头猫 } 390915d90f1S猫头猫 patchData.worksNum = musicList.length; 391740e3947S猫头猫 await updateMusicSheetBase(sheetId, { 392740e3947S猫头猫 coverImg: musicList.at(0)?.artwork, 393740e3947S猫头猫 }); 394915d90f1S猫头猫 395740e3947S猫头猫 await storage.setMusicList(sheetId, musicList.musicList); 396740e3947S猫头猫 ee.emit('UpdateMusicList', { 397740e3947S猫头猫 sheetId, 398740e3947S猫头猫 updateType: 'length', 399740e3947S猫头猫 }); 400740e3947S猫头猫} 401740e3947S猫头猫 402740e3947S猫头猫async function setSortType(sheetId: string, sortType: SortType) { 403740e3947S猫头猫 const musicList = getSortedMusicListBySheetId(sheetId); 404740e3947S猫头猫 musicList.setSortType(sortType); 405740e3947S猫头猫 406740e3947S猫头猫 // update 407740e3947S猫头猫 await storage.setMusicList(sheetId, musicList.musicList); 408740e3947S猫头猫 storage.setSheetMeta(sheetId, 'sort', sortType); 409740e3947S猫头猫 ee.emit('UpdateMusicList', { 410740e3947S猫头猫 sheetId, 411740e3947S猫头猫 updateType: 'resort', 412740e3947S猫头猫 }); 413740e3947S猫头猫} 414740e3947S猫头猫 415740e3947S猫头猫async function manualSort( 416740e3947S猫头猫 sheetId: string, 417740e3947S猫头猫 musicListAfterSort: IMusic.IMusicItem[], 418740e3947S猫头猫) { 419740e3947S猫头猫 const musicList = getSortedMusicListBySheetId(sheetId); 420740e3947S猫头猫 musicList.manualSort(musicListAfterSort); 421740e3947S猫头猫 422740e3947S猫头猫 // update 423740e3947S猫头猫 await storage.setMusicList(sheetId, musicList.musicList); 424740e3947S猫头猫 storage.setSheetMeta(sheetId, 'sort', SortType.None); 425740e3947S猫头猫 426740e3947S猫头猫 ee.emit('UpdateMusicList', { 427740e3947S猫头猫 sheetId, 428740e3947S猫头猫 updateType: 'resort', 429740e3947S猫头猫 }); 430740e3947S猫头猫} 431740e3947S猫头猫 432740e3947S猫头猫function useSheetsBase() { 433740e3947S猫头猫 return useAtomValue(musicSheetsBaseAtom); 434740e3947S猫头猫} 435740e3947S猫头猫 436740e3947S猫头猫// sheetId should not change 437740e3947S猫头猫function useSheetItem(sheetId: string) { 438740e3947S猫头猫 const sheetsBase = useAtomValue(musicSheetsBaseAtom); 439740e3947S猫头猫 440740e3947S猫头猫 const [sheetItem, setSheetItem] = useState<IMusic.IMusicSheetItem>({ 441740e3947S猫头猫 ...(sheetsBase.find(it => it.id === sheetId) || 442740e3947S猫头猫 ({} as IMusic.IMusicSheetItemBase)), 443740e3947S猫头猫 musicList: musicListMap.get(sheetId)?.musicList || [], 444740e3947S猫头猫 }); 445740e3947S猫头猫 446740e3947S猫头猫 useEffect(() => { 447740e3947S猫头猫 const onUpdateMusicList = ({sheetId: updatedSheetId}) => { 448740e3947S猫头猫 if (updatedSheetId !== sheetId) { 449740e3947S猫头猫 return; 450740e3947S猫头猫 } 451740e3947S猫头猫 setSheetItem(prev => ({ 452740e3947S猫头猫 ...prev, 453740e3947S猫头猫 musicList: musicListMap.get(sheetId)?.musicList || [], 454740e3947S猫头猫 })); 455740e3947S猫头猫 }; 456756bc302S猫头猫 457756bc302S猫头猫 const onUpdateSheetBasic = ({sheetId: updatedSheetId}) => { 458756bc302S猫头猫 if (updatedSheetId !== sheetId) { 459756bc302S猫头猫 return; 460756bc302S猫头猫 } 461756bc302S猫头猫 setSheetItem(prev => ({ 462756bc302S猫头猫 ...prev, 463756bc302S猫头猫 ...(getDefaultStore() 464756bc302S猫头猫 .get(musicSheetsBaseAtom) 465756bc302S猫头猫 .find(it => it.id === sheetId) || {}), 466756bc302S猫头猫 })); 467756bc302S猫头猫 }; 468740e3947S猫头猫 ee.on('UpdateMusicList', onUpdateMusicList); 469756bc302S猫头猫 ee.on('UpdateSheetBasic', onUpdateSheetBasic); 470740e3947S猫头猫 471740e3947S猫头猫 return () => { 472740e3947S猫头猫 ee.off('UpdateMusicList', onUpdateMusicList); 473756bc302S猫头猫 ee.off('UpdateSheetBasic', onUpdateSheetBasic); 474740e3947S猫头猫 }; 475740e3947S猫头猫 }, []); 476740e3947S猫头猫 477740e3947S猫头猫 return sheetItem; 478740e3947S猫头猫} 479740e3947S猫头猫 480740e3947S猫头猫function useFavorite(musicItem: IMusic.IMusicItem | null) { 481740e3947S猫头猫 const [fav, setFav] = useState(false); 482740e3947S猫头猫 483740e3947S猫头猫 useEffect(() => { 484740e3947S猫头猫 const onUpdateMusicList = ({sheetId: updatedSheetId, updateType}) => { 485740e3947S猫头猫 if (updatedSheetId !== defaultSheet.id || updateType === 'resort') { 486740e3947S猫头猫 return; 487740e3947S猫头猫 } 488740e3947S猫头猫 setFav(musicListMap.get(defaultSheet.id)?.has(musicItem) || false); 489740e3947S猫头猫 }; 490740e3947S猫头猫 ee.on('UpdateMusicList', onUpdateMusicList); 491740e3947S猫头猫 492740e3947S猫头猫 setFav(musicListMap.get(defaultSheet.id)?.has(musicItem) || false); 493740e3947S猫头猫 return () => { 494740e3947S猫头猫 ee.off('UpdateMusicList', onUpdateMusicList); 495740e3947S猫头猫 }; 496740e3947S猫头猫 }, [musicItem]); 497740e3947S猫头猫 498740e3947S猫头猫 return fav; 499740e3947S猫头猫} 500740e3947S猫头猫 501740e3947S猫头猫async function setupStarredMusicSheets() { 502740e3947S猫头猫 const starredSheets: IMusic.IMusicSheetItem[] = 503740e3947S猫头猫 storage.getStarredSheets() || []; 504740e3947S猫头猫 getDefaultStore().set(starredMusicSheetsAtom, starredSheets); 505740e3947S猫头猫} 506740e3947S猫头猫 507740e3947S猫头猫async function starMusicSheet(musicSheet: IMusic.IMusicSheetItem) { 508740e3947S猫头猫 const store = getDefaultStore(); 509740e3947S猫头猫 const starredSheets: IMusic.IMusicSheetItem[] = store.get( 510740e3947S猫头猫 starredMusicSheetsAtom, 511740e3947S猫头猫 ); 512740e3947S猫头猫 513740e3947S猫头猫 const newVal = [musicSheet, ...starredSheets]; 514740e3947S猫头猫 515740e3947S猫头猫 store.set(starredMusicSheetsAtom, newVal); 516740e3947S猫头猫 await storage.setStarredSheets(newVal); 517740e3947S猫头猫} 518740e3947S猫头猫 519740e3947S猫头猫async function unstarMusicSheet(musicSheet: IMusic.IMusicSheetItemBase) { 520740e3947S猫头猫 const store = getDefaultStore(); 521740e3947S猫头猫 const starredSheets: IMusic.IMusicSheetItem[] = store.get( 522740e3947S猫头猫 starredMusicSheetsAtom, 523740e3947S猫头猫 ); 524740e3947S猫头猫 525740e3947S猫头猫 const newVal = starredSheets.filter( 526740e3947S猫头猫 it => 527740e3947S猫头猫 !isSameMediaItem( 528740e3947S猫头猫 it as ICommon.IMediaBase, 529740e3947S猫头猫 musicSheet as ICommon.IMediaBase, 530740e3947S猫头猫 ), 531740e3947S猫头猫 ); 532740e3947S猫头猫 store.set(starredMusicSheetsAtom, newVal); 533740e3947S猫头猫 await storage.setStarredSheets(newVal); 534740e3947S猫头猫} 535740e3947S猫头猫 536740e3947S猫头猫function useSheetIsStarred( 537740e3947S猫头猫 musicSheet: IMusic.IMusicSheetItem | null | undefined, 538740e3947S猫头猫) { 539740e3947S猫头猫 // TODO: 类型有问题 540740e3947S猫头猫 const musicSheets = useAtomValue(starredMusicSheetsAtom); 541740e3947S猫头猫 return useMemo(() => { 542740e3947S猫头猫 if (!musicSheet) { 543740e3947S猫头猫 return false; 544740e3947S猫头猫 } 545740e3947S猫头猫 return ( 546740e3947S猫头猫 musicSheets.findIndex(it => 547740e3947S猫头猫 isSameMediaItem( 548740e3947S猫头猫 it as ICommon.IMediaBase, 549740e3947S猫头猫 musicSheet as ICommon.IMediaBase, 550740e3947S猫头猫 ), 551740e3947S猫头猫 ) !== -1 552740e3947S猫头猫 ); 553740e3947S猫头猫 }, [musicSheet, musicSheets]); 554740e3947S猫头猫} 555740e3947S猫头猫 556740e3947S猫头猫function useStarredSheets() { 557740e3947S猫头猫 return useAtomValue(starredMusicSheetsAtom); 558740e3947S猫头猫} 559740e3947S猫头猫 560740e3947S猫头猫/********* MusicSheet Meta ****************/ 561740e3947S猫头猫 562740e3947S猫头猫const MusicSheet = { 563740e3947S猫头猫 setup, 564740e3947S猫头猫 addSheet, 565740e3947S猫头猫 defaultSheet, 566740e3947S猫头猫 addMusic, 567740e3947S猫头猫 removeSheet, 568740e3947S猫头猫 backupSheets, 569740e3947S猫头猫 resumeSheets, 570740e3947S猫头猫 removeMusicByIndex, 571740e3947S猫头猫 removeMusic, 572740e3947S猫头猫 starMusicSheet, 573740e3947S猫头猫 unstarMusicSheet, 574740e3947S猫头猫 useFavorite, 575740e3947S猫头猫 useSheetsBase, 576740e3947S猫头猫 useSheetItem, 577740e3947S猫头猫 setSortType, 578740e3947S猫头猫 useSheetIsStarred, 579740e3947S猫头猫 useStarredSheets, 580740e3947S猫头猫 updateMusicSheetBase, 581740e3947S猫头猫 manualSort, 582740e3947S猫头猫 getSheetMeta: storage.getSheetMeta, 583740e3947S猫头猫}; 584740e3947S猫头猫 585740e3947S猫头猫export default MusicSheet; 586