xref: /MusicFree/src/pages/searchPage/hooks/useSearch.ts (revision 92a7e801f72a65b76b504a3522c1189ab5a67ed3)
1bf6e62f2S猫头猫import {pluginManager, usePlugins} from '@/common/pluginManager';
2bf6e62f2S猫头猫import produce from 'immer';
3bf6e62f2S猫头猫import {useAtom, useSetAtom} from 'jotai';
419c8eb6fS猫头猫import {useCallback, useRef} from 'react';
5bf6e62f2S猫头猫import {PageStatus, pageStatusAtom, searchResultsAtom} from '../store/atoms';
6bf6e62f2S猫头猫
7bf6e62f2S猫头猫export default function useSearch() {
8bf6e62f2S猫头猫  const setPageStatus = useSetAtom(pageStatusAtom);
9bf6e62f2S猫头猫  const [searchResults, setSearchResults] = useAtom(searchResultsAtom);
10bf6e62f2S猫头猫
1119c8eb6fS猫头猫  // 当前正在搜索
1219c8eb6fS猫头猫  const currentQueryRef = useRef<string>('');
1319c8eb6fS猫头猫
14ad2ad8ffS猫头猫  const search = useCallback(
15ad2ad8ffS猫头猫    async function (
16bf6e62f2S猫头猫      query?: string,
17bf6e62f2S猫头猫      platformHash = 'all',
18bf6e62f2S猫头猫      queryPage = undefined,
19bf6e62f2S猫头猫    ) {
20bf6e62f2S猫头猫      const installedPlugins = pluginManager.getValidPlugins();
21bf6e62f2S猫头猫      const plugins =
22bf6e62f2S猫头猫        platformHash === 'all'
23bf6e62f2S猫头猫          ? installedPlugins
24bf6e62f2S猫头猫          : [installedPlugins.find(_ => _.hash === platformHash)];
2519c8eb6fS猫头猫      // 使用选中插件搜素
26bf6e62f2S猫头猫      plugins.forEach(async plugin => {
27bf6e62f2S猫头猫        const _platform = plugin?.instance.platform;
28bf6e62f2S猫头猫        const _hash = plugin?.hash;
29bf6e62f2S猫头猫        if (!plugin || !_platform || !_hash) {
30bf6e62f2S猫头猫          // 没有插件,此时直接进入结果页
31bf6e62f2S猫头猫          setPageStatus(PageStatus.RESULT);
32bf6e62f2S猫头猫          return;
33bf6e62f2S猫头猫        }
3408a8e62cS猫头猫        const _prevResult = searchResults[_hash] ?? {};
3519c8eb6fS猫头猫        if (
3619c8eb6fS猫头猫          (_prevResult.state === 'pending' || _prevResult.state === 'done') &&
3719c8eb6fS猫头猫          undefined === query
3819c8eb6fS猫头猫        ) {
39bf6e62f2S猫头猫          return;
40bf6e62f2S猫头猫        }
41d139abf1S猫头猫
4219c8eb6fS猫头猫        // 是否是一次新的搜索
43bf6e62f2S猫头猫        const newSearch =
44bf6e62f2S猫头猫          query || _prevResult?.currentPage === undefined || queryPage === 1;
4519c8eb6fS猫头猫
4619c8eb6fS猫头猫        // 搜索关键词
4719c8eb6fS猫头猫        currentQueryRef.current = query = query ?? _prevResult?.query ?? '';
4819c8eb6fS猫头猫
4919c8eb6fS猫头猫        /** 搜索的页码 */
50bf6e62f2S猫头猫        const page =
51bf6e62f2S猫头猫          queryPage ?? newSearch ? 1 : (_prevResult.currentPage ?? 0) + 1;
52d139abf1S猫头猫
53bf6e62f2S猫头猫        try {
54*92a7e801S猫头猫          setSearchResults(
55*92a7e801S猫头猫            produce(draft => {
56bf6e62f2S猫头猫              const prev = draft[_hash] ?? {};
57*92a7e801S猫头猫              draft[_hash] = {
58*92a7e801S猫头猫                state: 'pending',
59*92a7e801S猫头猫                result: newSearch ? {} : prev.result,
60*92a7e801S猫头猫                query: query,
61*92a7e801S猫头猫                currentPage: page,
62*92a7e801S猫头猫              };
63*92a7e801S猫头猫              return draft;
64bf6e62f2S猫头猫            }),
65bf6e62f2S猫头猫          );
66ad2ad8ffS猫头猫          // !! jscore的promise有问题,改成hermes就好了,可能和JIT有关,不知道。
67bf6e62f2S猫头猫          const result = await plugin?.instance?.search?.(query, page);
6819c8eb6fS猫头猫          if (currentQueryRef.current !== query) {
6919c8eb6fS猫头猫            return;
7019c8eb6fS猫头猫          }
71bf6e62f2S猫头猫          setPageStatus(PageStatus.RESULT);
72bf6e62f2S猫头猫          if (!result) {
73bf6e62f2S猫头猫            throw new Error();
74bf6e62f2S猫头猫          }
75bf6e62f2S猫头猫          setSearchResults(
76bf6e62f2S猫头猫            produce(draft => {
77bf6e62f2S猫头猫              const prev = draft[_hash] ?? {};
7808a8e62cS猫头猫              if (result._isEnd === false) {
7908a8e62cS猫头猫                prev.state = 'resolved';
8008a8e62cS猫头猫              } else {
8108a8e62cS猫头猫                prev.state = 'done';
8208a8e62cS猫头猫              }
83bf6e62f2S猫头猫              prev.result = newSearch
84d139abf1S猫头猫                ? mergeResult(result, {}, _platform)
85d139abf1S猫头猫                : mergeResult(prev.result ?? {}, result ?? {}, _platform);
86d139abf1S猫头猫              draft[_hash] = {
87d139abf1S猫头猫                state: prev.state,
88d139abf1S猫头猫                result: prev.result,
89d139abf1S猫头猫                query: query,
90d139abf1S猫头猫                currentPage: page,
91d139abf1S猫头猫              };
92d139abf1S猫头猫              return draft;
93bf6e62f2S猫头猫            }),
94bf6e62f2S猫头猫          );
952f655a9eS猫头猫        } catch (e) {
962f655a9eS猫头猫          console.log('SEARCH ERROR', e);
97bf6e62f2S猫头猫          setSearchResults(
98bf6e62f2S猫头猫            produce(draft => {
99bf6e62f2S猫头猫              const prev = draft[_hash] ?? {};
10008a8e62cS猫头猫              prev.state = 'resolved';
101bf6e62f2S猫头猫              draft[_hash] = prev;
102bf6e62f2S猫头猫            }),
103bf6e62f2S猫头猫          );
104bf6e62f2S猫头猫        }
105bf6e62f2S猫头猫      });
106bf6e62f2S猫头猫    },
107ad2ad8ffS猫头猫    [searchResults],
108ad2ad8ffS猫头猫  );
109bf6e62f2S猫头猫
110bf6e62f2S猫头猫  return search;
111bf6e62f2S猫头猫}
112bf6e62f2S猫头猫
113ad2ad8ffS猫头猫// todo: 去重
114d139abf1S猫头猫const resultKeys: (keyof IPlugin.ISearchResult)[] = ['album', 'music'];
115d139abf1S猫头猫function mergeResult(
116d139abf1S猫头猫  obj1: Record<string, any>,
117d139abf1S猫头猫  obj2: Record<string, any>,
118d139abf1S猫头猫  platform: string,
119d139abf1S猫头猫): IPlugin.ISearchResult {
120d139abf1S猫头猫  const result: Record<string, any> = {};
121d139abf1S猫头猫  for (let k of resultKeys) {
122d139abf1S猫头猫    result[k] = (obj1[k] ?? [])
123d139abf1S猫头猫      .map((_: any) =>
124d139abf1S猫头猫        produce(_, (_: any) => {
125d139abf1S猫头猫          _.platform = platform;
126d139abf1S猫头猫        }),
127d139abf1S猫头猫      )
128d139abf1S猫头猫      .concat(
129d139abf1S猫头猫        (obj2[k] ?? []).map((_: any) =>
130d139abf1S猫头猫          produce(_, (_: any) => {
131d139abf1S猫头猫            _.platform = platform;
132d139abf1S猫头猫          }),
133d139abf1S猫头猫        ),
134d139abf1S猫头猫      );
135d139abf1S猫头猫  }
136d139abf1S猫头猫  return result;
137d139abf1S猫头猫}
138