리펙토링: 코드 최적화, AGENTS.md, README.md 내용 반영
This commit is contained in:
@@ -16,6 +16,9 @@ import KatexRenderer from "@/components/math/KatexRenderer";
|
||||
import { useGameStore } from "@/store/gameStore";
|
||||
import type { ProblemCount } from "@/store/gameStore";
|
||||
|
||||
const MOBILE_BREAKPOINT_QUERY = "(min-width: 640px)";
|
||||
const MOBILE_KEYBOARD_SPACER_OFFSET = 480;
|
||||
|
||||
function parseAnswer(value: string) {
|
||||
const trimmed = value.trim();
|
||||
|
||||
@@ -47,7 +50,6 @@ export default function PlayClient({ problemCount }: PlayClientProps) {
|
||||
const [answerA, setAnswerA] = useState("");
|
||||
const [answerB, setAnswerB] = useState("");
|
||||
const [activeInput, setActiveInput] = useState<ActiveAnswerInput>(0);
|
||||
const [focusInputOnFormMount, setFocusInputOnFormMount] = useState(false);
|
||||
const [mobileFocusSpacerHeight, setMobileFocusSpacerHeight] = useState(0);
|
||||
const [inputError, setInputError] = useState("");
|
||||
|
||||
@@ -86,15 +88,17 @@ export default function PlayClient({ problemCount }: PlayClientProps) {
|
||||
setInputError("");
|
||||
}, [currentProblem?.key]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
scrollTimeoutsRef.current.forEach((timeoutId) => {
|
||||
window.clearTimeout(timeoutId);
|
||||
});
|
||||
viewportResizeCleanupRef.current?.();
|
||||
};
|
||||
const clearViewportFocusCleanup = useCallback(() => {
|
||||
scrollTimeoutsRef.current.forEach((timeoutId) => {
|
||||
window.clearTimeout(timeoutId);
|
||||
});
|
||||
scrollTimeoutsRef.current = [];
|
||||
viewportResizeCleanupRef.current?.();
|
||||
viewportResizeCleanupRef.current = null;
|
||||
}, []);
|
||||
|
||||
useEffect(() => clearViewportFocusCleanup, [clearViewportFocusCleanup]);
|
||||
|
||||
function handleSubmit(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault();
|
||||
|
||||
@@ -113,15 +117,18 @@ export default function PlayClient({ problemCount }: PlayClientProps) {
|
||||
}
|
||||
|
||||
function handleNextProblem() {
|
||||
setFocusInputOnFormMount(true);
|
||||
flushSync(() => {
|
||||
nextProblem();
|
||||
});
|
||||
answerFormRef.current?.focusInput();
|
||||
}
|
||||
|
||||
const handleInputBlur = useCallback(() => {
|
||||
setMobileFocusSpacerHeight(0);
|
||||
}, []);
|
||||
|
||||
const scrollKatexToViewportTop = useCallback(() => {
|
||||
if (window.matchMedia("(min-width: 640px)").matches) return;
|
||||
if (window.matchMedia(MOBILE_BREAKPOINT_QUERY).matches) return;
|
||||
|
||||
function alignKatex() {
|
||||
const katexElement =
|
||||
@@ -158,15 +165,13 @@ export default function PlayClient({ problemCount }: PlayClientProps) {
|
||||
);
|
||||
|
||||
setMobileFocusSpacerHeight(
|
||||
Math.max(window.innerHeight, keyboardHeight + 480),
|
||||
Math.max(
|
||||
window.innerHeight,
|
||||
keyboardHeight + MOBILE_KEYBOARD_SPACER_OFFSET,
|
||||
),
|
||||
);
|
||||
|
||||
scrollTimeoutsRef.current.forEach((timeoutId) => {
|
||||
window.clearTimeout(timeoutId);
|
||||
});
|
||||
scrollTimeoutsRef.current = [];
|
||||
viewportResizeCleanupRef.current?.();
|
||||
viewportResizeCleanupRef.current = null;
|
||||
clearViewportFocusCleanup();
|
||||
|
||||
if (visualViewport) {
|
||||
let settleTimeoutId: number | null = null;
|
||||
@@ -197,7 +202,7 @@ export default function PlayClient({ problemCount }: PlayClientProps) {
|
||||
const timeoutId = window.setTimeout(alignKatex, delay);
|
||||
scrollTimeoutsRef.current.push(timeoutId);
|
||||
});
|
||||
}, []);
|
||||
}, [clearViewportFocusCleanup]);
|
||||
|
||||
if (!session || sessionNeedsInit) {
|
||||
return (
|
||||
@@ -272,13 +277,11 @@ export default function PlayClient({ problemCount }: PlayClientProps) {
|
||||
answerA={answerA}
|
||||
answerB={answerB}
|
||||
activeInput={activeInput}
|
||||
disabled={submitted}
|
||||
error={inputError}
|
||||
focusOnMount={focusInputOnFormMount}
|
||||
onActiveInputChange={setActiveInput}
|
||||
onAnswerAChange={setAnswerA}
|
||||
onAnswerBChange={setAnswerB}
|
||||
onInputBlur={() => setMobileFocusSpacerHeight(0)}
|
||||
onInputBlur={handleInputBlur}
|
||||
onInputFocus={scrollKatexToViewportTop}
|
||||
onSubmit={handleSubmit}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user