Commit fa6626f6 authored by timel's avatar timel

feat: popover

parent cfc75646
Pipeline #22952 passed with stages
in 12 minutes and 40 seconds
import { EventEmitter } from "eventemitter3";
import { v4 as v4uuid } from "uuid";
const eventEmitter = new EventEmitter();
export const eventEmitter = new EventEmitter();
export enum Task {
Move = "move",
Focus = "focus",
Attack = "attack",
Move = "move", // 卡片移动
Focus = "focus", // 卡片聚焦
Attack = "attack", // 卡片攻击
Mora = "mora", // 猜拳
Tp = "tp", // 选边
}
const getEnd = (task: Task) => `${task}-end`;
......
import { Button, Popover, Space } from "antd";
import { useState } from "react";
import { eventEmitter, Task } from "@/infra";
import { IconFont } from "../Shared";
export enum Mora {
Rock = "rock",
Scissors = "scissors",
Paper = "paper",
}
export enum Tp {
First = 1,
Second = 2,
}
export const MoraPopover: React.FC<React.PropsWithChildren> = ({
children,
}) => {
const [open, setOpen] = useState(false);
// 需要在mora的service之中,emit一个事件,让这个组件监听到,然后打开popover
eventEmitter.on(Task.Mora, () => {
setOpen(true);
});
const onClick = (result: Mora) => {
result; // 这里send猜拳的结果给服务器
setOpen(false);
};
const map = {
[Mora.Rock]: "石头",
[Mora.Scissors]: "剪刀",
[Mora.Paper]: "",
};
return (
<Popover
overlayStyle={{ backdropFilter: "blur(10px)" }}
content={
<Space>
{[Mora.Rock, Mora.Scissors, Mora.Paper].map((mora) => (
<Button
key={mora}
size="large"
type="text"
icon={<IconFont type={`icon-hand-${mora}`} size={16} />}
onClick={() => onClick(mora)}
>
{map[mora]}
</Button>
))}
</Space>
}
open={open}
placement="bottom"
>
{children}
</Popover>
);
};
export const TpPopover: React.FC<React.PropsWithChildren> = ({ children }) => {
const [open, setOpen] = useState(false);
// 需要在mora的service之中,emit一个事件,让这个组件监听到,然后打开popover
eventEmitter.on(Task.Tp, () => {
setOpen(true);
});
const onClick = (result: Tp) => {
result; // 这里send结果给服务器
setOpen(false);
};
const map = {
[Tp.First]: "先手",
[Tp.Second]: "后手",
};
return (
<Popover
overlayStyle={{ backdropFilter: "blur(10px)" }}
content={
<Space>
{[Tp.First, Tp.Second].map((item) => (
<Button
key={item}
size="large"
type="text"
icon={
<IconFont
type={`icon-${item === Tp.First ? "one" : "two"}`}
size={16}
/>
}
onClick={() => onClick(item)}
>
{map[item]}
</Button>
))}
</Space>
}
open={open}
placement="bottom"
>
{children}
</Popover>
);
};
import { CheckCircleFilled, LoadingOutlined } from "@ant-design/icons";
import { CheckCircleFilled } from "@ant-design/icons";
import {
sendHsNotReady,
......@@ -11,25 +11,19 @@ import {
import socketMiddleWare, { socketCmd } from "@/middleware/socket";
import PlayerState = ygopro.StocHsPlayerChange.State;
import SelfType = ygopro.StocTypeChange.SelfType;
import { Avatar, Button, ConfigProvider, Popover, Skeleton, Space } from "antd";
import { Avatar, Button, ConfigProvider, Skeleton, Space } from "antd";
import classNames from "classnames";
import { forwardRef, useImperativeHandle, useRef, useState } from "react";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import { useSnapshot } from "valtio";
import { useConfig } from "@/config";
import {
accountStore,
deckStore,
IDeck,
Player,
roomStore,
type RoomStage,
} from "@/stores";
import { accountStore, deckStore, IDeck, Player, roomStore } from "@/stores";
import { Background, IconFont, Select, SpecialButton } from "@/ui/Shared";
import { Chat } from "./Chat";
import styles from "./index.module.scss";
import { MoraPopover, TpPopover } from "./Popover";
const NeosConfig = useConfig();
......@@ -55,11 +49,6 @@ export const Component: React.FC = () => {
const { decks } = useSnapshot(deckStore);
const [deck, setDeck] = useState<IDeck>(JSON.parse(JSON.stringify(decks[0])));
const room = useSnapshot(roomStore);
// ref.current?.getMoraResult(); // 用这个来异步获取猜拳结果
const onClick = async () => {
// console.log(await ref.current?.getMoraResult());
};
return (
<ConfigProvider theme={theme}>
......@@ -115,7 +104,6 @@ export const Component: React.FC = () => {
? "决斗准备"
: "取消准备"}
</Button>
{/* <MoraButton ref={ref} /> */}
</>
}
/>
......@@ -129,106 +117,12 @@ export const Component: React.FC = () => {
);
};
enum Mora {
Rock = "rock",
Scissors = "scissors",
Paper = "paper",
}
interface MoraButtonRef {
getMoraResult: () => Promise<Mora>;
}
const MoraPopover = forwardRef<MoraButtonRef, React.PropsWithChildren>(
({ children }, ref) => {
const [open, setOpen] = useState(false);
const resolve = useRef<(mora: Mora) => void>(() => {});
useImperativeHandle(ref, () => ({
async getMoraResult() {
setOpen(true);
const result = await new Promise<Mora>((rs) => (resolve.current = rs));
setOpen(false);
return result;
},
}));
const onMoraClick = (mora: Mora) => resolve.current(mora);
const map = {
[Mora.Rock]: "石头",
[Mora.Scissors]: "剪刀",
[Mora.Paper]: "",
};
return (
<Popover
overlayStyle={{ backdropFilter: "blur(10px)" }}
content={
<Space>
{[Mora.Rock, Mora.Scissors, Mora.Paper].map((mora) => (
<Button
key={mora}
size="large"
type="text"
icon={<IconFont type={`icon-hand-${mora}`} size={16} />}
onClick={() => onMoraClick(mora)}
>
{map[mora]}
</Button>
))}
</Space>
}
open={open}
placement="bottom"
>
{children}
</Popover>
);
}
);
const OrderPopup: React.FC<React.PropsWithChildren<{ open: boolean }>> = ({
children,
open,
}) => {
return (
<Popover
overlayStyle={{ backdropFilter: "blur(10px)" }}
open={open}
content={
<Space>
<Button
size="large"
type="text"
icon={<IconFont type="icon-one" size={18} />}
>
先手
</Button>
<Button
size="large"
type="text"
icon={<IconFont type="icon-two" size={18} />}
>
后手
</Button>
</Space>
}
trigger="focus"
placement="bottom"
>
{children}
</Popover>
);
};
enum Who {
Me = "me",
Op = "op",
}
// 玩家区域: 两侧各有一个
// 玩家区域: 双方各有一个
const PlayerZone: React.FC<{
btn?: React.ReactNode; // 在内部右侧可以放一个按钮
who?: Who;
......@@ -238,23 +132,21 @@ const PlayerZone: React.FC<{
return (
<div className={classNames(styles["side-box"], who && styles[who])}>
<div className={styles.inner}></div>
<OrderPopup open={false}>
<div style={{ position: "relative" }}>
<Avatar
src={
avatar && player
? avatar
: player && player.state != PlayerState.LEAVE
? `${NeosConfig.assetsPath}/default-avatar.png`
: ""
}
size={48}
/>
{player?.state === PlayerState.READY && (
<CheckCircleFilled className={styles.check} />
)}
</div>
</OrderPopup>
<div style={{ position: "relative" }}>
<Avatar
src={
avatar && player
? avatar
: player && player.state != PlayerState.LEAVE
? `${NeosConfig.assetsPath}/default-avatar.png`
: ""
}
size={48}
/>
{player?.state === PlayerState.READY && (
<CheckCircleFilled className={styles.check} />
)}
</div>
<div className={styles.name}>
{player && player.state != PlayerState.LEAVE ? (
player.name
......@@ -354,33 +246,34 @@ const SideButtons: React.FC<{
};
const ActionButton: React.FC = () => {
const ref = useRef<MoraButtonRef>(null);
return (
<MoraPopover ref={ref}>
<SpecialButton className={styles["btns-action"]} disabled={false}>
<>
<IconFont type="icon-play" size={12} />
开始游戏
</>
{/* <>
<MoraPopover>
<TpPopover>
<SpecialButton className={styles["btns-action"]} disabled={false}>
<>
<IconFont type="icon-play" size={12} />
开始游戏
</>
{/* <>
<IconFont type="icon-mora" size={18} />
<span>请猜拳</span>
</> */}
<>
{/* 这里要把disabled设为true */}
{/* <LoadingOutlined size={20} />
<>
{/* 这里要把disabled设为true */}
{/* <LoadingOutlined size={20} />
<span>等待对方猜拳</span> */}
</>
{/* <>
</>
{/* <>
<IconFont type="icon-one" size={18} />
<span>请选择先后手</span>
</> */}
<>
{/* 这里要把disabled设为true */}
{/* <LoadingOutlined size={20} />
<>
{/* 这里要把disabled设为true */}
{/* <LoadingOutlined size={20} />
<span>等待选择先后手</span> */}
</>
</SpecialButton>
</>
</SpecialButton>
</TpPopover>
</MoraPopover>
);
};
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