1import {pluginManager, usePlugins} from '@/common/pluginManager'; 2import produce from 'immer'; 3import {useAtom, useSetAtom} from 'jotai'; 4import {useCallback} from 'react'; 5import {PageStatus, pageStatusAtom, searchResultsAtom} from '../store/atoms'; 6 7const mergeData = ( 8 target: IPlugin.ISearchResult, 9 original: IPlugin.ISearchResult, 10 key: IPlugin.ISearchResultType, 11 platform: string, 12) => { 13 // @ts-ignore 14 target[key] = (target[key] ?? [])?.concat( 15 (original[key] ?? [])?.map(_ => { 16 _.platform = platform; 17 return _; 18 }), 19 ); 20 return target; 21}; 22 23export default function useSearch() { 24 const setPageStatus = useSetAtom(pageStatusAtom); 25 const [searchResults, setSearchResults] = useAtom(searchResultsAtom); 26 27 const search = useCallback(async function ( 28 query?: string, 29 platformHash = 'all', 30 queryPage = undefined, 31 ) { 32 // 如果没有搜索结果缓存,那就是没有搜过 33 const installedPlugins = pluginManager.getValidPlugins(); 34 const plugins = 35 platformHash === 'all' 36 ? installedPlugins 37 : [installedPlugins.find(_ => _.hash === platformHash)]; 38 plugins.forEach(async plugin => { 39 const _platform = plugin?.instance.platform; 40 const _hash = plugin?.hash; 41 if (!plugin || !_platform || !_hash) { 42 // 没有插件,此时直接进入结果页 43 setPageStatus(PageStatus.RESULT); 44 return; 45 } 46 const _prevResult = searchResults[_hash] ?? {}; 47 if (_prevResult.state === 'pending' || _prevResult.state === 'done') { 48 return; 49 } 50 const newSearch = 51 query || _prevResult?.currentPage === undefined || queryPage === 1; 52 query = query ?? _prevResult?.query ?? ''; 53 const page = 54 queryPage ?? newSearch ? 1 : (_prevResult.currentPage ?? 0) + 1; 55 try { 56 setSearchResults( 57 produce(draft => { 58 const prev = draft[_hash] ?? {}; 59 prev.query = query; 60 prev.state = 'pending'; 61 draft[_hash] = prev; 62 }), 63 ); 64 // !! jscore的promise有问题,改成hermes就好了,可能和JIT 65 const result = await plugin?.instance?.search?.(query, page); 66 setPageStatus(PageStatus.RESULT); 67 if (!result) { 68 throw new Error(); 69 } 70 setSearchResults( 71 produce(draft => { 72 const prev = draft[_hash] ?? {}; 73 prev.query = query!; 74 prev.currentPage = page; 75 if (result._isEnd === false) { 76 prev.state = 'resolved'; 77 } else { 78 prev.state = 'done'; 79 } 80 prev.result = newSearch 81 ? [result] 82 : [...(prev?.result ?? []), result]; 83 draft[_hash] = prev; 84 }), 85 ); 86 } catch (e) { 87 console.log('SEARCH ERROR', e); 88 setSearchResults( 89 produce(draft => { 90 const prev = draft[_hash] ?? {}; 91 prev.state = 'resolved'; 92 draft[_hash] = prev; 93 }), 94 ); 95 } 96 }); 97 }, 98 []); 99 100 return search; 101} 102 103// export default function useSearch() { 104// const setSearchResult = useSetAtom(searchResultAtom); 105// const setPageStatus = useSetAtom(pageStatusAtom); 106 107// async function search(query: string, page: number) { 108// const plugins = pluginManager.getPlugins(); 109// console.log('1', Date.now()); 110// const _rawResults = await allSettled( 111// // @ts-ignore 112// plugins.map(plugin => 113// plugin.instance?.search?.(query, page)?.then(res => { 114// console.log('1.1', Date.now()); 115// return res; 116// }), 117// ), 118// ); 119// console.log('2', Date.now()); 120// for (let i = 0; i < plugins.length; ++i) { 121// const _rr = _rawResults[i]; 122// setSearchResult(prevResult => 123// produce(page === 1 ? {} : prevResult, draft => { 124// // merge data 125// // @ts-ignore 126// const _result = _rr.status === 'fulfilled' ? _rr.value ?? {} : {}; 127// // 合并搜索结果 128// mergeData(draft, _result, 'music', plugins[i].instance.platform); 129// mergeData(draft, _result, 'album', plugins[i].instance.platform); 130// }), 131// ); 132// } 133// setPageStatus(PageStatus.RESULT); 134// } 135// return search; 136// } 137