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