Skip to content

Commit 79505ef

Browse files
cyfung1031CopilotCodFrm
authored
🐛 恢复搜索选项 (#1014)
* ScriptSearchField 卡顿修正 * Update src/pages/options/routes/ScriptList/ScriptCard.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * 先跟Copliot指示改一下。但最终还是要还原至 1.1.2 所以这块要重新搞 * lint * 恢复搜索选项 * 对比defaultValue * 设定搜素框宽度 * 处理搜索结果 --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: 王一之 <yz@ggnb.top>
1 parent e67138e commit 79505ef

File tree

8 files changed

+135
-126
lines changed

8 files changed

+135
-126
lines changed

src/app/service/service_worker/client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { Script, ScriptCode, ScriptRunResource, TClientPageLoadInfo } from
22
import { type Resource } from "@App/app/repo/resource";
33
import { type Subscribe } from "@App/app/repo/subscribe";
44
import { type Permission } from "@App/app/repo/permission";
5-
import type { InstallSource, ScriptMenu, ScriptMenuItem, SearchType, TBatchUpdateListAction } from "./types";
5+
import type { InstallSource, ScriptMenu, ScriptMenuItem, TBatchUpdateListAction } from "./types";
66
import { Client } from "@Packages/message/client";
77
import type { MessageSend } from "@Packages/message/types";
88
import type PermissionVerify from "./permission_verify";
@@ -66,7 +66,7 @@ export class ScriptClient extends Client {
6666
return this.doThrow("fetchInfo", uuid);
6767
}
6868

69-
getFilterResult(req: { type: SearchType; value: string }): Promise<ScriptCode | undefined> {
69+
getFilterResult(req: { value: string }): Promise<ScriptCode | undefined> {
7070
return this.do("getFilterResult", req);
7171
}
7272

src/app/service/service_worker/script.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ import {
4545
BatchUpdateListActionCode,
4646
type TBatchUpdateListAction,
4747
UpdateStatusCode,
48-
type SearchType,
4948
type TBatchUpdateRecord,
5049
} from "./types";
5150
import { getSimilarityScore, ScriptUpdateCheck } from "./script_update_check";
@@ -552,7 +551,7 @@ export class ScriptService {
552551
return true;
553552
}
554553

555-
async getFilterResult(req: { type: SearchType; value: string }) {
554+
async getFilterResult(req: { value: string }) {
556555
const OPTION_CASE_INSENSITIVE = true;
557556
const scripts = await this.scriptDAO.all();
558557
const scriptCodes = await Promise.all(

src/pages/options/routes/ScriptList/ScriptCard.tsx

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,5 @@
1-
import React, { useMemo, useState } from "react";
2-
import {
3-
Avatar,
4-
Button,
5-
Card,
6-
Divider,
7-
Input,
8-
Popconfirm,
9-
Space,
10-
Tag,
11-
Tooltip,
12-
Typography,
13-
} from "@arco-design/web-react";
1+
import React, { useMemo } from "react";
2+
import { Avatar, Button, Card, Divider, Popconfirm, Space, Tag, Tooltip, Typography } from "@arco-design/web-react";
143
import { Link, useNavigate } from "react-router-dom";
154
import { IconClockCircle, IconDragDotVertical } from "@arco-design/web-react/icon";
165
import {
@@ -30,7 +19,7 @@ import { hashColor, ScriptIcons } from "../utils";
3019
import { getCombinedMeta } from "@App/app/service/service_worker/utils";
3120
import { parseTags } from "@App/app/repo/metadata";
3221
import type { ScriptLoading } from "@App/pages/store/features/script";
33-
import { EnableSwitch, HomeCell, MemoizedAvatar, SourceCell, UpdateTimeCell } from "./components";
22+
import { EnableSwitch, HomeCell, MemoizedAvatar, ScriptSearchField, SourceCell, UpdateTimeCell } from "./components";
3423
import { useTranslation } from "react-i18next";
3524
import { VscLayoutSidebarLeft, VscLayoutSidebarLeftOff } from "react-icons/vsc";
3625
import { FaThList } from "react-icons/fa";
@@ -39,6 +28,8 @@ import { DndContext, KeyboardSensor, PointerSensor, useSensor, useSensors } from
3928
import { rectSortingStrategy, SortableContext, sortableKeyboardCoordinates, useSortable } from "@dnd-kit/sortable";
4029
import { CSS } from "@dnd-kit/utilities";
4130
import { useAppContext } from "@App/pages/store/AppContext";
31+
import type { SetSearchRequest } from "./hooks";
32+
import type { SearchType } from "@App/app/service/service_worker/types";
4233

4334
const { Text } = Typography;
4435

@@ -337,7 +328,8 @@ interface ScriptCardProps {
337328
updateScripts: (uuids: string[], data: Partial<Script | ScriptLoading>) => void;
338329
setUserConfig: (config: { script: Script; userConfig: UserConfig; values: { [key: string]: any } }) => void;
339330
setCloudScript: (script: Script) => void;
340-
setSearchKeyword: (keyword: string) => void;
331+
searchRequest: { keyword: string; type: SearchType };
332+
setSearchRequest: SetSearchRequest;
341333
handleDelete: (item: ScriptLoading) => void;
342334
handleConfig: (
343335
item: ScriptLoading,
@@ -356,12 +348,12 @@ export const ScriptCard = ({
356348
updateScripts,
357349
setUserConfig,
358350
setCloudScript,
359-
setSearchKeyword,
351+
searchRequest,
352+
setSearchRequest,
360353
handleDelete,
361354
handleConfig,
362355
handleRunStop,
363356
}: ScriptCardProps) => {
364-
const [searchValue, setSearchValue] = useState<string>("");
365357
const { t } = useTranslation();
366358
const { guideMode } = useAppContext();
367359

@@ -417,17 +409,11 @@ export const ScriptCard = ({
417409
>
418410
<div className="flex flex-row justify-between items-center" style={{ padding: "8px 0" }}>
419411
<div className="flex-1">
420-
<Input.Search
421-
size="small"
422-
searchButton
423-
style={{ maxWidth: 400 }}
424-
placeholder={t("enter_search_value", { search: `${t("name")}/${t("script_code")}` })!}
425-
value={searchValue}
426-
onChange={(value) => {
427-
setSearchValue(value);
428-
}}
429-
onSearch={(value) => {
430-
setSearchKeyword(value);
412+
<ScriptSearchField
413+
t={t}
414+
defaultValue={searchRequest}
415+
onSearch={(req) => {
416+
setSearchRequest(req);
431417
}}
432418
/>
433419
</div>

src/pages/options/routes/ScriptList/ScriptTable.tsx

Lines changed: 32 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,11 @@ import { i18nName } from "@App/locales/locales";
5757
import { hashColor, ScriptIcons } from "../utils";
5858
import type { ScriptLoading } from "@App/pages/store/features/script";
5959
import { requestEnableScript, pinToTop, scriptClient, synchronizeClient } from "@App/pages/store/features/script";
60-
import { type TFunction } from "i18next";
6160
import { getCombinedMeta } from "@App/app/service/service_worker/utils";
6261
import { parseTags } from "@App/app/repo/metadata";
63-
import { EnableSwitch, HomeCell, MemoizedAvatar, SourceCell, UpdateTimeCell } from "./components";
62+
import { EnableSwitch, HomeCell, MemoizedAvatar, ScriptSearchField, SourceCell, UpdateTimeCell } from "./components";
63+
import type { SetSearchRequest } from "./hooks";
64+
import type { SearchType } from "@App/app/service/service_worker/types";
6465

6566
type ListType = ScriptLoading;
6667

@@ -115,47 +116,6 @@ const DraggableContainer = React.forwardRef<HTMLTableSectionElement, React.HTMLA
115116

116117
DraggableContainer.displayName = "DraggableContainer";
117118

118-
const FilterDropdown = React.memo(
119-
({
120-
filterKeys,
121-
setFilterKeys,
122-
confirm,
123-
t,
124-
inputRef,
125-
}: {
126-
filterKeys: string;
127-
setFilterKeys: (filterKeys: string, callback?: (...args: any[]) => any) => void;
128-
confirm: (...args: any[]) => any;
129-
t: TFunction<"translation", undefined>;
130-
inputRef: React.RefObject<RefInputType>;
131-
}) => {
132-
const { onSearchChange } = {
133-
onSearchChange: (value: string) => {
134-
setFilterKeys(value);
135-
},
136-
};
137-
// onSearch 不能使用 useCallback / useMemo
138-
const onSearch = () => {
139-
confirm(filterKeys);
140-
};
141-
return (
142-
<div className="arco-table-custom-filter flex flex-row gap-2">
143-
<Input.Search
144-
ref={inputRef}
145-
size="small"
146-
searchButton
147-
style={{ minWidth: 240 }}
148-
placeholder={t("enter_search_value", { search: `${t("name")}/${t("script_code")}` })}
149-
defaultValue={filterKeys || ""}
150-
onChange={onSearchChange}
151-
onSearch={onSearch}
152-
/>
153-
</div>
154-
);
155-
}
156-
);
157-
FilterDropdown.displayName = "FilterDropdown";
158-
159119
function composeRefs<T>(...refs: React.Ref<T>[]): (node: T | null) => void {
160120
return (node) => {
161121
for (const ref of refs) {
@@ -460,7 +420,8 @@ interface ScriptTableProps {
460420
updateScripts: (uuids: string[], data: Partial<Script | ScriptLoading>) => void;
461421
setUserConfig: (config: { script: Script; userConfig: UserConfig; values: { [key: string]: any } }) => void;
462422
setCloudScript: (script: Script) => void;
463-
setSearchKeyword: (keyword: string) => void;
423+
searchRequest: { keyword: string; type: SearchType };
424+
setSearchRequest: SetSearchRequest;
464425
handleDelete: (item: ScriptLoading) => void;
465426
handleConfig: (
466427
item: ScriptLoading,
@@ -479,7 +440,8 @@ export const ScriptTable = ({
479440
updateScripts,
480441
setUserConfig,
481442
setCloudScript,
482-
setSearchKeyword,
443+
searchRequest,
444+
setSearchRequest,
483445
handleDelete,
484446
handleConfig,
485447
handleRunStop,
@@ -532,18 +494,19 @@ export const ScriptTable = ({
532494
dataIndex: "name",
533495
sorter: (a, b) => a.name.localeCompare(b.name),
534496
filterIcon: <IconSearch />,
535-
filterDropdown: ({ filterKeys, setFilterKeys, confirm }: any) => {
497+
filterDropdown: ({ confirm }: any) => {
536498
return (
537-
<FilterDropdown
538-
filterKeys={filterKeys}
539-
setFilterKeys={setFilterKeys}
540-
confirm={(value) => {
541-
setSearchKeyword(value || "");
542-
confirm();
543-
}}
544-
t={t}
545-
inputRef={inputRef}
546-
/>
499+
<div className="arco-table-custom-filter flex flex-row gap-2">
500+
<ScriptSearchField
501+
t={t}
502+
defaultValue={searchRequest}
503+
onSearch={(req) => {
504+
setSearchRequest(req);
505+
confirm();
506+
}}
507+
inputRef={inputRef}
508+
/>
509+
</div>
547510
);
548511
},
549512
onFilterDropdownVisibleChange: (visible) => {
@@ -657,7 +620,8 @@ export const ScriptTable = ({
657620
t,
658621
sidebarOpen,
659622
updateScripts,
660-
setSearchKeyword,
623+
searchRequest,
624+
setSearchRequest,
661625
navigate,
662626
setSidebarOpen,
663627
setViewMode,
@@ -679,30 +643,18 @@ export const ScriptTable = ({
679643
useEffect(() => {
680644
if (savedWidths === null) return;
681645

682-
setNewColumns((nColumns) => {
683-
const widths = columns.map((item) => savedWidths[item.key!] ?? item.width);
684-
const c = nColumns.length === widths.length ? nColumns : columns;
685-
return c.map((item, i) => {
686-
const width = widths[i];
687-
let dest;
688-
if (i === 8) {
689-
// 第8列特殊处理,因为可能涉及到操作图的显示
690-
dest = item.render === columns[i].render && item.title === columns[i].title ? item : columns[i];
691-
} else {
692-
dest = item;
646+
// 主要只需要处理列宽变化的情况
647+
setNewColumns(
648+
columns.map((item, i) => {
649+
if (savedWidths[item.key!] === undefined) {
650+
return columns[i];
693651
}
694-
let m =
695-
width === dest.width
696-
? dest
697-
: {
698-
...dest,
699-
width,
700-
};
701-
// 处理语言更新
702-
if (m.title !== columns[i].title) m = { ...m, title: columns[i].title };
703-
return m;
704-
});
705-
});
652+
return {
653+
...columns[i],
654+
width: savedWidths[item.key!] ?? item.width,
655+
};
656+
})
657+
);
706658
}, [savedWidths, columns]);
707659

708660
useEffect(() => {

src/pages/options/routes/ScriptList/components.tsx

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import type { SCRIPT_STATUS } from "@App/app/repo/scripts";
22
import { SCRIPT_STATUS_ENABLE } from "@App/app/repo/scripts";
33
import { scriptClient, type ScriptLoading } from "@App/pages/store/features/script";
4-
import { Avatar, Message, Switch, Tag, Tooltip } from "@arco-design/web-react";
4+
import { Avatar, Input, Message, Select, Space, Switch, Tag, Tooltip } from "@arco-design/web-react";
55
import React from "react";
66
import Text from "@arco-design/web-react/es/Typography/text";
77
import { TbWorldWww } from "react-icons/tb";
88
import { semTime } from "@App/pkg/utils/dayjs";
99
import { useTranslation } from "react-i18next";
1010
import { ListHomeRender } from "../utils";
1111
import { IconEdit, IconLink, IconUserAdd } from "@arco-design/web-react/icon";
12+
import type { SearchType } from "@App/app/service/service_worker/types";
13+
import type { TFunction } from "i18next";
14+
import type { RefInputType } from "@arco-design/web-react/es/Input";
1215

1316
export const EnableSwitch = React.memo(
1417
({
@@ -178,3 +181,53 @@ export const UpdateTimeCell = React.memo(({ className, script }: { className?: s
178181
);
179182
});
180183
UpdateTimeCell.displayName = "UpdateTimeCell";
184+
185+
interface ScriptSearchFieldProps {
186+
t: TFunction<"translation", undefined>;
187+
defaultValue: { keyword: string; type: SearchType };
188+
onSearch?: (req: { keyword: string; type: SearchType }) => void;
189+
inputRef?: React.RefObject<RefInputType>;
190+
}
191+
192+
export const ScriptSearchField = React.memo(
193+
({ t, defaultValue, onSearch, inputRef }: ScriptSearchFieldProps) => {
194+
const [keyword, setKeyword] = React.useState(defaultValue?.keyword || "");
195+
const [type, setType] = React.useState<SearchType>(defaultValue?.type || "auto");
196+
return (
197+
<Space direction="horizontal">
198+
<Select
199+
className="flex-1"
200+
triggerProps={{ autoAlignPopupWidth: false, autoAlignPopupMinWidth: true, position: "bl" }}
201+
size="small"
202+
value={type}
203+
onChange={(value) => {
204+
setType(value as SearchType);
205+
onSearch?.({ keyword, type: value as SearchType });
206+
}}
207+
>
208+
<Select.Option value="auto">{t("auto")}</Select.Option>
209+
<Select.Option value="name">{t("name")}</Select.Option>
210+
<Select.Option value="script_code">{t("script_code")}</Select.Option>
211+
</Select>
212+
<Input.Search
213+
ref={inputRef}
214+
size="small"
215+
searchButton
216+
style={{ width: 280 }}
217+
value={keyword}
218+
placeholder={t("enter_search_value", { search: `${t("name")}/${t("script_code")}` })!}
219+
onChange={(value) => {
220+
setKeyword(value);
221+
}}
222+
onSearch={(value) => {
223+
onSearch?.({ keyword: value, type });
224+
}}
225+
/>
226+
</Space>
227+
);
228+
},
229+
(prevProps, nextProps) => {
230+
return prevProps.t === nextProps.t && prevProps.defaultValue === nextProps.defaultValue;
231+
}
232+
);
233+
ScriptSearchField.displayName = "ScriptSearchField";

0 commit comments

Comments
 (0)