diff --git a/B05_Profile/B05_Profile_UI_Profile_History.ts b/B05_Profile/B05_Profile_UI_Profile_History.ts index 37fe67636..c7b91d28a 100644 --- a/B05_Profile/B05_Profile_UI_Profile_History.ts +++ b/B05_Profile/B05_Profile_UI_Profile_History.ts @@ -114,10 +114,18 @@ const changed = (): void => hooks.forEach((entry) => entry.change?.()); function settle(): void { clearTimeout(settleTimer); settling = true; - settleTimer = setTimeout(() => { - settling = false; - active?.record(); - }, SETTLE_MS); + settleTimer = setTimeout(flushSettle, SETTLE_MS); + // ↶ 는 기다리지 않고 켬(477-3) — 같은 손길의 칸 쓰기가 끝난 한 틱 뒤 단추만 맞춤 + setTimeout(changed, 0); +} + +/** 기다리던 찍기를 지금 — 기다림이 끝났거나 그 사이 ↶ ↷ 를 누름(477-3 · 한 걸음 그대로). */ +function flushSettle(): void { + if (!settling) return; + clearTimeout(settleTimer); + settling = false; + active?.recordNow(); + changed(); } function watchPointer(): void { @@ -167,6 +175,8 @@ function restoreSnapshot(projectId: string, snapshot: HistorySnapshot): void { export interface ProfileHistory { /** 조작이 끝난 뒤 현재 상태를 이력에 쌓는다(직전과 같으면 무시). */ record(): void; + /** 누름이 남아 있어도 지금 찍음 — ↶ 단추 누름 중 기다리던 찍기(477-3). */ + recordNow(): void; /** 연속 조작(길게 누르기) 동안 기록을 미룬다 — 20칸 이동이 되돌리기 20번이 되는 것을 막는다. */ pause(): void; /** 연속 조작이 끝났음을 알린다 — 그 동안의 변화를 **한 덩어리로** 한 번만 쌓는다. */ @@ -224,6 +234,10 @@ export function createProfileHistory( return true; } + /** 찍기를 기다리는 동안 세션이 지금 걸음과 다름 — ↶ 를 바로 켜는 몫(477-3). */ + const pending = (): boolean => + settling && !restoring && !sameSnapshot(takeSnapshot(projectId, stack[cursor]), stack[cursor]); + const history: ProfileHistory = { record() { if (restoring || paused) return; @@ -231,6 +245,10 @@ export function createProfileHistory( releaseWaiters.add(history.record); return; } + history.recordNow(); + }, + recordNow() { + if (restoring || paused) return; sync(); restAt = gestures; const snapshot = takeSnapshot(projectId, stack[cursor]); @@ -253,10 +271,11 @@ export function createProfileHistory( paused = false; history.record(); }, - undo: () => apply(cursor - 1), - redo: () => apply(cursor + 1), - canUndo: () => cursor > 0, - canRedo: () => cursor < stack.length - 1, + // 기다리던 찍기 먼저 — 바로 누른 ↶ = 방금 조작 되돌림 · 묶음 한 걸음(477-3) + undo: () => (flushSettle(), apply(cursor - 1)), + redo: () => (flushSettle(), apply(cursor + 1)), + canUndo: () => cursor > 0 || pending(), + canRedo: () => cursor < stack.length - 1 && !pending(), }; rebaseActive = () => { if (restoring || paused || pointerHeld || settling || gestures !== restAt) return;