xref: /MusicFree/src/pages/searchPage/hooks/useSearch.ts (revision 2f655a9e3b66a152e554db5b6801c554a8ee8c95)
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?.pending) {
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.pending = true;
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            prev.pending = false;
76            prev.result = newSearch
77              ? [result]
78              : [...(prev?.result ?? []), result];
79            draft[_hash] = prev;
80          }),
81        );
82        // plugin?.instance
83        //   ?.search?.(query, page)
84        //   ?.then(result => {
85        //     // 任何一个加载出来就可以出现结果页了
86        //     setPageStatus(PageStatus.RESULT);
87        //     if (!result) {
88        //       throw new Error();
89        //     }
90        //     setSearchResults(
91        //       produce(draft => {
92        //         const prev = draft[_platform] ?? {};
93        //         prev.query = query!;
94        //         prev.currentPage = page;
95        //         prev.pending = false;
96        //         prev.result = newSearch
97        //           ? [result]
98        //           : [...(prev?.result ?? []), result];
99        //         draft[_platform] = prev;
100        //       }),
101        //     );
102        //   })
103        //   ?.catch(() => {
104        //     setSearchResults(
105        //       produce(draft => {
106        //         const prev = draft[_platform] ?? {};
107        //         prev.pending = false;
108        //         draft[_platform] = prev;
109        //       }),
110        //     );
111        //   });
112      } catch(e) {
113        console.log('SEARCH ERROR', e);
114        setSearchResults(
115          produce(draft => {
116            const prev = draft[_hash] ?? {};
117            prev.pending = false;
118            draft[_hash] = prev;
119          }),
120        );
121      }
122    });
123  },
124  []);
125
126  return search;
127}
128
129// export default function useSearch() {
130//   const setSearchResult = useSetAtom(searchResultAtom);
131//   const setPageStatus = useSetAtom(pageStatusAtom);
132
133//   async function search(query: string, page: number) {
134//     const plugins = pluginManager.getPlugins();
135//     console.log('1', Date.now());
136//     const _rawResults = await allSettled(
137//       // @ts-ignore
138//       plugins.map(plugin =>
139//         plugin.instance?.search?.(query, page)?.then(res => {
140//           console.log('1.1', Date.now());
141//           return res;
142//         }),
143//       ),
144//     );
145//     console.log('2', Date.now());
146//     for (let i = 0; i < plugins.length; ++i) {
147//       const _rr = _rawResults[i];
148//       setSearchResult(prevResult =>
149//         produce(page === 1 ? {} : prevResult, draft => {
150//           // merge data
151//           // @ts-ignore
152//           const _result = _rr.status === 'fulfilled' ? _rr.value ?? {} : {};
153//           // 合并搜索结果
154//           mergeData(draft, _result, 'music', plugins[i].instance.platform);
155//           mergeData(draft, _result, 'album', plugins[i].instance.platform);
156//         }),
157//       );
158//     }
159//     setPageStatus(PageStatus.RESULT);
160//   }
161//   return search;
162// }
163