xref: /MusicFree/src/pages/searchPage/hooks/useSearch.ts (revision bf6e62f27bf21a011995d7561e0093fae1a2d72e)
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 {
113        setSearchResults(
114          produce(draft => {
115            const prev = draft[_hash] ?? {};
116            prev.pending = false;
117            draft[_hash] = prev;
118          }),
119        );
120      }
121    });
122  },
123  []);
124
125  return search;
126}
127
128// export default function useSearch() {
129//   const setSearchResult = useSetAtom(searchResultAtom);
130//   const setPageStatus = useSetAtom(pageStatusAtom);
131
132//   async function search(query: string, page: number) {
133//     const plugins = pluginManager.getPlugins();
134//     console.log('1', Date.now());
135//     const _rawResults = await allSettled(
136//       // @ts-ignore
137//       plugins.map(plugin =>
138//         plugin.instance?.search?.(query, page)?.then(res => {
139//           console.log('1.1', Date.now());
140//           return res;
141//         }),
142//       ),
143//     );
144//     console.log('2', Date.now());
145//     for (let i = 0; i < plugins.length; ++i) {
146//       const _rr = _rawResults[i];
147//       setSearchResult(prevResult =>
148//         produce(page === 1 ? {} : prevResult, draft => {
149//           // merge data
150//           // @ts-ignore
151//           const _result = _rr.status === 'fulfilled' ? _rr.value ?? {} : {};
152//           // 合并搜索结果
153//           mergeData(draft, _result, 'music', plugins[i].instance.platform);
154//           mergeData(draft, _result, 'album', plugins[i].instance.platform);
155//         }),
156//       );
157//     }
158//     setPageStatus(PageStatus.RESULT);
159//   }
160//   return search;
161// }
162