1
- import { Button , Divider , H4 , H5 , H6 , Intent } from '@blueprintjs/core'
1
+ import { Alert , Button , Divider , H4 , H5 , H6 , Intent } from '@blueprintjs/core'
2
2
3
3
import clsx from 'clsx'
4
+ import { useAtom } from 'jotai'
5
+ import { isEqual , omit } from 'lodash'
4
6
import { useCallback , useEffect , useMemo , useRef , useState } from 'react'
5
7
import { UseFieldArrayRemove } from 'react-hook-form'
6
8
7
9
import { AppToaster } from 'components/Toaster'
8
10
import { OPERATORS , PROFESSIONS } from 'models/operator'
11
+ import { ignoreKeyDic } from 'store/useFavGroups'
12
+ import { favOperatorAtom } from 'store/useFavOperators'
9
13
10
14
import { EditorPerformerOperatorProps } from '../EditorPerformerOperator'
11
15
import { Group , Operator } from '../EditorSheet'
@@ -20,12 +24,23 @@ export interface SheetOperatorProps {
20
24
removeOperator : UseFieldArrayRemove
21
25
}
22
26
27
+ export interface OperatorModifyProps {
28
+ operatorPinHandle ?: ( value : Operator ) => void
29
+ operatorSelectHandle ?: ( value : string ) => void
30
+ operatorSkillHandle ?: ( value : Operator ) => void
31
+ }
32
+
23
33
const defaultProf = [
24
34
{
25
35
id : 'all' ,
26
36
name : '全部' ,
27
37
sub : [ ] ,
28
38
} ,
39
+ {
40
+ id : 'fav' ,
41
+ name : '收藏' ,
42
+ sub : [ ] ,
43
+ } ,
29
44
{
30
45
id : 'others' ,
31
46
name : '其它' ,
@@ -39,9 +54,9 @@ const defaultSubProf = [
39
54
]
40
55
41
56
const formattedProfessions = [
42
- defaultProf [ 0 ] ,
57
+ ... defaultProf . slice ( 0 , defaultProf . length - 1 ) ,
43
58
...PROFESSIONS ,
44
- ...defaultProf . slice ( 1 ) ,
59
+ ...defaultProf . slice ( defaultProf . length - 1 ) ,
45
60
]
46
61
47
62
const paginationSize = 60
@@ -56,6 +71,12 @@ const SheetOperator = ({
56
71
57
72
const [ selectedProf , setSelectedProf ] = useState ( formattedProfessions [ 0 ] )
58
73
const [ selectedSubProf , setSelectedSubProf ] = useState ( defaultSubProf [ 0 ] )
74
+ const [ favOperators , setFavOperators ] = useAtom ( favOperatorAtom )
75
+ const [ coverOperator , setCoverOperator ] = useState < Operator > ( )
76
+
77
+ const favOperatorFindByName = ( target : string ) => {
78
+ return ! ! favOperators . find ( ( { name } ) => name === target )
79
+ }
59
80
60
81
const [ formattedSubProfessions , operatorsGroupedByProf ] = useMemo (
61
82
( ) => [
@@ -73,12 +94,14 @@ const SheetOperator = ({
73
94
...OPERATORS ,
74
95
] . filter ( ( item ) => {
75
96
if ( selectedProf . id === defaultProf [ 0 ] . id ) return true
76
- else if ( selectedProf . id === defaultProf [ 1 ] . id ) {
97
+ if ( selectedProf . id === defaultProf [ 1 ] . id )
98
+ return favOperatorFindByName ( item . name )
99
+ else if ( selectedProf . id === defaultProf [ 2 ] . id ) {
77
100
return item . subProf === 'notchar1' || ! item . subProf
78
101
} else return ! ! selectedProf . sub ?. find ( ( op ) => op . id === item . subProf )
79
102
} ) ,
80
103
] ,
81
- [ selectedProf , existedOperators ] ,
104
+ [ selectedProf , existedOperators , favOperators ] ,
82
105
)
83
106
84
107
const checkOperatorSelected = useCallback (
@@ -93,6 +116,34 @@ const SheetOperator = ({
93
116
[ existedOperators , existedGroups ] ,
94
117
)
95
118
119
+ const checkOperatorPinned = ( target : Operator , ignoreKey = ignoreKeyDic ) =>
120
+ isEqual (
121
+ omit ( target , [ ...ignoreKey ] ) ,
122
+ omit (
123
+ favOperators . find ( ( { name } ) => name === target . name ) ,
124
+ [ ...ignoreKey ] ,
125
+ ) ,
126
+ )
127
+
128
+ const updateFavOperator = ( value : Operator ) =>
129
+ setFavOperators ( [
130
+ ...[ ...favOperators ] . filter ( ( { name } ) => name !== value . name ) ,
131
+ { ...value } ,
132
+ ] )
133
+
134
+ const operatorPinHandle : OperatorModifyProps [ 'operatorPinHandle' ] = (
135
+ value ,
136
+ ) => {
137
+ if ( checkOperatorPinned ( value ) )
138
+ setFavOperators (
139
+ [ ...favOperators ] . filter ( ( { name } ) => name !== value . name ) ,
140
+ )
141
+ else {
142
+ if ( favOperatorFindByName ( value . name ) ) setCoverOperator ( value )
143
+ else updateFavOperator ( value )
144
+ }
145
+ }
146
+
96
147
const operatorsGroupedBySubProf = useMemo ( ( ) => {
97
148
if ( selectedSubProf . id === 'all' ) return operatorsGroupedByProf
98
149
else if ( selectedSubProf . id === 'selected' )
@@ -105,7 +156,9 @@ const SheetOperator = ({
105
156
)
106
157
} , [ selectedSubProf , operatorsGroupedByProf , checkOperatorSelected ] )
107
158
108
- const operatorSelectHandle = ( operatorName : string ) => {
159
+ const operatorSelectHandle : OperatorModifyProps [ 'operatorSelectHandle' ] = (
160
+ operatorName ,
161
+ ) => {
109
162
if ( checkOperatorSelected ( operatorName ) )
110
163
if ( existedOperators . find ( ( item ) => item . name === operatorName ) )
111
164
removeOperator (
@@ -116,10 +169,19 @@ const SheetOperator = ({
116
169
message : `干员 ${ operatorName } 已被编组` ,
117
170
intent : Intent . DANGER ,
118
171
} )
119
- else submitOperator ( { name : operatorName } , undefined , true )
172
+ else
173
+ submitOperator (
174
+ favOperators . find ( ( { name } ) => name === operatorName ) || {
175
+ name : operatorName ,
176
+ } ,
177
+ undefined ,
178
+ true ,
179
+ )
120
180
}
121
181
122
- const operatorSkillHandle = ( value : Operator ) => {
182
+ const operatorSkillHandle : OperatorModifyProps [ 'operatorSkillHandle' ] = (
183
+ value ,
184
+ ) => {
123
185
submitOperator ( value , undefined , true )
124
186
}
125
187
@@ -259,44 +321,70 @@ const SheetOperator = ({
259
321
)
260
322
261
323
return (
262
- < div className = "flex h-full" >
263
- < div className = "flex-auto px-1" ref = { operatorScrollRef } >
264
- { operatorsGroupedBySubProf . length ? (
265
- < >
266
- < div
267
- key = "operatorContainer"
268
- className = "flex flex-wrap items-start content-start overscroll-contain relative"
269
- >
270
- { operatorsGroupedBySubProf
271
- . slice ( 0 , lastIndex )
272
- . map ( ( { name : operatorInfoName } , index ) => {
273
- const operatorDetail = existedOperators . find (
274
- ( { name } ) => name === operatorInfoName ,
275
- )
276
- return (
277
- < div
278
- className = "flex items-center w-32 h-32 flex-0"
279
- key = { index }
280
- >
281
- < OperatorItem
282
- selected = { checkOperatorSelected ( operatorInfoName ) }
283
- onSkillChange = { operatorSkillHandle }
284
- operator = { operatorDetail }
285
- name = { operatorInfoName }
286
- onClick = { ( ) => operatorSelectHandle ( operatorInfoName ) }
287
- />
288
- </ div >
289
- )
290
- } ) }
291
- </ div >
292
- { ShowMoreButton }
293
- </ >
294
- ) : (
295
- OperatorNoData
296
- ) }
324
+ < >
325
+ < div className = "flex h-full" >
326
+ < div className = "flex-auto px-1" ref = { operatorScrollRef } >
327
+ { operatorsGroupedBySubProf . length ? (
328
+ < >
329
+ < div
330
+ key = "operatorContainer"
331
+ className = "flex flex-wrap items-start content-start overscroll-contain relative"
332
+ >
333
+ { operatorsGroupedBySubProf
334
+ . slice ( 0 , lastIndex )
335
+ . map ( ( { name : operatorInfoName } , index ) => {
336
+ const operatorDetail = existedOperators . find (
337
+ ( { name } ) => name === operatorInfoName ,
338
+ )
339
+ return (
340
+ < div
341
+ className = "flex items-center w-32 h-32 flex-0"
342
+ key = { index }
343
+ >
344
+ < OperatorItem
345
+ selected = { checkOperatorSelected ( operatorInfoName ) }
346
+ pinned = { checkOperatorPinned (
347
+ operatorDetail || { name : operatorInfoName } ,
348
+ ) }
349
+ onSkillChange = { operatorSkillHandle }
350
+ operator = { operatorDetail }
351
+ name = { operatorInfoName }
352
+ onClick = { ( ) => operatorSelectHandle ( operatorInfoName ) }
353
+ onPinHandle = {
354
+ existedOperators . find (
355
+ ( { name } ) => name === operatorInfoName ,
356
+ )
357
+ ? operatorPinHandle
358
+ : undefined
359
+ }
360
+ />
361
+ </ div >
362
+ )
363
+ } ) }
364
+ </ div >
365
+ { ShowMoreButton }
366
+ </ >
367
+ ) : (
368
+ OperatorNoData
369
+ ) }
370
+ </ div >
371
+ { ProfSelect }
297
372
</ div >
298
- { ProfSelect }
299
- </ div >
373
+ < Alert
374
+ isOpen = { ! ! coverOperator }
375
+ confirmButtonText = "是"
376
+ cancelButtonText = "否"
377
+ icon = "error"
378
+ intent = { Intent . DANGER }
379
+ onConfirm = { ( ) => updateFavOperator ( coverOperator as Group ) }
380
+ onClose = { ( ) => setCoverOperator ( undefined ) }
381
+ >
382
+ < div >
383
+ < H5 > 收藏: </ H5 >
384
+ < p > 检测到同名的已收藏干员 { coverOperator ?. name } ,是否覆盖?</ p >
385
+ </ div >
386
+ </ Alert >
387
+ </ >
300
388
)
301
389
}
302
390
0 commit comments