Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
N
Neos
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
love_飞影
Neos
Commits
c4c2246c
Commit
c4c2246c
authored
Jul 07, 2023
by
timel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
optimize: card drapdown menu store
parent
2e712f62
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
152 additions
and
143 deletions
+152
-143
src/ui/Duel/PlayMat/Card/index.tsx
src/ui/Duel/PlayMat/Card/index.tsx
+152
-143
No files found.
src/ui/Duel/PlayMat/Card/index.tsx
View file @
c4c2246c
...
...
@@ -4,8 +4,9 @@ import { animated, to, useSpring } from "@react-spring/web";
import
{
Dropdown
,
type
MenuProps
}
from
"
antd
"
;
import
classnames
from
"
classnames
"
;
import
React
,
{
type
CSSProperties
,
useEffect
,
useState
}
from
"
react
"
;
import
{
proxy
,
useSnapshot
}
from
"
valtio
"
;
import
{
useSnapshot
}
from
"
valtio
"
;
import
type
{
CardMeta
}
from
"
@/api
"
;
import
{
fetchStrings
,
getCardStr
,
...
...
@@ -139,7 +140,152 @@ export const Card: React.FC<{ idx: number }> = React.memo(({ idx }) => {
useEffect
(()
=>
{
setHighlight
(
!!
idleInteractivities
.
length
);
},
[
idleInteractivities
]);
const
menuItems
=
useSnapshot
(
dropdownMenu
);
const
[
dropdownMenu
,
setDropdownMenu
]
=
useState
({
items
:
[]
as
DropdownItem
[],
});
// 发动效果
// 1. 下拉菜单里面选择[召唤 / 特殊召唤 /.../效果发动]
// 2. 如果是非效果发动,那么直接选择哪张卡(单张卡直接选择那张)
// 3. 如果是效果发动,那么选择哪张卡,然后选择效果
const
handleDropdownMenu
=
(
cards
:
CardType
[],
isField
:
boolean
)
=>
{
const
map
=
new
Map
<
Interactivity
<
number
>
[
"
interactType
"
],
CardType
[]
>
();
cards
.
forEach
((
card
)
=>
{
card
.
idleInteractivities
.
forEach
(({
interactType
})
=>
{
if
(
!
map
.
has
(
interactType
))
{
map
.
set
(
interactType
,
[]);
}
map
.
get
(
interactType
)?.
push
(
card
);
});
});
const
actions
=
[...
map
.
entries
()];
const
nonEffectActions
=
actions
.
filter
(
([
action
])
=>
action
!==
InteractType
.
ACTIVATE
);
const
getNonEffectResponse
=
(
action
:
InteractType
,
card
:
CardType
)
=>
card
.
idleInteractivities
.
find
((
item
)
=>
item
.
interactType
===
action
)
!
.
response
;
const
nonEffectItem
:
DropdownItem
[]
=
nonEffectActions
.
map
(
([
action
,
cards
],
key
)
=>
({
key
,
label
:
interactTypeToString
(
action
),
onClick
:
async
()
=>
{
if
(
!
isField
)
{
// 单卡: 直接召唤/特殊召唤/...
const
card
=
cards
[
0
];
sendSelectIdleCmdResponse
(
getNonEffectResponse
(
action
,
card
));
}
else
{
// 场地: 选择卡片
// TODO: hint
const
option
=
await
displaySimpleSelectCardsModal
({
selectables
:
cards
.
map
((
card
)
=>
({
meta
:
card
.
meta
,
location
:
card
.
location
,
response
:
getNonEffectResponse
(
action
,
card
),
})),
});
sendSelectIdleCmdResponse
(
option
[
0
].
response
!
);
}
},
})
);
const
hasEffect
=
cards
.
reduce
(
(
prev
,
acc
)
=>
[
...
prev
,
...
acc
.
idleInteractivities
.
filter
(
({
interactType
})
=>
interactType
===
InteractType
.
ACTIVATE
),
],
[]
as
Interactivity
<
number
>
[]
).
length
>
0
;
const
effectItem
:
DropdownItem
=
{
key
:
nonEffectItem
.
length
,
label
:
interactTypeToString
(
InteractType
.
ACTIVATE
),
onClick
:
async
()
=>
{
let
card
:
CardType
;
if
(
!
isField
)
{
// 单卡: 直接发动这个卡的效果
card
=
cards
[
0
];
}
else
{
// 场地: 选择卡片
// TODO: hint
const
option
=
await
displaySimpleSelectCardsModal
({
selectables
:
cards
// 过滤掉不能发效果的卡
.
filter
(
(
card
)
=>
card
.
idleInteractivities
.
find
(
({
interactType
})
=>
interactType
===
InteractType
.
ACTIVATE
)
!==
undefined
)
.
map
((
card
)
=>
({
meta
:
card
.
meta
,
location
:
card
.
location
,
card
,
})),
});
card
=
option
[
0
].
card
!
as
any
;
// 一定会有的,有输入则定有输出
}
// 选择发动哪个效果
handleEffectActivation
(
card
.
idleInteractivities
.
filter
(
({
interactType
})
=>
interactType
===
InteractType
.
ACTIVATE
)
.
map
((
x
)
=>
({
desc
:
interactTypeToString
(
x
.
interactType
),
response
:
x
.
response
,
effectCode
:
x
.
activateIndex
,
})),
card
.
meta
);
},
};
const
items
=
[...
nonEffectItem
];
hasEffect
&&
items
.
push
(
effectItem
);
setDropdownMenu
({
items
});
};
const
onClick
=
()
=>
{
const
onCardClick
=
(
card
:
CardType
)
=>
{
// 中央弹窗展示选中卡牌信息
// TODO: 同一张卡片,是否重复点击会关闭CardModal?
displayCardModal
(
card
);
if
(
card
.
idleInteractivities
.
length
)
handleDropdownMenu
([
card
],
false
);
// 侧边栏展示超量素材信息
const
overlayMaterials
=
cardStore
.
findOverlay
(
card
.
location
.
zone
,
card
.
location
.
controller
,
card
.
location
.
sequence
);
if
(
overlayMaterials
.
length
>
0
)
{
displayCardListModal
({
isZone
:
false
,
monster
:
card
,
});
}
};
const
onFieldClick
=
(
card
:
CardType
)
=>
{
displayCardListModal
({
isZone
:
true
,
zone
:
card
.
location
.
zone
,
controller
:
card
.
location
.
controller
,
});
// 收集这个zone的所有交互,并且在下拉菜单之中显示
const
cards
=
cardStore
.
at
(
card
.
location
.
zone
,
card
.
location
.
controller
);
handleDropdownMenu
(
cards
,
true
);
};
if
([
MZONE
,
SZONE
,
HAND
].
includes
(
state
.
location
.
zone
))
{
onCardClick
(
state
);
}
else
if
([
EXTRA
,
GRAVE
,
REMOVED
].
includes
(
state
.
location
.
zone
))
{
onFieldClick
(
state
);
}
};
// <<< 效果 <<<
return
(
...
...
@@ -161,23 +307,17 @@ export const Card: React.FC<{ idx: number }> = React.memo(({ idx }) => {
"
--focus-opacity
"
:
styles
.
focusOpacity
,
}
as
any
as
CSSProperties
}
onClick=
{
()
=>
{
if
([
MZONE
,
SZONE
,
HAND
].
includes
(
state
.
location
.
zone
))
{
onCardClick
(
state
);
}
else
if
([
EXTRA
,
GRAVE
,
REMOVED
].
includes
(
state
.
location
.
zone
))
{
onFieldClick
(
state
);
}
}
}
onClick=
{
onClick
}
>
<
div
className=
"card-focus"
/>
<
div
className=
"card-shadow"
/>
<
Dropdown
menu=
{
{
items
:
menuItems
.
value
as
any
}
}
menu=
{
dropdownMenu
}
placement=
"bottom"
overlayClassName=
"card-dropdown"
arrow
trigger=
{
[
"
click
"
]
}
// disabled={!highlight}
// disabled={!highlight}
// TODO: 这里的disable要考虑到field的情况,比如额外卡组
>
<
div
className=
{
classnames
(
"
card-img-wrap
"
,
{
focus
:
classFocus
})
}
>
<
YgoCard
...
...
@@ -192,37 +332,6 @@ export const Card: React.FC<{ idx: number }> = React.memo(({ idx }) => {
);
});
const
onCardClick
=
(
card
:
CardType
)
=>
{
// 中央弹窗展示选中卡牌信息
// TODO: 同一张卡片,是否重复点击会关闭CardModal?
displayCardModal
(
card
);
if
(
card
.
idleInteractivities
)
handleDropdownMenu
([
card
],
false
);
// 侧边栏展示超量素材信息
const
overlayMaterials
=
cardStore
.
findOverlay
(
card
.
location
.
zone
,
card
.
location
.
controller
,
card
.
location
.
sequence
);
if
(
overlayMaterials
.
length
>
0
)
{
displayCardListModal
({
isZone
:
false
,
monster
:
card
,
});
}
};
const
onFieldClick
=
(
card
:
CardType
)
=>
{
displayCardListModal
({
isZone
:
true
,
zone
:
card
.
location
.
zone
,
controller
:
card
.
location
.
controller
,
});
// 收集这个zone的所有交互,并且在下拉菜单之中显示
const
cards
=
cardStore
.
at
(
card
.
location
.
zone
,
card
.
location
.
controller
);
handleDropdownMenu
(
cards
,
true
);
};
// >>> 下拉菜单:点击动作 >>>
interface
Interactivy
{
desc
:
string
;
...
...
@@ -233,11 +342,10 @@ interface Interactivy {
type
DropdownItem
=
NonNullable
<
MenuProps
[
"
items
"
]
>
[
number
]
&
{
onClick
:
()
=>
void
;
};
const
dropdownMenu
=
proxy
({
value
:
[]
as
DropdownItem
[]
});
const
handleEffectActivation
=
(
effectInteractivies
:
Interactivy
[],
meta
?:
any
// FIXME: meta的类型
meta
?:
CardMeta
)
=>
{
if
(
!
effectInteractivies
.
length
)
return
;
else
if
(
effectInteractivies
.
length
===
1
)
{
...
...
@@ -259,103 +367,4 @@ const handleEffectActivation = (
}
};
// 发动效果
// 1. 下拉菜单里面选择[召唤 / 特殊召唤 /.../效果发动]
// 2. 如果是非效果发动,那么直接选择哪张卡(单张卡直接选择那张)
// 3. 如果是效果发动,那么选择哪张卡,然后选择效果
const
handleDropdownMenu
=
(
cards
:
CardType
[],
isField
:
boolean
)
=>
{
const
map
=
new
Map
<
Interactivity
<
number
>
[
"
interactType
"
],
CardType
[]
>
();
cards
.
forEach
((
card
)
=>
{
card
.
idleInteractivities
.
forEach
(({
interactType
})
=>
{
if
(
!
map
.
has
(
interactType
))
{
map
.
set
(
interactType
,
[]);
}
map
.
get
(
interactType
)?.
push
(
card
);
});
});
const
actions
=
[...
map
.
entries
()];
const
nonEffectActions
=
actions
.
filter
(
([
action
])
=>
action
!==
InteractType
.
ACTIVATE
);
const
getNonEffectResponse
=
(
action
:
InteractType
,
card
:
CardType
)
=>
card
.
idleInteractivities
.
find
((
item
)
=>
item
.
interactType
===
action
)
!
.
response
;
const
nonEffectItem
:
DropdownItem
[]
=
nonEffectActions
.
map
(
([
action
,
cards
],
key
)
=>
({
key
,
label
:
interactTypeToString
(
action
),
onClick
:
async
()
=>
{
if
(
!
isField
)
{
// 单卡: 直接召唤/特殊召唤/...
const
card
=
cards
[
0
];
sendSelectIdleCmdResponse
(
getNonEffectResponse
(
action
,
card
));
}
else
{
// 场地: 选择卡片
// TODO: hint
const
option
=
await
displaySimpleSelectCardsModal
({
selectables
:
cards
.
map
((
card
)
=>
({
meta
:
card
.
meta
,
location
:
card
.
location
,
response
:
getNonEffectResponse
(
action
,
card
),
})),
});
sendSelectIdleCmdResponse
(
option
[
0
].
response
!
);
}
},
})
);
const
hasEffect
=
cards
.
reduce
(
(
prev
,
acc
)
=>
[
...
prev
,
...
acc
.
idleInteractivities
.
filter
(
({
interactType
})
=>
interactType
===
InteractType
.
ACTIVATE
),
],
[]
as
Interactivity
<
number
>
[]
).
length
>
0
;
const
effectItem
:
DropdownItem
=
{
key
:
nonEffectItem
.
length
,
label
:
interactTypeToString
(
InteractType
.
ACTIVATE
),
onClick
:
async
()
=>
{
let
card
:
CardType
;
if
(
!
isField
)
{
// 单卡: 直接发动这个卡的效果
card
=
cards
[
0
];
}
else
{
// 场地: 选择卡片
// TODO: hint
const
option
=
await
displaySimpleSelectCardsModal
({
selectables
:
cards
// 过滤掉不能发效果的卡
.
filter
(
(
card
)
=>
card
.
idleInteractivities
.
find
(
({
interactType
})
=>
interactType
===
InteractType
.
ACTIVATE
)
!==
undefined
)
.
map
((
card
)
=>
({
meta
:
card
.
meta
,
location
:
card
.
location
,
card
,
})),
});
card
=
option
[
0
].
card
!
as
any
;
// 一定会有的,有输入则定有输出
}
// 选择发动哪个效果
handleEffectActivation
(
card
.
idleInteractivities
.
filter
(({
interactType
})
=>
interactType
===
InteractType
.
ACTIVATE
)
.
map
((
x
)
=>
({
desc
:
interactTypeToString
(
x
.
interactType
),
response
:
x
.
response
,
effectCode
:
x
.
activateIndex
,
})),
card
.
meta
);
},
};
dropdownMenu
.
value
=
nonEffectItem
;
hasEffect
&&
dropdownMenu
.
value
.
push
(
effectItem
);
};
// <<< 下拉菜单 <<<
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment