xref: /MusicFree/src/pages/searchPage/hooks/useSearch.ts (revision 0b940038696677ddf4d2a91434ce49a8383fecf4)
1*0b940038S猫头猫import {Plugin, pluginManager} from '@/common/pluginManager';
2bf6e62f2S猫头猫import produce from 'immer';
3bf6e62f2S猫头猫import {useAtom, useSetAtom} from 'jotai';
419c8eb6fS猫头猫import {useCallback, useRef} from 'react';
5*0b940038S猫头猫import {
6*0b940038S猫头猫  PageStatus,
7*0b940038S猫头猫  pageStatusAtom,
8*0b940038S猫头猫  searchResultsAtom,
9*0b940038S猫头猫  SearchStateCode,
10*0b940038S猫头猫} from '../store/atoms';
11bf6e62f2S猫头猫
12bf6e62f2S猫头猫export default function useSearch() {
13bf6e62f2S猫头猫  const setPageStatus = useSetAtom(pageStatusAtom);
14bf6e62f2S猫头猫  const [searchResults, setSearchResults] = useAtom(searchResultsAtom);
15bf6e62f2S猫头猫
1619c8eb6fS猫头猫  // 当前正在搜索
1719c8eb6fS猫头猫  const currentQueryRef = useRef<string>('');
1819c8eb6fS猫头猫
19*0b940038S猫头猫  /**
20*0b940038S猫头猫   * query: 搜索词
21*0b940038S猫头猫   * queryPage: 搜索页码
22*0b940038S猫头猫   * type: 搜索类型
23*0b940038S猫头猫   * pluginHash: 搜索条件
24*0b940038S猫头猫   */
25ad2ad8ffS猫头猫  const search = useCallback(
26ad2ad8ffS猫头猫    async function (
27bf6e62f2S猫头猫      query?: string,
28*0b940038S猫头猫      queryPage?: number,
29*0b940038S猫头猫      type?: ICommon.SupportMediaType,
30*0b940038S猫头猫      pluginHash?: string,
31bf6e62f2S猫头猫    ) {
32*0b940038S猫头猫      /** 如果没有指定插件,就用所有插件搜索 */
33*0b940038S猫头猫
34*0b940038S猫头猫      let plugins: Plugin[] = [];
35*0b940038S猫头猫      if (pluginHash) {
36*0b940038S猫头猫        const tgtPlugin = pluginManager.getPluginByHash(pluginHash);
37*0b940038S猫头猫        tgtPlugin && (plugins = [tgtPlugin]);
38*0b940038S猫头猫      } else {
39*0b940038S猫头猫        plugins = pluginManager.getValidPlugins();
40*0b940038S猫头猫      }
41*0b940038S猫头猫
4219c8eb6fS猫头猫      // 使用选中插件搜素
43bf6e62f2S猫头猫      plugins.forEach(async plugin => {
44*0b940038S猫头猫        const _platform = plugin.instance.platform;
45*0b940038S猫头猫        const _hash = plugin.hash;
46*0b940038S猫头猫        if (!_platform || !_hash) {
47*0b940038S猫头猫          // 插件无效,此时直接进入结果页
48bf6e62f2S猫头猫          setPageStatus(PageStatus.RESULT);
49bf6e62f2S猫头猫          return;
50bf6e62f2S猫头猫        }
51*0b940038S猫头猫
52*0b940038S猫头猫        const searchType = type ?? plugin.instance.defaultSearchType ?? 'music';
53*0b940038S猫头猫        // 上一份搜索结果
54*0b940038S猫头猫        const prevPluginResult = searchResults[searchType][plugin.hash];
55*0b940038S猫头猫        /** 上一份搜索还没返回/已经结束 */
5619c8eb6fS猫头猫        if (
57*0b940038S猫头猫          (prevPluginResult?.state === SearchStateCode.PENDING ||
58*0b940038S猫头猫            prevPluginResult?.state === SearchStateCode.FINISHED) &&
5919c8eb6fS猫头猫          undefined === query
6019c8eb6fS猫头猫        ) {
61bf6e62f2S猫头猫          return;
62bf6e62f2S猫头猫        }
63d139abf1S猫头猫
6419c8eb6fS猫头猫        // 是否是一次新的搜索
65bf6e62f2S猫头猫        const newSearch =
66*0b940038S猫头猫          query || prevPluginResult?.page === undefined || queryPage === 1;
6719c8eb6fS猫头猫
68*0b940038S猫头猫        // 本次搜索关键词
69*0b940038S猫头猫        currentQueryRef.current = query =
70*0b940038S猫头猫          query ?? prevPluginResult?.query ?? '';
7119c8eb6fS猫头猫
7219c8eb6fS猫头猫        /** 搜索的页码 */
73bf6e62f2S猫头猫        const page =
74*0b940038S猫头猫          queryPage ?? newSearch ? 1 : (prevPluginResult?.page ?? 0) + 1;
75d139abf1S猫头猫
76bf6e62f2S猫头猫        try {
7792a7e801S猫头猫          setSearchResults(
7892a7e801S猫头猫            produce(draft => {
79*0b940038S猫头猫              const prevMediaResult: any = draft[searchType];
80*0b940038S猫头猫              prevMediaResult[_hash] = {
81*0b940038S猫头猫                state: newSearch
82*0b940038S猫头猫                  ? SearchStateCode.PENDING_FP
83*0b940038S猫头猫                  : SearchStateCode.PENDING,
84*0b940038S猫头猫                // @ts-ignore
85*0b940038S猫头猫                data: newSearch ? [] : prevMediaResult[_hash]?.data ?? [],
8692a7e801S猫头猫                query: query,
87*0b940038S猫头猫                page,
8892a7e801S猫头猫              };
8992a7e801S猫头猫              return draft;
90bf6e62f2S猫头猫            }),
91bf6e62f2S猫头猫          );
92ad2ad8ffS猫头猫          // !! jscore的promise有问题,改成hermes就好了,可能和JIT有关,不知道。
93*0b940038S猫头猫          const result = await plugin?.instance?.search?.(
94*0b940038S猫头猫            query,
95*0b940038S猫头猫            page,
96*0b940038S猫头猫            searchType,
97*0b940038S猫头猫          );
98*0b940038S猫头猫          /** 如果搜索结果不是本次结果 */
9919c8eb6fS猫头猫          if (currentQueryRef.current !== query) {
10019c8eb6fS猫头猫            return;
10119c8eb6fS猫头猫          }
102*0b940038S猫头猫          /** 切换到结果页 */
103bf6e62f2S猫头猫          setPageStatus(PageStatus.RESULT);
104bf6e62f2S猫头猫          if (!result) {
105bf6e62f2S猫头猫            throw new Error();
106bf6e62f2S猫头猫          }
107bf6e62f2S猫头猫          setSearchResults(
108bf6e62f2S猫头猫            produce(draft => {
109*0b940038S猫头猫              const prevMediaResult = draft[searchType];
110*0b940038S猫头猫              const prevPluginResult: any = prevMediaResult[_hash] ?? {
111*0b940038S猫头猫                data: [],
112*0b940038S猫头猫              };
113*0b940038S猫头猫              const tagedResult = makeTag(result.data ?? [], _platform);
114*0b940038S猫头猫
115*0b940038S猫头猫              prevMediaResult[_hash] = {
116*0b940038S猫头猫                state:
117*0b940038S猫头猫                  (result?.isEnd === false && result?.data?.length)
118*0b940038S猫头猫                    ? SearchStateCode.PARTLY_DONE
119*0b940038S猫头猫                    : SearchStateCode.FINISHED,
120*0b940038S猫头猫                query,
121*0b940038S猫头猫                page,
122*0b940038S猫头猫                data: newSearch
123*0b940038S猫头猫                  ? tagedResult
124*0b940038S猫头猫                  : (prevPluginResult.data ?? []).concat(tagedResult),
125d139abf1S猫头猫              };
126d139abf1S猫头猫              return draft;
127bf6e62f2S猫头猫            }),
128bf6e62f2S猫头猫          );
1292f655a9eS猫头猫        } catch (e) {
1302f655a9eS猫头猫          console.log('SEARCH ERROR', e);
131*0b940038S猫头猫          setPageStatus(PageStatus.RESULT);
132bf6e62f2S猫头猫          setSearchResults(
133bf6e62f2S猫头猫            produce(draft => {
134*0b940038S猫头猫              const prevMediaResult = draft[searchType];
135*0b940038S猫头猫              const prevPluginResult = prevMediaResult[_hash] ?? {data: []};
136*0b940038S猫头猫
137*0b940038S猫头猫              prevPluginResult.state = SearchStateCode.PARTLY_DONE;
138*0b940038S猫头猫              return draft;
139bf6e62f2S猫头猫            }),
140bf6e62f2S猫头猫          );
141bf6e62f2S猫头猫        }
142bf6e62f2S猫头猫      });
143bf6e62f2S猫头猫    },
144ad2ad8ffS猫头猫    [searchResults],
145ad2ad8ffS猫头猫  );
146bf6e62f2S猫头猫
147bf6e62f2S猫头猫  return search;
148bf6e62f2S猫头猫}
149bf6e62f2S猫头猫
150*0b940038S猫头猫function makeTag<X extends Record<string, any>[] = any[]>(
151*0b940038S猫头猫  objArray: X,
152*0b940038S猫头猫  tag: string,
153*0b940038S猫头猫): X {
154*0b940038S猫头猫  objArray.forEach(_ => {
155*0b940038S猫头猫    _.platform = tag;
156*0b940038S猫头猫  });
157*0b940038S猫头猫  return objArray;
158d139abf1S猫头猫}
159