Skip to content

Commit 9ab7c19

Browse files
committed
feat: add option for saving selected operators (#371)
1 parent 24d617c commit 9ab7c19

File tree

3 files changed

+85
-32
lines changed

3 files changed

+85
-32
lines changed

src/components/Operations.tsx

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,17 @@ import {
77
} from '@blueprintjs/core'
88

99
import { UseOperationsParams } from 'apis/operation'
10-
import { useAtom, useAtomValue } from 'jotai'
10+
import { useAtom } from 'jotai'
1111
import { debounce } from 'lodash-es'
1212
import { ComponentType, useMemo, useState } from 'react'
1313

1414
import { CardTitle } from 'components/CardTitle'
1515
import { OperationList } from 'components/OperationList'
1616
import { OperationSetList } from 'components/OperationSetList'
1717
import { neoLayoutAtom } from 'store/pref'
18-
import {
19-
selectedOperatorQueryAtom,
20-
selectedOperatorsAtom,
21-
} from 'store/selectedOperators'
2218

2319
import { authAtom } from '../store/auth'
24-
import { OperatorSelect } from './OperatorSelect'
20+
import { OperatorFilter } from './OperatorFilter'
2521
import { withSuspensable } from './Suspensable'
2622

2723
export const Operations: ComponentType = withSuspensable(() => {
@@ -31,14 +27,13 @@ export const Operations: ComponentType = withSuspensable(() => {
3127
limit: 10,
3228
orderBy: 'hot',
3329
})
34-
const [selectedOperators, setSelectedOperators] = useAtom(
35-
selectedOperatorsAtom,
36-
)
37-
const selectedOperatorQuery = useAtomValue(selectedOperatorQueryAtom)
3830
const debouncedSetQueryParams = useMemo(
3931
() => debounce(setQueryParams, 500),
4032
[],
4133
)
34+
35+
const [selectedOperators, setSelectedOperators] = useState<string[]>([])
36+
4237
const [authState] = useAtom(authAtom)
4338
const [neoLayout, setNeoLayout] = useAtom(neoLayoutAtom)
4439
const [listMode, setListMode] = useState<'operation' | 'operationSet'>(
@@ -104,14 +99,7 @@ export const Operations: ComponentType = withSuspensable(() => {
10499
{listMode === 'operation' && (
105100
<div className="flex flex-wrap items-end">
106101
<div className="flex mr-4">
107-
<FormGroup
108-
helperText={
109-
selectedOperators.length
110-
? '点击干员标签以标记为排除该干员'
111-
: undefined
112-
}
113-
className="max-w-md"
114-
>
102+
<div className="max-w-md">
115103
<InputGroup
116104
className="[&>input]:!rounded-md"
117105
placeholder="标题、描述、神秘代码"
@@ -145,12 +133,12 @@ export const Operations: ComponentType = withSuspensable(() => {
145133
}
146134
onBlur={() => debouncedSetQueryParams.flush()}
147135
/>
148-
<OperatorSelect
136+
<OperatorFilter
149137
className="mt-2"
150-
operators={selectedOperatorQuery.split(',')}
138+
operators={selectedOperators}
151139
onChange={setSelectedOperators}
152140
/>
153-
</FormGroup>
141+
</div>
154142
</div>
155143
<div className="flex flex-col">
156144
{filterNode}
@@ -221,7 +209,7 @@ export const Operations: ComponentType = withSuspensable(() => {
221209
{listMode === 'operation' && (
222210
<OperationList
223211
{...queryParams}
224-
operator={selectedOperatorQuery}
212+
operator={selectedOperators.join(',')}
225213
// 按热度排序时列表前几页的变化不会太频繁,可以不刷新第一页,节省点流量
226214
revalidateFirstPage={queryParams.orderBy !== 'hot'}
227215
/>

src/components/OperatorFilter.tsx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { Checkbox } from '@blueprintjs/core'
2+
3+
import { useAtom } from 'jotai'
4+
import { FC, useEffect } from 'react'
5+
6+
import {
7+
selectedOperatorsAtom,
8+
shouldSaveSelectedOperatorsAtom,
9+
} from '../store/selectedOperators'
10+
import { OperatorSelect } from './OperatorSelect'
11+
12+
interface OperatorSelectProps {
13+
className?: string
14+
operators: string[]
15+
onChange: (operators: string[]) => void
16+
}
17+
18+
export const OperatorFilter: FC<OperatorSelectProps> = ({
19+
className,
20+
operators,
21+
onChange,
22+
}) => {
23+
const [shouldSaveSelectedOperators, setShouldSaveSelectedOperators] = useAtom(
24+
shouldSaveSelectedOperatorsAtom,
25+
)
26+
const [savedSelectedOperators, setSavedSelectedOperators] = useAtom(
27+
selectedOperatorsAtom,
28+
)
29+
30+
useEffect(() => {
31+
// 用户在另一个标签页中修改选择时,savedSelectedOperators 会同步到当前标签页,需要手动更新给 operators
32+
if (shouldSaveSelectedOperators) {
33+
onChange(savedSelectedOperators)
34+
}
35+
}, [shouldSaveSelectedOperators, savedSelectedOperators, onChange])
36+
37+
const handleSelectOperator = (operators: string[]) => {
38+
onChange(operators)
39+
40+
if (shouldSaveSelectedOperators) {
41+
setSavedSelectedOperators(operators)
42+
}
43+
}
44+
45+
const handleShouldSaveSelectedOperators = (shouldSave: boolean) => {
46+
setShouldSaveSelectedOperators(shouldSave)
47+
48+
if (shouldSave) {
49+
setSavedSelectedOperators(operators)
50+
}
51+
}
52+
53+
return (
54+
<div className={className}>
55+
<OperatorSelect operators={operators} onChange={handleSelectOperator} />
56+
{operators.length > 0 && (
57+
<div className="flex justify-between items-baseline text-zinc-500">
58+
<div>点击干员标签以标记为排除该干员</div>
59+
<Checkbox
60+
checked={shouldSaveSelectedOperators}
61+
onChange={(e) =>
62+
handleShouldSaveSelectedOperators(e.currentTarget.checked)
63+
}
64+
>
65+
<span className="-ml-2">记住选择</span>
66+
</Checkbox>
67+
</div>
68+
)}
69+
</div>
70+
)
71+
}

src/store/selectedOperators.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
1-
import { atom } from 'jotai'
21
import { atomWithStorage } from 'jotai/utils'
32

4-
interface OperatorEntry {
5-
name: string
6-
exclude?: boolean
7-
}
8-
93
export const selectedOperatorsAtom = atomWithStorage(
104
'maa-copilot-selectedOperators',
115
[] as string[],
126
)
137

14-
export const selectedOperatorQueryAtom = atom((get) => {
15-
const operators = get(selectedOperatorsAtom)
16-
return operators.join(',')
17-
})
8+
export const shouldSaveSelectedOperatorsAtom = atomWithStorage(
9+
'maa-copilot-saveSelectedOperators',
10+
true,
11+
)

0 commit comments

Comments
 (0)