Commit e09a99cf authored by Chunchi Che's avatar Chunchi Che

merge OptionModal and AnnounceModal

parent f6d69df9
Pipeline #23303 passed with stages
in 11 minutes and 4 seconds
import { fetchCard, fetchStrings, Region, ygopro } from "@/api";
import { displayAnnounceModal } from "@/ui/Duel/Message";
import { displayOptionModal } from "@/ui/Duel/Message";
import MsgAnnounce = ygopro.StocGameMessage.MsgAnnounce;
export default async (announce: MsgAnnounce) => {
......@@ -14,26 +14,26 @@ export default async (announce: MsgAnnounce) => {
switch (type_) {
case MsgAnnounce.AnnounceType.RACE: {
await displayAnnounceModal({
min,
title: fetchStrings(Region.System, 563),
options: announce.options.map((option) => ({
await displayOptionModal(
fetchStrings(Region.System, 563),
announce.options.map((option) => ({
info: fetchStrings(Region.System, 1200 + option.code),
response: option.response,
})),
});
min,
);
break;
}
case MsgAnnounce.AnnounceType.Attribute: {
await displayAnnounceModal({
min,
title: fetchStrings(Region.System, 562),
options: announce.options.map((option) => ({
await displayOptionModal(
fetchStrings(Region.System, 562),
announce.options.map((option) => ({
info: fetchStrings(Region.System, 1010 + option.code),
response: option.response,
})),
});
min,
);
break;
}
......@@ -48,23 +48,19 @@ export default async (announce: MsgAnnounce) => {
});
}
}
await displayAnnounceModal({
min,
title: fetchStrings(Region.System, 564),
options,
});
await displayOptionModal(fetchStrings(Region.System, 564), options, min);
break;
}
case MsgAnnounce.AnnounceType.Number: {
await displayAnnounceModal({
min,
title: fetchStrings(Region.System, 565),
options: announce.options.map((option) => ({
await displayOptionModal(
fetchStrings(Region.System, 565),
announce.options.map((option) => ({
info: option.code.toString(),
response: option.response,
})),
});
min,
);
break;
}
......
......@@ -5,9 +5,13 @@ export default async (mora: ygopro.StocGameMessage.MsgRockPaperScissors) => {
const _player = mora.player;
// TODO: I18n
await displayOptionModal("请选择猜拳", [
{ msg: "剪刀", response: 1 },
{ msg: "石头", response: 2 },
{ msg: "", response: 3 },
]);
await displayOptionModal(
"请选择猜拳",
[
{ info: "剪刀", response: 1 },
{ info: "石头", response: 2 },
{ info: "", response: 3 },
],
1,
);
};
......@@ -14,9 +14,10 @@ export default async (selectOption: ygopro.StocGameMessage.MsgSelectOption) => {
await Promise.all(
options.map(async ({ code, response }) => {
const meta = fetchCard(code >> 4);
const msg = getCardStr(meta, code & 0xf) ?? "[?]";
return { msg, response };
const info = getCardStr(meta, code & 0xf) ?? "[?]";
return { info, response };
}),
),
1,
);
};
......@@ -6,7 +6,6 @@ import { SideStage, sideStore } from "@/stores";
import {
Alert,
AnnounceModal,
CardListModal,
CardModal,
CheckCounterModal,
......@@ -48,7 +47,6 @@ export const Component: React.FC = () => {
<OptionModal />
<CheckCounterModal />
<SortCardModal />
<AnnounceModal />
<SimpleSelectCardsModal />
<EndModal />
</>
......
import { CheckCard } from "@ant-design/pro-components";
import { Button } from "antd";
import React, { useState } from "react";
import { proxy, useSnapshot } from "valtio";
import { sendSelectOptionResponse } from "@/api";
import { NeosModal } from "./NeosModal";
interface AnnounceModalProps {
isOpen: boolean;
title?: string;
min: number;
options: {
info: string;
response: number;
}[];
}
const defaultProps = {
isOpen: false,
min: 1,
options: [],
};
const localStore = proxy<AnnounceModalProps>(defaultProps);
export const AnnounceModal = () => {
const { isOpen, title, min, options } = useSnapshot(localStore);
const [selected, setSelected] = useState<number[]>([]);
return (
<NeosModal
title={title}
open={isOpen}
footer={
<Button
disabled={selected.length !== min}
onClick={() => {
let response = selected.reduce((res, current) => res | current, 0); // 多个选择求或
sendSelectOptionResponse(response);
rs();
}}
>
submit
</Button>
}
>
<CheckCard.Group
bordered
multiple
size="small"
onChange={(value: any) => {
setSelected(value);
}}
>
{options.map((option, idx) => (
<CheckCard key={idx} title={option.info} value={option.response} />
))}
</CheckCard.Group>
</NeosModal>
);
};
let rs: (arg?: any) => void = () => {};
export const displayAnnounceModal = async (
args: Omit<AnnounceModalProps, "isOpen">,
) => {
Object.entries(args).forEach(([key, value]) => {
// @ts-ignore
localStore[key] = value;
});
localStore.isOpen = true;
await new Promise<void>((resolve) => (rs = resolve)); // 等待在组件内resolve
localStore.isOpen = false;
localStore.min = 1;
localStore.options = [];
localStore.title = undefined;
};
import { CheckCard } from "@ant-design/pro-components";
import { Button, Segmented } from "antd";
import { chunk } from "lodash-es";
import React, { useState } from "react";
import { proxy, useSnapshot } from "valtio";
......@@ -14,11 +15,12 @@ import {
import { NeosModal } from "./NeosModal";
type Options = { msg: string; response: number }[];
type Options = { info: string; response: number }[];
const defaultStore = {
title: "",
isOpen: false,
min: 1,
options: [] satisfies Options as Options,
};
const store = proxy(defaultStore);
......@@ -28,15 +30,20 @@ const MAX_NUM_PER_PAGE = 4;
export const OptionModal = () => {
const snap = useSnapshot(store);
const { title, isOpen, options } = snap;
const [selected, setSelected] = useState<number | undefined>(undefined);
const { title, isOpen, min, options } = snap;
// options可能太多,因此分页展示
const [page, setPage] = useState(0);
const maxPage = Math.ceil(options.length / MAX_NUM_PER_PAGE);
const [selecteds, setSelecteds] = useState<number[][]>(
Array.from({ length: maxPage }).map((_) => []),
);
const grouped = chunk(options, MAX_NUM_PER_PAGE);
const onSummit = () => {
if (selected !== undefined) {
sendSelectOptionResponse(selected);
const responses = selecteds.flat();
if (responses.length > 0) {
const response = responses.reduce((res, current) => res | current, 0); // 多个选择求或
sendSelectOptionResponse(response);
rs();
}
};
......@@ -46,35 +53,45 @@ export const OptionModal = () => {
title={title}
open={isOpen}
footer={
<Button disabled={selected === undefined} onClick={onSummit}>
<Button disabled={selecteds.flat().length !== min} onClick={onSummit}>
确定
</Button>
}
>
<Selector page={page} maxPage={maxPage} onChange={setPage as any} />
<CheckCard.Group
bordered
style={{
display: "grid",
gridTemplateColumns: "repeat(2, 1fr)",
gap: "10px",
}}
onChange={setSelected as any}
>
{options
.slice(
page * MAX_NUM_PER_PAGE,
Math.min((page + 1) * MAX_NUM_PER_PAGE, options.length),
)
.map((option, idx) => (
<CheckCard
key={idx}
style={{ width: "200px", marginInlineEnd: 0, marginBlockEnd: 0 }}
title={option.msg}
value={option.response}
/>
))}
</CheckCard.Group>
{grouped.map(
(options, i) =>
i === page && (
<CheckCard.Group
key={i}
bordered
multiple
value={selecteds[i]}
style={{
display: "grid",
gridTemplateColumns: "repeat(2, 1fr)",
gap: "10px",
}}
onChange={(values: any) => {
const v = selecteds.map((x, i) => (i === page ? values : x));
setSelecteds(v);
}}
>
{options.map((option, idx) => (
<CheckCard
key={idx}
style={{
width: "200px",
marginInlineEnd: 0,
marginBlockEnd: 0,
}}
title={option.info}
value={option.response}
/>
))}
</CheckCard.Group>
),
)}
</NeosModal>
);
};
......@@ -98,9 +115,14 @@ const Selector: React.FC<{
);
let rs: (v?: any) => void = () => {};
export const displayOptionModal = async (title: string, options: Options) => {
export const displayOptionModal = async (
title: string,
options: Options,
min: number,
) => {
store.title = title;
store.options = options;
store.min = min;
store.isOpen = true;
await new Promise((resolve) => (rs = resolve));
store.isOpen = false;
......@@ -128,10 +150,10 @@ export const handleEffectActivation = async (
? getCardStr(meta, effect.effectCode & 0xf) ?? "[:?]"
: "[:?]";
return {
msg: effectMsg,
info: effectMsg,
response: effect.response,
};
});
await displayOptionModal(fetchStrings(Region.System, 556), options); // 主动发动效果,所以不需要await,但是以后可能要留心
await displayOptionModal(fetchStrings(Region.System, 556), options, 1); // 主动发动效果,所以不需要await,但是以后可能要留心
}
};
export * from "./Alert";
export * from "./AnnounceModal";
export * from "./CardListModal";
export * from "./CardModal";
export * from "./CheckCounterModal";
......
......@@ -351,11 +351,11 @@ const handleEffectActivation = (
? getCardStr(meta, effect.effectCode & 0xf) ?? "[:?]"
: "[:?]";
return {
msg: effectMsg,
info: effectMsg,
response: effect.response,
};
});
displayOptionModal(fetchStrings(Region.System, 556), options); // 主动发动效果,所以不需要await,但是以后可能要留心
displayOptionModal(fetchStrings(Region.System, 556), options, 1); // 主动发动效果,所以不需要await,但是以后可能要留心
}
};
......
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