Commit e200d3c7 authored by timel's avatar timel Committed by Chunchi Che

feat: waiting msg, card dropdown menu

parent 2a1217db
......@@ -53,6 +53,8 @@ import onMsgUpdateHp from "./updateHp";
import onMsgWait from "./wait";
import onMsgWin from "./win";
import { showWaiting } from "@/ui/Duel/Message";
const ActiveList = [
"select_idle_cmd",
"select_place",
......@@ -77,7 +79,7 @@ async function _handleGameMsg(pb: ygopro.YgoStocMsg) {
const msg = pb.stoc_game_msg;
if (ActiveList.includes(msg.gameMsg)) {
matStore.waiting = false;
showWaiting(false);
}
switch (msg.gameMsg) {
......
import { ygopro } from "@/api";
import { cardStore, matStore } from "@/stores";
import { showWaiting } from "@/ui/Duel/Message";
export default (_wait: ygopro.StocGameMessage.MsgWait) => {
for (const card of cardStore.inner) {
card.idleInteractivities = [];
}
matStore.waiting = true;
showWaiting(true);
};
......@@ -33,8 +33,6 @@ export interface MatState {
reason: string;
};
waiting: boolean;
unimplemented: number; // 未处理的`Message`
tossResult?: string; // 骰子/硬币结果
......
.card-modal-desc {
line-height: 1.6;
font-size: 15px;
font-size: 14px;
font-family: var(--theme-font);
max-height: calc(100% - 237px);
overflow-y: overlay;
......
......@@ -79,6 +79,7 @@ export const CardModal = () => {
mask={false}
title={name}
closeIcon={<LeftOutlined />}
width={350}
>
<div className="card-modal-container">
<Space
......
import { notification } from "antd";
import { notification, message } from "antd";
import React, { useEffect } from "react";
import { useSnapshot } from "valtio";
......@@ -14,21 +14,27 @@ const style = {
};
const NeosConfig = useConfig();
let globalMsgApi: ReturnType<typeof message.useMessage>[0] | undefined;
export const HintNotification = () => {
const snap = useSnapshot(matStore);
const hintState = snap.hint;
const toss = snap.tossResult;
const currentPhase = snap.phase.currentPhase;
const waiting = snap.waiting;
// const waiting = snap.waiting;
const result = snap.result;
const [api, contextHolder] = notification.useNotification({
const [notify, notifyContextHolder] = notification.useNotification({
maxCount: NeosConfig.ui.hint.maxCount,
});
const [msgApi, msgContextHolder] = message.useMessage({
maxCount: NeosConfig.ui.hint.maxCount,
});
globalMsgApi = msgApi;
useEffect(() => {
if (hintState && hintState.msg) {
api.open({
notify.open({
message: `${hintState.msg}`,
placement: "topLeft",
style: style,
......@@ -38,7 +44,7 @@ export const HintNotification = () => {
useEffect(() => {
if (toss) {
api.open({
notify.open({
message: `${toss}`,
placement: "topLeft",
style: style,
......@@ -52,7 +58,7 @@ export const HintNotification = () => {
"!system",
Phase2StringCodeMap.get(currentPhase) ?? 0
);
api.open({
notify.open({
message,
placement: "topRight",
style: style,
......@@ -63,21 +69,10 @@ export const HintNotification = () => {
}
}, [currentPhase]);
useEffect(() => {
if (waiting) {
api.open({
message: fetchStrings("!system", 1390),
placement: "top",
duration: NeosConfig.ui.hint.waitingDuration,
style: style,
});
}
}, [waiting]);
useEffect(() => {
if (result) {
const message = result.isWin ? "Win" : "Defeated" + " " + result.reason;
api.open({
notify.open({
message,
placement: "bottom",
style: style,
......@@ -85,5 +80,36 @@ export const HintNotification = () => {
}
}, [result]);
return <>{contextHolder}</>;
return (
<>
{notifyContextHolder}
{msgContextHolder}
</>
);
};
// 防抖的waiting msg
let isWaiting = false;
let destoryTimer: NodeJS.Timeout | undefined;
const waitingKey = "waiting";
export const showWaiting = (open: boolean) => {
if (open) {
if (!isWaiting) {
globalMsgApi?.open({
type: "loading",
content: fetchStrings("!system", 1390),
key: waitingKey,
});
clearTimeout(destoryTimer);
isWaiting = true;
destoryTimer = undefined;
}
} else {
if (!destoryTimer) {
destoryTimer = setTimeout(() => {
globalMsgApi?.destroy(waitingKey);
isWaiting = false;
}, 1000);
}
}
};
......@@ -18,7 +18,6 @@ section#mat {
transition: 0.2s scale;
cursor: pointer;
&:hover {
scale: 1.05;
}
.card-cover,
.card-back {
......@@ -113,3 +112,9 @@ section#mat {
filter: brightness(1) contrast(1);
}
}
.card-dropdown {
.ant-dropdown-menu {
background-color: #333;
}
}
......@@ -23,6 +23,14 @@ import type { SpringApiProps } from "./springs/types";
import { YgoCard } from "@/ui/Shared";
import { showCardModal } from "@/ui/Duel/Message/CardModal";
import { Button, Dropdown } from "antd";
import {
UploadOutlined,
DownloadOutlined,
UpOutlined,
} from "@ant-design/icons";
const NeosConfig = useConfig();
const { HAND, GRAVE, REMOVED, DECK, EXTRA, MZONE, SZONE, TZONE } =
......@@ -130,7 +138,20 @@ export const Card: FC<{ idx: number }> = React.memo(({ idx }) => {
useEffect(() => {
setHighlight(!!idleInteractivities.length);
}, [idleInteractivities]);
const items = [
{
key: "1",
label: "正面攻表召唤",
},
{
key: "2",
label: "反面守表召唤",
},
{
key: "3",
label: "效果发动",
},
];
return (
<animated.div
className="mat-card"
......@@ -160,13 +181,21 @@ export const Card: FC<{ idx: number }> = React.memo(({ idx }) => {
>
<div className="card-focus" />
<div className="card-shadow" />
<div className={classnames("card-img-wrap", { focus: classFocus })}>
<YgoCard
className={classnames("card-cover")}
code={snap.code === 0 ? snap.meta.id : snap.code}
/>
<YgoCard className="card-back" isBack />
</div>
<Dropdown
menu={{ items }}
placement="bottom"
overlayClassName="card-dropdown"
arrow={{ pointAtCenter: true }}
trigger={["click"]}
>
<div className={classnames("card-img-wrap", { focus: classFocus })}>
<YgoCard
className={classnames("card-cover")}
code={snap.code === 0 ? snap.meta.id : snap.code}
/>
<YgoCard className="card-back" isBack />
</div>
</Dropdown>
{snap.selected ? <div className="card-streamer" /> : <></>}
</animated.div>
);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment