xref: /MusicFree/src/pages/searchPage/hooks/useSearch.ts (revision 08a8e62cefcd62ae360d77c4b4cb4cf69ede345b)
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