fix(B05·B06): 조작 놓은 직후 ↶ 바로 켜짐 · 기다림 중 ↶ = 먼저 찍고 되돌림 (PLAN 477-3 · 요구 433)
- 찍기 기다림(400 ms) 들어가면 한 틱 뒤 단추 맞춤 — 세션이 지금 걸음과 다를 때만 켜짐(바뀐 것 없는 누름은 그대로 꺼짐) - ↶ ↷ 누르면 기다리던 찍기 먼저(누름 중이어도) — 방금 조작이 한 걸음으로 되돌아감 - 기다림 시간 · 서버 다시 셈 묶음은 그대로 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user