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