Commit 07eb4ed6 authored by Chunchi Che's avatar Chunchi Che

Merge branch 'feat/mouseEvent' into 'main'

feat: add mouse event on deck

See merge request mycard/Neos!296
parents 5ebda8bb c1c288c5
Pipeline #23380 passed with stages
in 13 minutes and 49 seconds
...@@ -13,6 +13,7 @@ import { ...@@ -13,6 +13,7 @@ import {
Dropdown, Dropdown,
Input, Input,
type MenuProps, type MenuProps,
message,
Pagination, Pagination,
Space, Space,
} from "antd"; } from "antd";
...@@ -26,12 +27,13 @@ import { proxy, useSnapshot } from "valtio"; ...@@ -26,12 +27,13 @@ import { proxy, useSnapshot } from "valtio";
import { subscribeKey } from "valtio/utils"; import { subscribeKey } from "valtio/utils";
import { type CardMeta, searchCards } from "@/api"; import { type CardMeta, searchCards } from "@/api";
import { isToken } from "@/common"; import { isExtraDeckCard, isToken } from "@/common";
import { FtsConditions } from "@/middleware/sqlite/fts"; import { FtsConditions } from "@/middleware/sqlite/fts";
import { deckStore, type IDeck, initStore } from "@/stores"; import { deckStore, type IDeck, initStore } from "@/stores";
import { import {
Background, Background,
DeckCard, DeckCard,
DeckCardMouseUpEvent,
DeckZone, DeckZone,
IconFont, IconFont,
Loading, Loading,
...@@ -159,6 +161,53 @@ export const DeckEditor: React.FC<{ ...@@ -159,6 +161,53 @@ export const DeckEditor: React.FC<{
useEffect(() => { useEffect(() => {
iDeckToEditingDeck(deck).then(editDeckStore.set); iDeckToEditingDeck(deck).then(editDeckStore.set);
}, [deck]); }, [deck]);
const handleSwitchCard = (type: Type, card: CardMeta) => {
const cardType = card.data.type ?? 0;
const isSide = type === "side";
const targetType = isSide
? isExtraDeckCard(cardType)
? "extra"
: "main"
: "side";
const { result, reason } = editDeckStore.canAdd(card, targetType, type);
if (result) {
editDeckStore.remove(type, card);
editDeckStore.add(targetType, card);
} else {
message.error(reason);
}
};
const showSelectedCard = (card: CardMeta) => {
selectedCard.id = card.id;
selectedCard.open = true;
};
const handleMouseUp = (
type: "main" | "extra" | "side",
payload: DeckCardMouseUpEvent,
) => {
const { event, card } = payload;
switch (event.button) {
// 左键
case 0:
showSelectedCard(card);
break;
// 中键
case 1:
handleSwitchCard(type, card);
break;
// 右键
case 2:
editDeckStore.remove(type, card);
break;
default:
break;
}
event.preventDefault();
};
return ( return (
<div className={styles.container}> <div className={styles.container}>
<Space className={styles.title}> <Space className={styles.title}>
...@@ -215,11 +264,7 @@ export const DeckEditor: React.FC<{ ...@@ -215,11 +264,7 @@ export const DeckEditor: React.FC<{
editDeckStore.remove(source, card); editDeckStore.remove(source, card);
} }
}} }}
onElementClick={(card) => { onElementMouseUp={(event) => handleMouseUp(type, event)}
selectedCard.id = card.id;
selectedCard.open = true;
}}
onElementRightClick={(card) => editDeckStore.remove(type, card)}
/> />
))} ))}
</ScrollableArea> </ScrollableArea>
...@@ -423,6 +468,53 @@ const SearchResults: React.FC<{ ...@@ -423,6 +468,53 @@ const SearchResults: React.FC<{
const endIndex = startIndex + itemsPerPage; const endIndex = startIndex + itemsPerPage;
const currentData = results.slice(startIndex, endIndex); const currentData = results.slice(startIndex, endIndex);
const showSelectedCard = (card: CardMeta) => {
selectedCard.id = card.id;
selectedCard.open = true;
};
const handleAddCardToMain = (card: CardMeta) => {
const cardType = card.data.type ?? 0;
const isExtraCard = isExtraDeckCard(cardType);
const type = isExtraCard ? "extra" : "main";
const { result, reason } = editDeckStore.canAdd(card, type, "search");
if (result) {
editDeckStore.add(type, card);
} else {
message.error(reason);
}
};
const handleAddCardToSide = (card: CardMeta) => {
const { result, reason } = editDeckStore.canAdd(card, "side", "search");
if (result) {
editDeckStore.add("side", card);
} else {
message.error(reason);
}
};
/** safari 不支持 onAuxClick,所以使用 mousedown 模拟 */
const handleMouseUp = (payload: DeckCardMouseUpEvent) => {
const { event, card } = payload;
switch (event.button) {
// 左键
case 0:
showSelectedCard(card);
break;
// 中键
case 1:
handleAddCardToSide(card);
break;
// 右键
case 2:
handleAddCardToMain(card);
break;
default:
break;
}
};
return ( return (
<> <>
<div className={styles["search-cards"]}> <div className={styles["search-cards"]}>
...@@ -431,10 +523,8 @@ const SearchResults: React.FC<{ ...@@ -431,10 +523,8 @@ const SearchResults: React.FC<{
value={card} value={card}
key={card.id} key={card.id}
source="search" source="search"
onClick={() => { onMouseUp={handleMouseUp}
selectedCard.id = card.id; onMouseEnter={() => showSelectedCard(card)}
selectedCard.open = true;
}}
/> />
))} ))}
</div> </div>
......
...@@ -10,13 +10,18 @@ import styles from "./index.module.scss"; ...@@ -10,13 +10,18 @@ import styles from "./index.module.scss";
const { assetsPath } = useConfig(); const { assetsPath } = useConfig();
export interface DeckCardMouseUpEvent {
event: React.MouseEvent;
card: CardMeta;
}
/** 组卡页和Side页使用的单张卡片,增加了文字和禁限数量 */ /** 组卡页和Side页使用的单张卡片,增加了文字和禁限数量 */
export const DeckCard: React.FC<{ export const DeckCard: React.FC<{
value: CardMeta; value: CardMeta;
source: Type | "search"; source: Type | "search";
onRightClick?: () => void; onMouseUp?: (event: DeckCardMouseUpEvent) => void;
onClick?: () => void; onMouseEnter?: () => void;
}> = memo(({ value, source, onRightClick, onClick }) => { }> = memo(({ value, source, onMouseUp, onMouseEnter }) => {
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
const [{ isDragging }, drag] = useDrag({ const [{ isDragging }, drag] = useDrag({
type: "Card", type: "Card",
...@@ -33,10 +38,15 @@ export const DeckCard: React.FC<{ ...@@ -33,10 +38,15 @@ export const DeckCard: React.FC<{
className={styles.card} className={styles.card}
ref={ref} ref={ref}
style={{ opacity: isDragging && source !== "search" ? 0 : 1 }} style={{ opacity: isDragging && source !== "search" ? 0 : 1 }}
onClick={onClick} onMouseUp={(event) =>
onMouseUp?.({
event,
card: value,
})
}
onMouseEnter={onMouseEnter}
onContextMenu={(e) => { onContextMenu={(e) => {
e.preventDefault(); e.preventDefault();
onRightClick?.();
}} }}
> >
{showText && <div className={styles.cardname}>{value.text.name}</div>} {showText && <div className={styles.cardname}>{value.text.name}</div>}
......
...@@ -5,7 +5,7 @@ import { useDrop } from "react-dnd"; ...@@ -5,7 +5,7 @@ import { useDrop } from "react-dnd";
import { CardMeta } from "@/api"; import { CardMeta } from "@/api";
import { DeckCard } from "../DeckCard"; import { DeckCard, DeckCardMouseUpEvent } from "../DeckCard";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
/** 正在组卡的zone,包括main/extra/side /** 正在组卡的zone,包括main/extra/side
...@@ -24,15 +24,13 @@ export const DeckZone: React.FC<{ ...@@ -24,15 +24,13 @@ export const DeckZone: React.FC<{
source: Type | "search", source: Type | "search",
destination: Type, destination: Type,
) => void; ) => void;
onElementClick: (card: CardMeta) => void; onElementMouseUp: (event: DeckCardMouseUpEvent) => void;
onElementRightClick?: (card: CardMeta) => void;
}> = ({ }> = ({
type, type,
cards, cards,
canAdd, canAdd,
onChange, onChange,
onElementClick, onElementMouseUp: onElementMouseUp,
onElementRightClick,
}) => { }) => {
const { message } = App.useApp(); const { message } = App.useApp();
const [allowToDrop, setAllowToDrop] = useState(false); const [allowToDrop, setAllowToDrop] = useState(false);
...@@ -72,12 +70,7 @@ export const DeckZone: React.FC<{ ...@@ -72,12 +70,7 @@ export const DeckZone: React.FC<{
value={card} value={card}
key={card.id + i + type} key={card.id + i + type}
source={type} source={type}
onClick={() => { onMouseUp={onElementMouseUp}
onElementClick(card);
}}
onRightClick={() => {
onElementRightClick?.(card);
}}
/> />
))} ))}
<div className={styles["editing-zone-name"]}> <div className={styles["editing-zone-name"]}>
......
...@@ -115,7 +115,7 @@ export const Component: React.FC = () => { ...@@ -115,7 +115,7 @@ export const Component: React.FC = () => {
cards={[...deck[type]].map((id) => fetchCard(id))} cards={[...deck[type]].map((id) => fetchCard(id))}
canAdd={canAdd} canAdd={canAdd}
onChange={onChange} onChange={onChange}
onElementClick={(card) => setSelectedCard(card.id)} onElementMouseUp={(event) => setSelectedCard(event.card.id)}
/> />
))} ))}
</ScrollableArea> </ScrollableArea>
......
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