diff --git a/src/components/react/Chessify.tsx b/src/components/react/Chessify.tsx
index cfa4278..bf99f0f 100644
--- a/src/components/react/Chessify.tsx
+++ b/src/components/react/Chessify.tsx
@@ -1,8 +1,12 @@
+import { Chess, Move } from "chess.js";
+import { Api } from "chessground/api";
import { App } from "obsidian";
import * as React from "react";
+import { useCallback, useMemo, useState } from "react";
import { ChessifyPluginSettings } from "src/components/obsidian/SettingsTab";
-import { ChessgroundWrapper, ChessGroundSettings } from "./ChessgroundWrapper";
-import { parseUserConfig } from "src/utils";
+import { ChessifyFileData, parseUserConfig } from "src/utils";
+import { ChessGroundSettings, ChessgroundWrapper } from "./ChessgroundWrapper";
+import { PgnViewer } from "./PgnViewer";
export type ChessifyConfig = ChessGroundSettings;
@@ -10,21 +14,129 @@ interface AppProps {
source: string;
app: App;
pluginSettings: ChessifyPluginSettings;
+ chessifyData: ChessifyFileData;
}
-export const Chessify = ({ source, pluginSettings }: AppProps) => {
- const { fen, boardColor, boardOrientation } = parseUserConfig(
+export const Chessify = ({
+ source,
+ pluginSettings,
+ chessifyData,
+}: AppProps) => {
+ // Parse Obsidian / Code Block Settings
+ const { boardColor, boardOrientation, chessifyId } = parseUserConfig(
pluginSettings,
source
);
+ // Setup Chessboard and Chess.js APIs
+ const [chessView, setChessView] = useState
(null);
+ const chessLogic = useMemo(() => {
+ const chess = new Chess();
+
+ chessifyData.moves.forEach((move) => {
+ chess.move({
+ from: move.from,
+ to: move.to,
+ promotion: move.promotion,
+ });
+ });
+ return chess;
+ }, [chessifyData.moves]);
+
+ // Track Application State
+ const [history, setHistory] = useState([]);
+ const [isViewOnly, setIsViewOnly] = useState(false);
+ const [currentMove, setCurrentMove] = useState(0);
+
+ //PgnViewer Functions
+ const onBackButtonClick = useCallback(() => {
+ if (currentMove >= 0) {
+ setCurrentMove((currentMove) => {
+ const move = history[currentMove];
+ const tempChess = new Chess(move.before);
+ chessView?.set({
+ fen: move.before,
+ check: tempChess.isCheck(),
+ });
+ setIsViewOnly(true);
+ return currentMove - 1;
+ });
+ }
+ }, [chessView, currentMove, history]);
+
+ const onForwardButtonClick = useCallback(() => {
+ if (currentMove < history.length - 1) {
+ setCurrentMove((currentMove) => {
+ const move = history[currentMove + 1];
+ const tempChess = new Chess(move.after);
+ chessView?.set({
+ fen: move.after,
+ check: tempChess.isCheck(),
+ });
+ if (currentMove + 1 === history.length - 1)
+ setIsViewOnly(false);
+ return currentMove + 1;
+ });
+ }
+ }, [currentMove, chessView, history]);
+
+ const onMoveItemClick = useCallback(
+ (moveIndex: number) => {
+ setCurrentMove(() => {
+ const move = history[moveIndex];
+ const tempChess = new Chess(move.after);
+ chessView?.set({
+ fen: move.after,
+ check: tempChess.isCheck(),
+ });
+ if (moveIndex + 1 !== history.length - 1) {
+ setIsViewOnly(false);
+ } else {
+ setIsViewOnly(true);
+ }
+
+ return moveIndex;
+ });
+ },
+ [chessView, history]
+ );
+
return (
-
+ >
+
+
+
+
+
);
};
diff --git a/src/components/react/PgnViewer/index.tsx b/src/components/react/PgnViewer/index.tsx
new file mode 100644
index 0000000..9d25cce
--- /dev/null
+++ b/src/components/react/PgnViewer/index.tsx
@@ -0,0 +1,129 @@
+import { Move } from "chess.js";
+import { ArrowLeft, ArrowRight } from "lucide-react";
+import * as React from "react";
+import { useEffect, useMemo, useRef } from "react";
+
+const chunkArray =