mirror of
https://github.com/chrislicodes/obsidian-chess-study.git
synced 2026-07-22 07:50:30 +00:00
chore: memo all the things
This commit is contained in:
parent
3b99c55d1d
commit
d1207f4a65
3 changed files with 210 additions and 199 deletions
|
|
@ -23,115 +23,119 @@ export interface ChessGroundSettings {
|
|||
currentMoveShapes: DrawShape[];
|
||||
}
|
||||
|
||||
export function ChessgroundWrapper({
|
||||
api,
|
||||
setApi,
|
||||
chessifyId,
|
||||
boardColor = "green",
|
||||
config = {},
|
||||
chess,
|
||||
setHistory,
|
||||
setMoveNumber,
|
||||
currentMoveNumber,
|
||||
setShapes,
|
||||
isViewOnly,
|
||||
currentMoveShapes,
|
||||
}: ChessGroundSettings) {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
//Chessground Init
|
||||
useEffect(() => {
|
||||
if (ref.current && !api) {
|
||||
const chessgroundApi = ChessgroundApi(ref.current, {
|
||||
fen: chess.fen(),
|
||||
animation: { enabled: true, duration: 100 },
|
||||
check: chess.isCheck(),
|
||||
movable: {
|
||||
free: false,
|
||||
color: toColor(chess),
|
||||
dests: toDests(chess),
|
||||
events: {
|
||||
//Hook up the Chessground UI changes to our App State
|
||||
after: (orig, dest, _metadata) => {
|
||||
const handler = playOtherSide(
|
||||
chessgroundApi,
|
||||
chess
|
||||
);
|
||||
|
||||
setHistory(handler(orig, dest));
|
||||
setMoveNumber((state) => state + 1);
|
||||
},
|
||||
},
|
||||
},
|
||||
highlight: {
|
||||
check: true,
|
||||
},
|
||||
turnColor: toColor(chess),
|
||||
...config,
|
||||
});
|
||||
|
||||
setHistory(chess.history({ verbose: true }));
|
||||
setApi(chessgroundApi);
|
||||
setMoveNumber(chess.history().length - 1);
|
||||
} else if (ref.current && api) {
|
||||
api.set(config);
|
||||
}
|
||||
}, [
|
||||
ref,
|
||||
chess,
|
||||
export const ChessgroundWrapper = React.memo(
|
||||
({
|
||||
api,
|
||||
chessifyId,
|
||||
config,
|
||||
setApi,
|
||||
chessifyId,
|
||||
boardColor = "green",
|
||||
config = {},
|
||||
chess,
|
||||
setHistory,
|
||||
setMoveNumber,
|
||||
setShapes,
|
||||
currentMoveNumber,
|
||||
]);
|
||||
setShapes,
|
||||
isViewOnly,
|
||||
currentMoveShapes,
|
||||
}: ChessGroundSettings) => {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
//Sync View Only
|
||||
useEffect(() => {
|
||||
api?.set({ viewOnly: isViewOnly });
|
||||
}, [isViewOnly, api]);
|
||||
//Chessground Init
|
||||
useEffect(() => {
|
||||
if (ref.current && !api) {
|
||||
const chessgroundApi = ChessgroundApi(ref.current, {
|
||||
fen: chess.fen(),
|
||||
animation: { enabled: true, duration: 100 },
|
||||
check: chess.isCheck(),
|
||||
movable: {
|
||||
free: false,
|
||||
color: toColor(chess),
|
||||
dests: toDests(chess),
|
||||
events: {
|
||||
//Hook up the Chessground UI changes to our App State
|
||||
after: (orig, dest, _metadata) => {
|
||||
const handler = playOtherSide(
|
||||
chessgroundApi,
|
||||
chess
|
||||
);
|
||||
|
||||
//Sync Shapes To State
|
||||
useEffect(() => {
|
||||
api?.set({
|
||||
drawable: {
|
||||
onChange(shapes) {
|
||||
setShapes((currentShapes) => {
|
||||
const shapesModified = [...currentShapes];
|
||||
shapesModified[currentMoveNumber] = shapes;
|
||||
setHistory(handler(orig, dest));
|
||||
setMoveNumber((state) => state + 1);
|
||||
},
|
||||
},
|
||||
},
|
||||
highlight: {
|
||||
check: true,
|
||||
},
|
||||
turnColor: toColor(chess),
|
||||
...config,
|
||||
});
|
||||
|
||||
return shapesModified;
|
||||
});
|
||||
setHistory(chess.history({ verbose: true }));
|
||||
setApi(chessgroundApi);
|
||||
setMoveNumber(chess.history().length - 1);
|
||||
} else if (ref.current && api) {
|
||||
api.set(config);
|
||||
}
|
||||
}, [
|
||||
ref,
|
||||
chess,
|
||||
api,
|
||||
chessifyId,
|
||||
config,
|
||||
setApi,
|
||||
setHistory,
|
||||
setMoveNumber,
|
||||
setShapes,
|
||||
currentMoveNumber,
|
||||
]);
|
||||
|
||||
//Sync View Only
|
||||
useEffect(() => {
|
||||
api?.set({ viewOnly: isViewOnly });
|
||||
}, [isViewOnly, api]);
|
||||
|
||||
//Sync Shapes To State
|
||||
useEffect(() => {
|
||||
api?.set({
|
||||
drawable: {
|
||||
onChange(shapes) {
|
||||
setShapes((currentShapes) => {
|
||||
const shapesModified = [...currentShapes];
|
||||
shapesModified[currentMoveNumber] = shapes;
|
||||
|
||||
return shapesModified;
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}, [api, currentMoveNumber, setShapes]);
|
||||
});
|
||||
}, [api, currentMoveNumber, setShapes]);
|
||||
|
||||
//Load Shapes
|
||||
useEffect(() => {
|
||||
if (currentMoveShapes) api?.setShapes(currentMoveShapes);
|
||||
}, [api, currentMoveNumber, currentMoveShapes, setShapes]);
|
||||
//Load Shapes
|
||||
useEffect(() => {
|
||||
if (currentMoveShapes) api?.setShapes(currentMoveShapes);
|
||||
}, [api, currentMoveNumber, currentMoveShapes, setShapes]);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
}}
|
||||
className={`${boardColor}-board`}
|
||||
>
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
style={{
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
display:
|
||||
"table" /* hack: round to full pixel size in chrome */,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
className={`${boardColor}-board`}
|
||||
>
|
||||
<div
|
||||
ref={ref}
|
||||
style={{
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
display:
|
||||
"table" /* hack: round to full pixel size in chrome */,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
ChessgroundWrapper.displayName = "ChessgroundWrapper";
|
||||
|
|
|
|||
|
|
@ -9,34 +9,35 @@ interface CommentSectionProps {
|
|||
setComments: React.Dispatch<React.SetStateAction<(JSONContent | null)[]>>;
|
||||
}
|
||||
|
||||
export const CommentSection = ({
|
||||
currentMove,
|
||||
currentComment,
|
||||
setComments,
|
||||
}: CommentSectionProps) => {
|
||||
const editor = useEditor({
|
||||
extensions: [StarterKit],
|
||||
onUpdate: (state) => {
|
||||
setComments((currentComments) => {
|
||||
const currentCommentModified = [...currentComments];
|
||||
currentCommentModified[currentMove] = state.editor.getJSON();
|
||||
return currentCommentModified;
|
||||
});
|
||||
},
|
||||
});
|
||||
export const CommentSection = React.memo(
|
||||
({ currentMove, currentComment, setComments }: CommentSectionProps) => {
|
||||
const editor = useEditor({
|
||||
extensions: [StarterKit],
|
||||
onUpdate: (state) => {
|
||||
setComments((currentComments) => {
|
||||
const currentCommentModified = [...currentComments];
|
||||
currentCommentModified[currentMove] =
|
||||
state.editor.getJSON();
|
||||
return currentCommentModified;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!editor) return;
|
||||
const { from, to } = editor.state.selection;
|
||||
if (currentComment) {
|
||||
editor.commands.setContent(currentComment, false, {
|
||||
preserveWhitespace: true,
|
||||
});
|
||||
} else {
|
||||
editor.commands.clearContent();
|
||||
}
|
||||
editor.commands.setTextSelection({ from, to });
|
||||
}, [currentComment, editor]);
|
||||
useEffect(() => {
|
||||
if (!editor) return;
|
||||
const { from, to } = editor.state.selection;
|
||||
if (currentComment) {
|
||||
editor.commands.setContent(currentComment, false, {
|
||||
preserveWhitespace: true,
|
||||
});
|
||||
} else {
|
||||
editor.commands.clearContent();
|
||||
}
|
||||
editor.commands.setTextSelection({ from, to });
|
||||
}, [currentComment, editor]);
|
||||
|
||||
return <EditorContent editor={editor} />;
|
||||
};
|
||||
return <EditorContent editor={editor} />;
|
||||
}
|
||||
);
|
||||
|
||||
CommentSection.displayName = "CommentSection";
|
||||
|
|
|
|||
|
|
@ -54,84 +54,90 @@ const MoveItem = ({
|
|||
);
|
||||
};
|
||||
|
||||
export const PgnViewer = ({
|
||||
history,
|
||||
currentMove,
|
||||
onBackButtonClick,
|
||||
onForwardButtonClick,
|
||||
onMoveItemClick,
|
||||
onSaveButtonClick,
|
||||
}: {
|
||||
history: Move[];
|
||||
currentMove: number;
|
||||
onBackButtonClick: () => void;
|
||||
onForwardButtonClick: () => void;
|
||||
onMoveItemClick: (moveIndex: number) => void;
|
||||
onSaveButtonClick: () => void;
|
||||
}) => {
|
||||
const movePairs = useMemo(() => chunkArray(history, 2), [history]);
|
||||
export const PgnViewer = React.memo(
|
||||
({
|
||||
history,
|
||||
currentMove,
|
||||
onBackButtonClick,
|
||||
onForwardButtonClick,
|
||||
onMoveItemClick,
|
||||
onSaveButtonClick,
|
||||
}: {
|
||||
history: Move[];
|
||||
currentMove: number;
|
||||
onBackButtonClick: () => void;
|
||||
onForwardButtonClick: () => void;
|
||||
onMoveItemClick: (moveIndex: number) => void;
|
||||
onSaveButtonClick: () => void;
|
||||
}) => {
|
||||
const movePairs = useMemo(() => chunkArray(history, 2), [history]);
|
||||
|
||||
return (
|
||||
<div style={{ width: "100%", height: "100%" }}>
|
||||
<div style={{ height: "415px" }}>
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "0.15fr 0.425fr 0.425fr",
|
||||
gridAutoRows: "30px",
|
||||
width: "100%",
|
||||
maxHeight: "415px",
|
||||
overflowY: "scroll",
|
||||
}}
|
||||
>
|
||||
{movePairs.map((pair, i) => {
|
||||
const [wMove, bMove] = pair;
|
||||
return (
|
||||
<React.Fragment key={wMove.san + bMove?.san}>
|
||||
<p className="move-indicator center">{i + 1}</p>
|
||||
<MoveItem
|
||||
san={wMove.san}
|
||||
isCurrentMove={i * 2 === currentMove}
|
||||
onMoveItemClick={() =>
|
||||
onMoveItemClick(i * 2)
|
||||
}
|
||||
/>
|
||||
{bMove && (
|
||||
return (
|
||||
<div style={{ width: "100%", height: "100%" }}>
|
||||
<div style={{ height: "415px" }}>
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "0.15fr 0.425fr 0.425fr",
|
||||
gridAutoRows: "30px",
|
||||
width: "100%",
|
||||
maxHeight: "415px",
|
||||
overflowY: "scroll",
|
||||
}}
|
||||
>
|
||||
{movePairs.map((pair, i) => {
|
||||
const [wMove, bMove] = pair;
|
||||
return (
|
||||
<React.Fragment key={wMove.san + bMove?.san}>
|
||||
<p className="move-indicator center">
|
||||
{i + 1}
|
||||
</p>
|
||||
<MoveItem
|
||||
san={bMove.san}
|
||||
isCurrentMove={
|
||||
i * 2 + 1 === currentMove
|
||||
}
|
||||
san={wMove.san}
|
||||
isCurrentMove={i * 2 === currentMove}
|
||||
onMoveItemClick={() =>
|
||||
onMoveItemClick(i * 2 + 1)
|
||||
onMoveItemClick(i * 2)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
{bMove && (
|
||||
<MoveItem
|
||||
san={bMove.san}
|
||||
isCurrentMove={
|
||||
i * 2 + 1 === currentMove
|
||||
}
|
||||
onMoveItemClick={() =>
|
||||
onMoveItemClick(i * 2 + 1)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
width: "100%",
|
||||
gap: "4px",
|
||||
height: "35px",
|
||||
}}
|
||||
>
|
||||
<button onClick={() => onBackButtonClick()}>
|
||||
<ArrowLeft />
|
||||
</button>
|
||||
<button onClick={() => onForwardButtonClick()}>
|
||||
<ArrowRight />
|
||||
</button>
|
||||
<button onClick={() => onSaveButtonClick()}>
|
||||
<Save strokeWidth={"1px"} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
width: "100%",
|
||||
gap: "4px",
|
||||
height: "35px",
|
||||
}}
|
||||
>
|
||||
<button onClick={() => onBackButtonClick()}>
|
||||
<ArrowLeft />
|
||||
</button>
|
||||
<button onClick={() => onForwardButtonClick()}>
|
||||
<ArrowRight />
|
||||
</button>
|
||||
<button onClick={() => onSaveButtonClick()}>
|
||||
<Save strokeWidth={"1px"} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
PgnViewer.displayName = "PgnViewer";
|
||||
|
|
|
|||
Loading…
Reference in a new issue