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