xref: /MusicFree/src/pages/searchPage/hooks/useSearch.ts (revision ad2ad8ff0c73a593f8d871aeafe032c5ad4c688c)
1bf6e62f2S猫头猫import {pluginManager, usePlugins} from '@/common/pluginManager';
2bf6e62f2S猫头猫import produce from 'immer';
3bf6e62f2S猫头猫import {useAtom, useSetAtom} from 'jotai';
4bf6e62f2S猫头猫import {useCallback} 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猫头猫
11*ad2ad8ffS猫头猫  const search = useCallback(
12*ad2ad8ffS猫头猫    async function (
13bf6e62f2S猫头猫      query?: string,
14bf6e62f2S猫头猫      platformHash = 'all',
15bf6e62f2S猫头猫      queryPage = undefined,
16bf6e62f2S猫头猫    ) {
17bf6e62f2S猫头猫      // 如果没有搜索结果缓存,那就是没有搜过
18bf6e62f2S猫头猫      const installedPlugins = pluginManager.getValidPlugins();
19bf6e62f2S猫头猫      const plugins =
20bf6e62f2S猫头猫        platformHash === 'all'
21bf6e62f2S猫头猫          ? installedPlugins
22bf6e62f2S猫头猫          : [installedPlugins.find(_ => _.hash === platformHash)];
23bf6e62f2S猫头猫      plugins.forEach(async plugin => {
24bf6e62f2S猫头猫        const _platform = plugin?.instance.platform;
25bf6e62f2S猫头猫        const _hash = plugin?.hash;
26bf6e62f2S猫头猫        if (!plugin || !_platform || !_hash) {
27bf6e62f2S猫头猫          // 没有插件,此时直接进入结果页
28bf6e62f2S猫头猫          setPageStatus(PageStatus.RESULT);
29bf6e62f2S猫头猫          return;
30bf6e62f2S猫头猫        }
3108a8e62cS猫头猫        const _prevResult = searchResults[_hash] ?? {};
3208a8e62cS猫头猫        if (_prevResult.state === 'pending' || _prevResult.state === 'done') {
33bf6e62f2S猫头猫          return;
34bf6e62f2S猫头猫        }
35d139abf1S猫头猫
36bf6e62f2S猫头猫        const newSearch =
37bf6e62f2S猫头猫          query || _prevResult?.currentPage === undefined || queryPage === 1;
38bf6e62f2S猫头猫        query = query ?? _prevResult?.query ?? '';
39bf6e62f2S猫头猫        const page =
40bf6e62f2S猫头猫          queryPage ?? newSearch ? 1 : (_prevResult.currentPage ?? 0) + 1;
41d139abf1S猫头猫
42bf6e62f2S猫头猫        try {
43d139abf1S猫头猫          setSearchResults(prevState =>
44d139abf1S猫头猫            produce(prevState, draft => {
45bf6e62f2S猫头猫              const prev = draft[_hash] ?? {};
46bf6e62f2S猫头猫              prev.query = query;
4708a8e62cS猫头猫              prev.state = 'pending';
48bf6e62f2S猫头猫              draft[_hash] = prev;
49bf6e62f2S猫头猫            }),
50bf6e62f2S猫头猫          );
51*ad2ad8ffS猫头猫          // !! jscore的promise有问题,改成hermes就好了,可能和JIT有关,不知道。
52bf6e62f2S猫头猫          const result = await plugin?.instance?.search?.(query, page);
53bf6e62f2S猫头猫          setPageStatus(PageStatus.RESULT);
54bf6e62f2S猫头猫          if (!result) {
55bf6e62f2S猫头猫            throw new Error();
56bf6e62f2S猫头猫          }
57bf6e62f2S猫头猫          setSearchResults(
58bf6e62f2S猫头猫            produce(draft => {
59bf6e62f2S猫头猫              const prev = draft[_hash] ?? {};
6008a8e62cS猫头猫              if (result._isEnd === false) {
6108a8e62cS猫头猫                prev.state = 'resolved';
6208a8e62cS猫头猫              } else {
6308a8e62cS猫头猫                prev.state = 'done';
6408a8e62cS猫头猫              }
65bf6e62f2S猫头猫              prev.result = newSearch
66d139abf1S猫头猫                ? mergeResult(result, {}, _platform)
67d139abf1S猫头猫                : mergeResult(prev.result ?? {}, result ?? {}, _platform);
68d139abf1S猫头猫              draft[_hash] = {
69d139abf1S猫头猫                state: prev.state,
70d139abf1S猫头猫                result: prev.result,
71d139abf1S猫头猫                query: query,
72d139abf1S猫头猫                currentPage: page,
73d139abf1S猫头猫              };
74d139abf1S猫头猫              return draft;
75bf6e62f2S猫头猫            }),
76bf6e62f2S猫头猫          );
772f655a9eS猫头猫        } catch (e) {
782f655a9eS猫头猫          console.log('SEARCH ERROR', e);
79bf6e62f2S猫头猫          setSearchResults(
80bf6e62f2S猫头猫            produce(draft => {
81bf6e62f2S猫头猫              const prev = draft[_hash] ?? {};
8208a8e62cS猫头猫              prev.state = 'resolved';
83bf6e62f2S猫头猫              draft[_hash] = prev;
84bf6e62f2S猫头猫            }),
85bf6e62f2S猫头猫          );
86bf6e62f2S猫头猫        }
87bf6e62f2S猫头猫      });
88bf6e62f2S猫头猫    },
89*ad2ad8ffS猫头猫    [searchResults],
90*ad2ad8ffS猫头猫  );
91bf6e62f2S猫头猫
92bf6e62f2S猫头猫  return search;
93bf6e62f2S猫头猫}
94bf6e62f2S猫头猫
95*ad2ad8ffS猫头猫// todo: 去重
96d139abf1S猫头猫const resultKeys: (keyof IPlugin.ISearchResult)[] = ['album', 'music'];
97d139abf1S猫头猫function mergeResult(
98d139abf1S猫头猫  obj1: Record<string, any>,
99d139abf1S猫头猫  obj2: Record<string, any>,
100d139abf1S猫头猫  platform: string,
101d139abf1S猫头猫): IPlugin.ISearchResult {
102d139abf1S猫头猫  const result: Record<string, any> = {};
103d139abf1S猫头猫  for (let k of resultKeys) {
104d139abf1S猫头猫    result[k] = (obj1[k] ?? [])
105d139abf1S猫头猫      .map((_: any) =>
106d139abf1S猫头猫        produce(_, (_: any) => {
107d139abf1S猫头猫          _.platform = platform;
108d139abf1S猫头猫        }),
109d139abf1S猫头猫      )
110d139abf1S猫头猫      .concat(
111d139abf1S猫头猫        (obj2[k] ?? []).map((_: any) =>
112d139abf1S猫头猫          produce(_, (_: any) => {
113d139abf1S猫头猫            _.platform = platform;
114d139abf1S猫头猫          }),
115d139abf1S猫头猫        ),
116d139abf1S猫头猫      );
117d139abf1S猫头猫  }
118d139abf1S猫头猫  return result;
119d139abf1S猫头猫}
120