diff --git a/src/components/react/ChessStudy.tsx b/src/components/react/ChessStudy.tsx index 614c178..06471e9 100644 --- a/src/components/react/ChessStudy.tsx +++ b/src/components/react/ChessStudy.tsx @@ -42,6 +42,7 @@ export interface GameState { export type GameActions = | { type: 'ADD_MOVE_TO_HISTORY'; move: Move } + | { type: 'REMOVE_LAST_MOVE_FROM_HISTORY' } | { type: 'DISPLAY_NEXT_MOVE_IN_HISTORY' } | { type: 'DISPLAY_PREVIOUS_MOVE_IN_HISTORY' } | { type: 'DISPLAY_SELECTED_MOVE_IN_HISTORY'; moveId: string } @@ -56,6 +57,7 @@ export const ChessStudy = ({ }: AppProps) => { // Parse Obsidian / Code Block Settings const { boardColor, boardOrientation, fen, viewComments, chessStudyId } = + parseUserConfig(pluginSettings, source); // Setup Chessground API @@ -85,7 +87,7 @@ export const ChessStudy = ({ (draft, action) => { switch (action.type) { case 'DISPLAY_NEXT_MOVE_IN_HISTORY': { - if (!chessView) return draft; + if (!chessView || !draft || draft.study.moves.length == 0) return draft; displayMoveInHistory(draft, chessView, setChessLogic, { offset: 1, @@ -95,7 +97,7 @@ export const ChessStudy = ({ return draft; } case 'DISPLAY_PREVIOUS_MOVE_IN_HISTORY': { - if (!chessView) return draft; + if (!chessView || !draft || draft.study.moves.length == 0) return draft; displayMoveInHistory(draft, chessView, setChessLogic, { offset: -1, @@ -104,8 +106,57 @@ export const ChessStudy = ({ return draft; } + case 'REMOVE_LAST_MOVE_FROM_HISTORY': { + if (!chessView || !draft || draft.study.moves.length == 0) return draft; + + let moves = draft.study.moves; + + const currentMoveId = draft.currentMove?.moveId; + + const { variant, moveIndex } = findMoveIndex(moves, currentMoveId); + + if (variant) { + const parent = moves[variant.parentMoveIndex]; + const variantMoves = parent.variants[variant.variantIndex].moves; + + const isLastMove = moveIndex === variantMoves.length - 1; + + if (isLastMove) { + displayMoveInHistory(draft, chessView, setChessLogic, { + offset: -1, + selectedMoveId: currentMoveId, + }); + } + + variantMoves.pop(); + if (variantMoves.length == 0) { + parent.variants.splice(variant.variantIndex, 1); + } + + if (isLastMove) { + draft.currentMove = (variantMoves.length > 0) ? variantMoves[variantMoves.length - 1] : moves[variant.parentMoveIndex]; + } + } else { + const isLastMove = moveIndex === moves.length - 1; + + if (isLastMove) { + displayMoveInHistory(draft, chessView, setChessLogic, { + offset: -1, + selectedMoveId: currentMoveId, + }); + } + + moves.pop(); + + if (isLastMove) { + draft.currentMove = (moves.length > 0) ? moves[moves.length - 1] : null; + } + } + + return draft; + } case 'DISPLAY_SELECTED_MOVE_IN_HISTORY': { - if (!chessView) return draft; + if (!chessView || !draft || draft.study.moves.length == 0) return draft; const selectedMoveId = action.moveId; @@ -117,6 +168,8 @@ export const ChessStudy = ({ return draft; } case 'SYNC_SHAPES': { + if (!chessView || !draft || draft.study.moves.length == 0) return draft; + const move = getCurrentMove(draft); move.shapes = action.shapes; @@ -125,6 +178,8 @@ export const ChessStudy = ({ return draft; } case 'SYNC_COMMENT': { + if (!chessView || !draft || draft.study.moves.length == 0) return draft; + const move = getCurrentMove(draft); move.comment = action.comment; @@ -262,8 +317,12 @@ export const ChessStudy = ({ + dispatch({ type: 'REMOVE_LAST_MOVE_FROM_HISTORY' }) + } onBackButtonClick={() => dispatch({ type: 'DISPLAY_PREVIOUS_MOVE_IN_HISTORY' }) } diff --git a/src/components/react/PgnViewer/index.tsx b/src/components/react/PgnViewer/index.tsx index 447804c..054efd6 100644 --- a/src/components/react/PgnViewer/index.tsx +++ b/src/components/react/PgnViewer/index.tsx @@ -1,4 +1,4 @@ -import { ArrowLeft, ArrowRight, Copy, Save } from 'lucide-react'; +import { ArrowLeft, ArrowRight, Save, Undo2 } from 'lucide-react'; import * as React from 'react'; import { ReactNode, useEffect, useMemo, useRef } from 'react'; import { ChessStudyMove } from 'src/lib/storage'; @@ -110,6 +110,7 @@ export const PgnViewer = React.memo( currentMoveId, firstPlayer, initialMoveNumber, + onUndoButtonClick, onBackButtonClick, onForwardButtonClick, onMoveItemClick, @@ -120,6 +121,7 @@ export const PgnViewer = React.memo( currentMoveId: string; firstPlayer: string; initialMoveNumber: number; + onUndoButtonClick: () => void; onBackButtonClick: () => void; onForwardButtonClick: () => void; onMoveItemClick: (moveId: string) => void; @@ -295,6 +297,9 @@ export const PgnViewer = React.memo(
+