Commit 9511809e authored by Chunchi Che's avatar Chunchi Che

Merge branch 'feat/dragmodal' into 'main'

Feat/dragmodal

See merge request !157
parents 40fa8d97 869449bf
...@@ -13,15 +13,14 @@ import { ...@@ -13,15 +13,14 @@ import {
resetCheckCardModal, resetCheckCardModal,
setCheckCardModalIsOpen, setCheckCardModalIsOpen,
} from "../../reducers/duel/mod"; } from "../../reducers/duel/mod";
import { Modal, Button, Row, Col, Popover } from "antd"; import { Button, Row, Col, Popover } from "antd";
import { CheckCard } from "@ant-design/pro-components"; import { CheckCard } from "@ant-design/pro-components";
import { import {
sendSelectCardResponse, sendSelectCardResponse,
sendSelectChainResponse, sendSelectChainResponse,
} from "../../api/ocgcore/ocgHelper"; } from "../../api/ocgcore/ocgHelper";
import type { DraggableData, DraggableEvent } from "react-draggable";
import Draggable from "react-draggable";
import NeosConfig from "../../../neos.config.json"; import NeosConfig from "../../../neos.config.json";
import DragModal from "./dragModal";
const CheckCardModal = () => { const CheckCardModal = () => {
const dispatch = store.dispatch; const dispatch = store.dispatch;
...@@ -33,30 +32,10 @@ const CheckCardModal = () => { ...@@ -33,30 +32,10 @@ const CheckCardModal = () => {
const cancelResponse = useAppSelector(selectCheckCardModalCacnelResponse); const cancelResponse = useAppSelector(selectCheckCardModalCacnelResponse);
const [response, setResponse] = useState<number[]>([]); const [response, setResponse] = useState<number[]>([]);
const defaultValue: number[] = []; const defaultValue: number[] = [];
// Draggable 相关 // Draggable 相关
const [draggable, setDraggable] = useState(false); const [draggable, setDraggable] = useState(false);
const [bounds, setBounds] = useState({
left: 0,
top: 0,
bottom: 0,
right: 0,
});
const draggleRef = useRef<HTMLDivElement>(null); const draggleRef = useRef<HTMLDivElement>(null);
const onStart = (_event: DraggableEvent, uiData: DraggableData) => {
const { clientWidth, clientHeight } = window.document.documentElement;
const targetRect = draggleRef.current?.getBoundingClientRect();
if (!targetRect) {
return;
}
setBounds({
left: -targetRect.left + uiData.x,
right: clientWidth - (targetRect.right - uiData.x),
top: -targetRect.top + uiData.y,
bottom: clientHeight - (targetRect.bottom - uiData.y),
});
};
const onMouseOver = () => { const onMouseOver = () => {
if (draggable) { if (draggable) {
setDraggable(false); setDraggable(false);
...@@ -65,7 +44,6 @@ const CheckCardModal = () => { ...@@ -65,7 +44,6 @@ const CheckCardModal = () => {
const onMouseOut = () => { const onMouseOut = () => {
setDraggable(true); setDraggable(true);
}; };
// TODO: 这里可以考虑更好地封装 // TODO: 这里可以考虑更好地封装
const sendResponseHandler = ( const sendResponseHandler = (
handlerName: string | undefined, handlerName: string | undefined,
...@@ -86,32 +64,17 @@ const CheckCardModal = () => { ...@@ -86,32 +64,17 @@ const CheckCardModal = () => {
}; };
return ( return (
<Modal <DragModal
title={`请选择${min}到${max}张卡片`} modalProps={{
open={isOpen} title: `请选择${min}到${max}张卡片`,
closable={false} open: isOpen,
footer={ closable: false,
<> footer: (
<Button <>
disabled={response.length < min || response.length > max}
onClick={() => {
sendResponseHandler(onSubmit, response);
dispatch(setCheckCardModalIsOpen(false));
dispatch(resetCheckCardModal());
}}
onMouseOver={onMouseOver}
onMouseOut={onMouseOut}
onFocus={() => {}}
onBlur={() => {}}
>
submit
</Button>
{cancelAble ? (
<Button <Button
disabled={response.length < min || response.length > max}
onClick={() => { onClick={() => {
if (cancelResponse) { sendResponseHandler(onSubmit, response);
sendResponseHandler(onSubmit, [cancelResponse]);
}
dispatch(setCheckCardModalIsOpen(false)); dispatch(setCheckCardModalIsOpen(false));
dispatch(resetCheckCardModal()); dispatch(resetCheckCardModal());
}} }}
...@@ -120,19 +83,33 @@ const CheckCardModal = () => { ...@@ -120,19 +83,33 @@ const CheckCardModal = () => {
onFocus={() => {}} onFocus={() => {}}
onBlur={() => {}} onBlur={() => {}}
> >
cancel submit
</Button> </Button>
) : ( {cancelAble ? (
<></> <Button
)} onClick={() => {
</> if (cancelResponse) {
} sendResponseHandler(onSubmit, [cancelResponse]);
modalRender={(modal) => ( }
<Draggable disabled={!draggable} bounds={bounds} onStart={onStart}> dispatch(setCheckCardModalIsOpen(false));
<div ref={draggleRef}>{modal}</div> dispatch(resetCheckCardModal());
</Draggable> }}
)} onMouseOver={onMouseOver}
width={800} onMouseOut={onMouseOut}
onFocus={() => {}}
onBlur={() => {}}
>
cancel
</Button>
) : (
<></>
)}
</>
),
width: 800,
}}
dragRef={draggleRef}
draggable={draggable}
> >
<CheckCard.Group <CheckCard.Group
multiple multiple
...@@ -181,7 +158,7 @@ const CheckCardModal = () => { ...@@ -181,7 +158,7 @@ const CheckCardModal = () => {
); );
})} })}
</CheckCard.Group> </CheckCard.Group>
</Modal> </DragModal>
); );
}; };
......
import React from "react"; import React, { useRef, useState } from "react";
import { useAppSelector } from "../../hook"; import { useAppSelector } from "../../hook";
import { store } from "../../store"; import { store } from "../../store";
import { Modal, Button, Card, Row, Col } from "antd"; import { Button, Card, Row, Col } from "antd";
import { CheckCard } from "@ant-design/pro-components"; import { CheckCard } from "@ant-design/pro-components";
import { import {
selectCheckCardModalV2CancelAble, selectCheckCardModalV2CancelAble,
...@@ -19,6 +19,7 @@ import { ...@@ -19,6 +19,7 @@ import {
setCheckCardModalV2ResponseAble, setCheckCardModalV2ResponseAble,
} from "../../reducers/duel/mod"; } from "../../reducers/duel/mod";
import NeosConfig from "../../../neos.config.json"; import NeosConfig from "../../../neos.config.json";
import DragModal from "./dragModal";
const CheckCardModalV2 = () => { const CheckCardModalV2 = () => {
const dispatch = store.dispatch; const dispatch = store.dispatch;
...@@ -31,35 +32,59 @@ const CheckCardModalV2 = () => { ...@@ -31,35 +32,59 @@ const CheckCardModalV2 = () => {
); );
const selectedOptions = useAppSelector(selectCheckCardModalV2SelectedOptions); const selectedOptions = useAppSelector(selectCheckCardModalV2SelectedOptions);
const responseable = useAppSelector(selectCheckCardModalV2ResponseAble); const responseable = useAppSelector(selectCheckCardModalV2ResponseAble);
// Draggable 相关
const [draggable, setDraggable] = useState(false);
const draggleRef = useRef<HTMLDivElement>(null);
const onMouseOver = () => {
if (draggable) {
setDraggable(false);
}
};
const onMouseOut = () => {
setDraggable(true);
};
const onFinish = () => { const onFinish = () => {
sendSelectUnselectCardResponse({ cancel_or_finish: true }); sendSelectUnselectCardResponse({ cancel_or_finish: true });
dispatch(setCheckCardModalV2IsOpen(false)); dispatch(setCheckCardModalV2IsOpen(false));
dispatch(resetCheckCardModalV2()); dispatch(resetCheckCardModalV2());
dispatch(setCheckCardModalV2ResponseAble(false)); dispatch(setCheckCardModalV2ResponseAble(false));
}; };
const onCancel = () => { const onCancel = () => {
sendSelectUnselectCardResponse({ cancel_or_finish: true }); sendSelectUnselectCardResponse({ cancel_or_finish: true });
dispatch(setCheckCardModalV2ResponseAble(false)); dispatch(setCheckCardModalV2ResponseAble(false));
}; };
return ( return (
<Modal <DragModal
title={`请选择未选择的卡片,最少${min}张,最多${max}张`} modalProps={{
open={isOpen} title: `请选择未选择的卡片,最少${min}张,最多${max}张`,
closable={false} open: isOpen,
footer={ closable: false,
<> footer: (
<Button disabled={!finishable || !responseable} onClick={onFinish}> <>
finish <Button
</Button> disabled={!finishable || !responseable}
<Button disabled={!cancelable || !responseable} onClick={onCancel}> onClick={onFinish}
cancel onMouseOver={onMouseOver}
</Button> onMouseOut={onMouseOut}
</> >
} finish
width={800} </Button>
<Button
disabled={!cancelable || !responseable}
onClick={onCancel}
onMouseOver={onMouseOver}
onMouseOut={onMouseOut}
>
cancel
</Button>
</>
),
width: 800,
}}
dragRef={draggleRef}
draggable={draggable}
> >
<CheckCard.Group <CheckCard.Group
bordered bordered
...@@ -89,6 +114,8 @@ const CheckCardModalV2 = () => { ...@@ -89,6 +114,8 @@ const CheckCardModalV2 = () => {
/> />
} }
value={option.response} value={option.response}
onMouseEnter={onMouseOver}
onMouseLeave={onMouseOut}
/> />
</Col> </Col>
); );
...@@ -114,7 +141,7 @@ const CheckCardModalV2 = () => { ...@@ -114,7 +141,7 @@ const CheckCardModalV2 = () => {
); );
})} })}
</Row> </Row>
</Modal> </DragModal>
); );
}; };
......
import React, { useState } from "react"; import React, { useRef, useState } from "react";
import { useAppSelector } from "../../hook"; import { useAppSelector } from "../../hook";
import { store } from "../../store"; import { store } from "../../store";
import { Modal, Button, Card, Row, Col } from "antd"; import { Button, Card, Row, Col } from "antd";
import { CheckCard } from "@ant-design/pro-components"; import { CheckCard } from "@ant-design/pro-components";
import { sendSelectCardResponse } from "../../api/ocgcore/ocgHelper"; import { sendSelectCardResponse } from "../../api/ocgcore/ocgHelper";
import { import {
...@@ -11,6 +11,7 @@ import { ...@@ -11,6 +11,7 @@ import {
} from "../../reducers/duel/mod"; } from "../../reducers/duel/mod";
import NeosConfig from "../../../neos.config.json"; import NeosConfig from "../../../neos.config.json";
import { selectCheckCardModalV3 } from "../../reducers/duel/modal/checkCardModalV3Slice"; import { selectCheckCardModalV3 } from "../../reducers/duel/modal/checkCardModalV3Slice";
import DragModal from "./dragModal";
const CheckCardModalV3 = () => { const CheckCardModalV3 = () => {
const dispatch = store.dispatch; const dispatch = store.dispatch;
...@@ -31,14 +32,24 @@ const CheckCardModalV3 = () => { ...@@ -31,14 +32,24 @@ const CheckCardModalV3 = () => {
.concat(selectedOptions) .concat(selectedOptions)
.map((option) => option.level2) .map((option) => option.level2)
.reduce((sum, current) => sum + current, 0); .reduce((sum, current) => sum + current, 0);
// Draggable 相关
const [draggable, setDraggable] = useState(false);
const draggleRef = useRef<HTMLDivElement>(null);
const onMouseOver = () => {
if (draggable) {
setDraggable(false);
}
};
const onMouseOut = () => {
setDraggable(true);
};
const responseable = const responseable =
(overflow (overflow
? Level1Sum >= LevelSum || Level2Sum >= LevelSum ? Level1Sum >= LevelSum || Level2Sum >= LevelSum
: Level1Sum == LevelSum || Level2Sum == LevelSum) && : Level1Sum == LevelSum || Level2Sum == LevelSum) &&
selectedOptions.length <= max && selectedOptions.length <= max &&
selectedOptions.length >= min; selectedOptions.length >= min;
const onFinish = () => { const onFinish = () => {
sendSelectCardResponse( sendSelectCardResponse(
mustSelectOptions.concat(selectedOptions).map((option) => option.response) mustSelectOptions.concat(selectedOptions).map((option) => option.response)
...@@ -49,18 +60,27 @@ const CheckCardModalV3 = () => { ...@@ -49,18 +60,27 @@ const CheckCardModalV3 = () => {
}; };
return ( return (
<Modal <DragModal
title={`请选择卡片,最少${min}张,最多${max}张`} modalProps={{
open={isOpen} title: `请选择卡片,最少${min}张,最多${max}张`,
closable={false} open: isOpen,
footer={ closable: false,
<> footer: (
<Button disabled={!responseable} onClick={onFinish}> <>
finish <Button
</Button> disabled={!responseable}
</> onClick={onFinish}
} onMouseOver={onMouseOver}
width={800} onMouseOut={onMouseOut}
>
finish
</Button>
</>
),
width: 800,
}}
dragRef={draggleRef}
draggable={draggable}
> >
<CheckCard.Group <CheckCard.Group
bordered bordered
...@@ -87,6 +107,8 @@ const CheckCardModalV3 = () => { ...@@ -87,6 +107,8 @@ const CheckCardModalV3 = () => {
/> />
} }
value={option} value={option}
onMouseEnter={onMouseOver}
onMouseLeave={onMouseOut}
/> />
</Col> </Col>
); );
...@@ -112,7 +134,7 @@ const CheckCardModalV3 = () => { ...@@ -112,7 +134,7 @@ const CheckCardModalV3 = () => {
); );
})} })}
</Row> </Row>
</Modal> </DragModal>
); );
}; };
......
// 经过封装的可拖拽`Modal`
import React, { useState } from "react";
import type { DraggableData, DraggableEvent } from "react-draggable";
import Draggable from "react-draggable";
import { Modal, ModalProps } from "antd";
export interface DragModalProps {
modalProps: ModalProps;
dragRef: React.RefObject<HTMLDivElement>;
draggable: boolean;
children?: React.ReactNode;
}
const DragModal = (props: DragModalProps) => {
const [bounds, setBounds] = useState({
left: 0,
top: 0,
bottom: 0,
right: 0,
});
const onStart = (_event: DraggableEvent, uiData: DraggableData) => {
const { clientWidth, clientHeight } = window.document.documentElement;
const targetRect = props.dragRef.current?.getBoundingClientRect();
if (!targetRect) {
return;
}
setBounds({
left: -targetRect.left + uiData.x,
right: clientWidth - (targetRect.right - uiData.x),
top: -targetRect.top + uiData.y,
bottom: clientHeight - (targetRect.bottom - uiData.y),
});
};
return (
<Modal
{...props.modalProps}
modalRender={(modal) => (
<Draggable
disabled={!props.draggable}
bounds={bounds}
onStart={onStart}
>
<div ref={props.dragRef}>{modal}</div>
</Draggable>
)}
>
{props.children}
</Modal>
);
};
export default DragModal;
import React, { useState } from "react"; import React, { useRef, useState } from "react";
import { useAppSelector } from "../../hook"; import { useAppSelector } from "../../hook";
import { store } from "../../store"; import { store } from "../../store";
import { Modal, Button } from "antd"; import { Button } from "antd";
import { CheckCard } from "@ant-design/pro-components"; import { CheckCard } from "@ant-design/pro-components";
import { import {
selectOptionModalIsOpen, selectOptionModalIsOpen,
...@@ -12,32 +12,38 @@ import { ...@@ -12,32 +12,38 @@ import {
resetOptionModal, resetOptionModal,
setOptionModalIsOpen, setOptionModalIsOpen,
} from "../../reducers/duel/mod"; } from "../../reducers/duel/mod";
import DragModal from "./dragModal";
const OptionModal = () => { const OptionModal = () => {
const dispatch = store.dispatch; const dispatch = store.dispatch;
const isOpen = useAppSelector(selectOptionModalIsOpen); const isOpen = useAppSelector(selectOptionModalIsOpen);
const options = useAppSelector(selectOptionModalOptions); const options = useAppSelector(selectOptionModalOptions);
const [selected, setSelected] = useState<number | undefined>(undefined); const [selected, setSelected] = useState<number | undefined>(undefined);
const draggleRef = useRef<HTMLDivElement>(null);
return ( return (
<Modal <DragModal
title="请选择需要发动的效果" modalProps={{
open={isOpen} title: "请选择需要发动的效果",
closable={false} open: isOpen,
footer={ closable: false,
<Button footer: (
disabled={selected === undefined} <Button
onClick={() => { disabled={selected === undefined}
if (selected !== undefined) { onClick={() => {
sendSelectOptionResponse(selected); if (selected !== undefined) {
dispatch(setOptionModalIsOpen(false)); sendSelectOptionResponse(selected);
dispatch(resetOptionModal()); dispatch(setOptionModalIsOpen(false));
} dispatch(resetOptionModal());
}} }
> }}
submit >
</Button> submit
} </Button>
),
}}
dragRef={draggleRef}
draggable={true}
> >
<CheckCard.Group <CheckCard.Group
bordered bordered
...@@ -51,7 +57,7 @@ const OptionModal = () => { ...@@ -51,7 +57,7 @@ const OptionModal = () => {
<CheckCard key={idx} title={option.msg} value={option.response} /> <CheckCard key={idx} title={option.msg} value={option.response} />
))} ))}
</CheckCard.Group> </CheckCard.Group>
</Modal> </DragModal>
); );
}; };
......
import React, { useState } from "react"; import React, { useRef, useState } from "react";
import { useAppSelector } from "../../hook"; import { useAppSelector } from "../../hook";
import { store } from "../../store"; import { store } from "../../store";
import { Modal, Button } from "antd"; import { Button } from "antd";
import { sendSelectPositionResponse } from "../../api/ocgcore/ocgHelper"; import { sendSelectPositionResponse } from "../../api/ocgcore/ocgHelper";
import { import {
selectPositionModalIsOpen, selectPositionModalIsOpen,
...@@ -13,6 +13,7 @@ import { ...@@ -13,6 +13,7 @@ import {
setPositionModalIsOpen, setPositionModalIsOpen,
} from "../../reducers/duel/mod"; } from "../../reducers/duel/mod";
import { CheckCard } from "@ant-design/pro-components"; import { CheckCard } from "@ant-design/pro-components";
import DragModal from "./dragModal";
const PositionModal = () => { const PositionModal = () => {
const dispatch = store.dispatch; const dispatch = store.dispatch;
...@@ -21,26 +22,31 @@ const PositionModal = () => { ...@@ -21,26 +22,31 @@ const PositionModal = () => {
const [selected, setSelected] = useState<ygopro.CardPosition | undefined>( const [selected, setSelected] = useState<ygopro.CardPosition | undefined>(
undefined undefined
); );
const draggleRef = useRef<HTMLDivElement>(null);
return ( return (
<Modal <DragModal
title="请选择表示形式" modalProps={{
open={isOpen} title: "请选择表示形式",
closable={false} open: isOpen,
footer={ closable: false,
<Button footer: (
disabled={selected === undefined} <Button
onClick={() => { disabled={selected === undefined}
if (selected !== undefined) { onClick={() => {
sendSelectPositionResponse(selected); if (selected !== undefined) {
dispatch(setPositionModalIsOpen(false)); sendSelectPositionResponse(selected);
dispatch(resetPositionModal()); dispatch(setPositionModalIsOpen(false));
} dispatch(resetPositionModal());
}} }
> }}
submit >
</Button> submit
} </Button>
),
}}
dragRef={draggleRef}
draggable={true}
> >
<CheckCard.Group <CheckCard.Group
bordered bordered
...@@ -58,7 +64,7 @@ const PositionModal = () => { ...@@ -58,7 +64,7 @@ const PositionModal = () => {
/> />
))} ))}
</CheckCard.Group> </CheckCard.Group>
</Modal> </DragModal>
); );
}; };
......
import React from "react"; import React, { useRef } from "react";
import { useAppSelector } from "../../hook"; import { useAppSelector } from "../../hook";
import { store } from "../../store"; import { store } from "../../store";
import { Modal, Button } from "antd"; import { Button } from "antd";
import { sendSelectEffectYnResponse } from "../../api/ocgcore/ocgHelper"; import { sendSelectEffectYnResponse } from "../../api/ocgcore/ocgHelper";
import { import {
selectYesNoModalIsOpen, selectYesNoModalIsOpen,
selectYesNOModalMsg, selectYesNOModalMsg,
} from "../../reducers/duel/modal/mod"; } from "../../reducers/duel/modal/mod";
import { setYesNoModalIsOpen } from "../../reducers/duel/mod"; import { setYesNoModalIsOpen } from "../../reducers/duel/mod";
import DragModal from "./dragModal";
const YesNoModal = () => { const YesNoModal = () => {
const dispatch = store.dispatch; const dispatch = store.dispatch;
const isOpen = useAppSelector(selectYesNoModalIsOpen); const isOpen = useAppSelector(selectYesNoModalIsOpen);
const msg = useAppSelector(selectYesNOModalMsg); const msg = useAppSelector(selectYesNOModalMsg);
// Draggable 相关
const draggleRef = useRef<HTMLDivElement>(null);
return ( return (
<Modal <DragModal
title={msg} modalProps={{
open={isOpen} title: msg,
closable={false} open: isOpen,
footer={ closable: false,
<> footer: (
<Button <>
onClick={() => { <Button
sendSelectEffectYnResponse(true); onClick={() => {
dispatch(setYesNoModalIsOpen(false)); sendSelectEffectYnResponse(true);
}} dispatch(setYesNoModalIsOpen(false));
> }}
Yes >
</Button> Yes
<Button </Button>
onClick={() => { <Button
sendSelectEffectYnResponse(false); onClick={() => {
dispatch(setYesNoModalIsOpen(false)); sendSelectEffectYnResponse(false);
}} dispatch(setYesNoModalIsOpen(false));
> }}
No >
</Button> No
</> </Button>
} </>
),
}}
dragRef={draggleRef}
draggable={true}
/> />
); );
}; };
......
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