Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"recommendations": ["wallabyjs.quokka-vscode"]
}
21 changes: 11 additions & 10 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ import Deck from './gameSession/deck/Deck';
import Btns from './gameSession/footer/Btns';
import About from './about/About';
import DebugVisual from './dev/debugVisual/DebugVisual';
import type { CardType, DragsStatusType, DevSpeedControlType } from './types/types';
import type { CardType, DragsStatusType, DevSpeedControlType, BtnType } from './types/types';

import './App.css';

function App() {
const [btns, btnsSet] = useState<{ left: boolean; right: boolean; back: boolean; flip: boolean }>({
left: false,
right: false,
back: false,
flip: false,
});
const btnHndlr = (action: BtnType): void => {
deckBtnHndlrRef.current?.(action);
};

const deckBtnHndlrRef = useRef<((action: BtnType) => void) | null>(null);

const [devDeckRest, devDeckRestSet] = useState<number>(0);
const [devDragsStatus, setDevDragsStatus] = useState<DragsStatusType[]>([]);
const [devDeckVisible, devDeckVisibleSet] = useState<CardType[]>([]);
Expand All @@ -29,16 +29,17 @@ function App() {
</section>
<section className='flexChildren2'>
<Deck
btns={btns}
btnsSet={btnsSet}
setBtnHndlr={(hndlr) => {
deckBtnHndlrRef.current = hndlr;
}}
devDeckRestSet={devDeckRestSet}
devDeckVisibleSet={devDeckVisibleSet}
setDevDragsStatus={setDevDragsStatus}
devSpeed={devSpeed}
/>
</section>
<section className='flexChildren3'>
<Btns btns={btns} btnsSet={btnsSet} />
<Btns btnHndlr={btnHndlr} />
</section>
</section>

Expand Down
11 changes: 5 additions & 6 deletions src/components/draggable/Draggable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const Draggable = ({
const xyMove = useRef<XYType>({ x: 0, y: 0 });
const xyPrev = useRef<XYType>({ x: 0, y: 0 });

const [xy, setXy] = useState<XYType>(card.comeBack ? card.lastPos : { x: 0, y: 0 });
const [xy, setXy] = useState<XYType>(card.lastPos ? card.lastPos : { x: 0, y: 0 });
const xyRef = useRef(xy);

const dragHistory = React.useRef<{ pos: XYType; time: number }[]>([]);
Expand Down Expand Up @@ -142,7 +142,7 @@ const Draggable = ({
if (
Math.abs(xyRef.current.x) > window.innerWidth * 0.5 - window.innerWidth * 0.1 &&
!card?.btnLR &&
!card?.comeBack
!card?.lastPos
) {
if (isCardOut) {
if (outFlag.current) return;
Expand Down Expand Up @@ -177,7 +177,7 @@ const Draggable = ({
const fresh = [...prev];
for (let i = 0; i < fresh.length; i++) {
if (fresh[i].id === card.id) {
delete fresh[i]?.comeBack;
delete fresh[i]?.lastPos;
delete fresh[i]?.btnLR;
}
}
Expand Down Expand Up @@ -208,7 +208,7 @@ const Draggable = ({
const fresh = [...prev];
for (let i = 0; i < fresh.length; i++) {
if (fresh[i].id === card.id) {
delete fresh[i]?.comeBack;
delete fresh[i]?.lastPos;
delete fresh[i]?.btnLR;
}
}
Expand All @@ -225,7 +225,7 @@ const Draggable = ({
return { x: prev.x * speed, y: prev.y * speed };
});

if (comeBackFlag.current && !card?.comeBack) {
if (comeBackFlag.current && !card?.lastPos) {
//? DEV
devChangeStatus(setDevDragsStatus, card, 'backToDeck', dragCountRef);

Expand Down Expand Up @@ -289,7 +289,6 @@ const Draggable = ({

delete deckRef.current[cardIndex]?.btnLR;
delete deckRef.current[cardIndex]?.lastPos;
delete deckRef.current[cardIndex]?.comeBack;

const pickedToTop = () => {
const deck = deckRef.current;
Expand Down
1 change: 0 additions & 1 deletion src/gameSession/deck/Deck.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
-webkit-user-select: none;
-webkit-tap-highlight-color: transparent; /* 🧽 убирает синюю подсветку при тапе */
-webkit-touch-callout: none; /* ❌ запрещает контекстное меню на iOS */

z-index: 1;
}

Expand Down
170 changes: 85 additions & 85 deletions src/gameSession/deck/Deck.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ import type {
import gameDeck from '../../features/gameDeck';
import { nameFromImg, devChangeStatus } from '../../dev/debugVisual/features';
import { dragCountUpdate } from '../../components/draggable/features/actions';
import type { BtnType } from '../../types/types';

type DeckProps = {
btns: { left: boolean; right: boolean; back: boolean; flip: boolean };
btnsSet: React.Dispatch<React.SetStateAction<{ left: boolean; right: boolean; back: boolean; flip: boolean }>>;
setBtnHndlr: (handler: (btn: BtnType) => void) => void;
devDeckRestSet: React.Dispatch<React.SetStateAction<number>>;
devDeckVisibleSet: React.Dispatch<React.SetStateAction<CardType[]>>;
setDevDragsStatus: React.Dispatch<React.SetStateAction<DragsStatusType[]>>;
devSpeed: React.RefObject<DevSpeedControlType>;
};

const Deck = ({ btns, btnsSet, devDeckRestSet, devDeckVisibleSet, setDevDragsStatus, devSpeed }: DeckProps) => {
const Deck = ({ setBtnHndlr, devDeckRestSet, devDeckVisibleSet, setDevDragsStatus, devSpeed }: DeckProps) => {
const dragCountLimit = useRef<number>(5);
const [dragCount, setDragCount] = useState<number>(5);
const dragCountRef = useRef<number>(5);
Expand All @@ -36,9 +36,6 @@ const Deck = ({ btns, btnsSet, devDeckRestSet, devDeckVisibleSet, setDevDragsSta

const draggedId = useRef<Set<number>>(new Set([]));

// Я могу вынести glow(right/wrong) на урвовень deck и управлять им by max и min value of xyDragged(всех карт в !== sleep)
const xyDragged = useRef<XYType[]>([]);

// Удаление карточки:
//* I. Clear
// 0. Add field lastPos
Expand All @@ -54,6 +51,7 @@ const Deck = ({ btns, btnsSet, devDeckRestSet, devDeckVisibleSet, setDevDragsSta
};
const counter1Ref: React.RefObject<(n?: number) => number> = useRef(closure());
const counter2Ref: React.RefObject<(n?: number) => number> = useRef(closure());
const counter3Ref: React.RefObject<(n?: number) => number> = useRef(closure());

// console.log('🍒', counter2Ref.current(), 'Deck Re-Render');
const cardOutHndlr = (cardId: number, direction: 'string', lastPos: XYType, codePoint: string) => {
Expand Down Expand Up @@ -97,7 +95,7 @@ const Deck = ({ btns, btnsSet, devDeckRestSet, devDeckVisibleSet, setDevDragsSta
const prevStatus = prevJ.find((j) => j.id === card.id)?.status;

let status: DragsStatusStatusType = 'sleep';
if (card.comeBack) status = 'comeBack';
if (card?.lastPos) status = 'comeBack';
else if (prevStatus) status = prevStatus;
return { id: card.id, dragNum: i, card: nameFromImg([card], 0), status };
});
Expand All @@ -107,112 +105,114 @@ const Deck = ({ btns, btnsSet, devDeckRestSet, devDeckVisibleSet, setDevDragsSta
});
};

const btnSwipeHndlr = (direction: 'l' | 'r') => {
let notRLDraged: number = 0;

for (let i = 0; i < draggedId.current.size; i++) {
if (!deckRef.current[deckRef.current.length - 1 - i]?.btnLR) notRLDraged++;
}

const indexTop = deckRef.current.length - 1 - (draggedId.current.size - notRLDraged);
const topCard = deckRef.current[indexTop];

if (!topCard || topCard?.btnLR || topCard?.lastPos) return;

draggedId.current.add(topCard.id);
topCard.btnLR = direction;
setDeck(deckRef.current);

dragCountUpdate(draggedId, dragCountLimit, dragCountRef, setDragCount);

//? DEV
setDevDragsStatus((prevJ) => {
const fresh: DragsStatusType[] = deckRef.current.slice(-dragCountRef.current).map((card, i) => {
const prevStatus = prevJ.find((j) => j.id === card.id)?.status;

let status: DragsStatusStatusType = 'sleep';
if (card.lastPos) status = 'comeBack';
else if (card.id === topCard.id) status = 'fling';
else if (prevStatus) status = prevStatus;
return { id: card.id, dragNum: i, card: nameFromImg([card], 0), status };
});
return fresh;
});
};

const hasInitialized = useRef(false);
useEffect(() => {
if (hasInitialized.current) return;
hasInitialized.current = true;

// deck Initialization
const deckFirst = gameDeck();
setDeck(deckFirst);

for (let i = 0; i < dragCountLimit.current; i++) {
const indexTop = deckFirst.length - dragCountLimit.current + i;
const cardName = nameFromImg(deckFirst, indexTop);
setDevDragsStatus((prev) => {
return [...prev, { id: deckFirst[indexTop].id, dragNum: prev.length, card: cardName, status: 'sleep' }];
});
}
}, []);

useEffect(() => {
if (deck.length === 0) return;
const vis = deck.slice(-(dragCountLimit.current + 15));

setDeckVisible(vis);
devDeckVisibleSet(vis);

deckRef.current = deck;
// btns action
const btnHndlr = (btn: BtnType) => {
if (btn === 'left') btnSwipeHndlr('l');
else if (btn === 'right') btnSwipeHndlr('r');
else if (btn === 'back') {
if (deckHistory.current.length === 0) {
deckHistoryTop.current = null;
return;
}
if (deckRef.current.some((card) => card.id === deckHistory.current[deckHistory.current.length - 1].id)) {
console.warn('🔁 Карта уже в колоде, повторное добавление пропущено');
return;
}
if (draggedId.current.size >= dragCountLimit.current) return;

// Dev
devDeckRestSet(deck.length);
}, [deck, dragCountLimit.current]);
deckHistoryTop.current = deckHistory.current.pop() ?? null;
const comeBackCard = { ...deckHistoryTop.current };

useEffect(() => {
if (!btns.back) return;
setDeck((prev) => {
const freshDeck = [...prev, comeBackCard];
deckRef.current = freshDeck;

if (deckHistory.current.length === 0) {
deckHistoryTop.current = null;
return;
}
if (deckRef.current.some((card) => card.id === deckHistory.current[deckHistory.current.length - 1].id)) {
console.warn('🔁 Карта уже в колоде, повторное добавление пропущено');
return;
}
if (draggedId.current.size >= dragCountLimit.current) return;
draggedId.current.add(comeBackCard.id);
dragCountUpdate(draggedId, dragCountLimit, dragCountRef, setDragCount);

deckHistoryTop.current = deckHistory.current.pop() ?? null;
const comeBackCard = { ...deckHistoryTop.current, comeBack: true };
setDevDragsStatus((prevJ) => {
const fresh: DragsStatusType[] = freshDeck.slice(-dragCountRef.current).map((card, i) => {
const prevStatus = prevJ.find((j) => j.id === card.id)?.status;

setDeck((prev) => {
const freshDeck = [...prev, comeBackCard];
deckRef.current = freshDeck;
let status: DragsStatusStatusType = 'sleep';
if (card?.lastPos) status = 'comeBack';
else if (prevStatus) status = prevStatus;
return { id: card.id, dragNum: i, card: nameFromImg([card], 0), status };
});
return fresh;
});

draggedId.current.add(comeBackCard.id);
dragCountUpdate(draggedId, dragCountLimit, dragCountRef, setDragCount);

setDevDragsStatus((prevJ) => {
const fresh: DragsStatusType[] = freshDeck.slice(-dragCountRef.current).map((card, i) => {
const prevStatus = prevJ.find((j) => j.id === card.id)?.status;

let status: DragsStatusStatusType = 'sleep';
if (card.comeBack) status = 'comeBack';
else if (prevStatus) status = prevStatus;
return { id: card.id, dragNum: i, card: nameFromImg([card], 0), status };
return freshDeck;
});
return fresh;
});

return freshDeck;
});
} else if (btn === 'flip') {
// console.log('flip');
}
};

btnsSet((prev) => ({ ...prev, back: false }));
}, [btns.back]);
setBtnHndlr(btnHndlr);
}, []);

useEffect(() => {
if (!btns.left && !btns.right) return;
btnsSet((prev) => ({ ...prev, left: false, right: false }));

let notRLDraged: number = 0;

for (let i = 0; i < draggedId.current.size; i++) {
if (!deckRef.current[deckRef.current.length - 1 - i]?.btnLR) notRLDraged++;
}

const indexTop = deckRef.current.length - 1 - (draggedId.current.size - notRLDraged);
const topCard = deckRef.current[indexTop];

if (!topCard || topCard?.btnLR || topCard?.comeBack) return;

draggedId.current.add(topCard.id);
topCard.btnLR = btns.left ? 'l' : 'r';
setDeck(deckRef.current);
if (deck.length === 0) return;
const vis = deck.slice(-(dragCountLimit.current + 15));

dragCountUpdate(draggedId, dragCountLimit, dragCountRef, setDragCount);
setDeckVisible(vis);
devDeckVisibleSet(vis);

//? DEV
setDevDragsStatus((prevJ) => {
const fresh: DragsStatusType[] = deckRef.current.slice(-dragCountRef.current).map((card, i) => {
const prevStatus = prevJ.find((j) => j.id === card.id)?.status;
deckRef.current = deck;

let status: DragsStatusStatusType = 'sleep';
if (card.comeBack) status = 'comeBack';
else if (card.id === topCard.id) status = 'fling';
else if (prevStatus) status = prevStatus;
return { id: card.id, dragNum: i, card: nameFromImg([card], 0), status };
});
return fresh;
});
}, [btns.left, btns.right]);
// Dev
devDeckRestSet(deck.length);
}, [deck, dragCountLimit.current]);

const [imgHasError, setImgHasError] = useState(false);

Expand Down
Loading