fix(472 덧 B05 관 지움 ↶): 관 초안 없는 걸음 = 저장분 — 판이 마지막 저장분 답과 견줘 다르면 조용히 다시 읽음 · 옛 「처음 본 관 목록」(판이 읽기 전 빈 목록 · 관 하나 지움 ↶ 이 같은 목록으로 멈춤 → 배수판 · 시설 줄 · 알약 · 목록 관 없음 · −17,385.4 · B06 보기 배수유역도 관 · 세부유역 빠짐) 걷음 · 종단 ↶ ↷ 켜짐 = 사진첩 change 알림으로 바로(삭제 직후 꺼져 있던 흠) · 시험 test_472_d_b05_pipe_undo(옛 코드 빨강 2) · 옛 단언 215_1 이름 · 219_1 흉내 · 위키 operations_common · _b05 · rules 줄

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-19 16:45:44 +09:00
co-authored by Claude Opus 5.5
parent b14de92621
commit be9d1b9185
12 changed files with 261 additions and 42 deletions
@@ -20,6 +20,7 @@ import { adjustStation } from "./logic/B05_Profile_UI_Profile_Alignment";
import { HOLD_DELAY_MS, HOLD_INTERVAL_MS } from "./B05_Profile_UI_Profile_Edit";
import {
createProfileHistory,
onPageHistory,
setPageHistory,
type ProfileHistory,
} from "./B05_Profile_UI_Profile_History";
@@ -63,8 +64,7 @@ export interface PanelToolsContext {
moveStation: (station: IrregularStation, toChainageM: number) => void;
/** 관 목록 정본 — 되돌리기가 구조물 위치까지 되돌리려면 이력이 이 값을 봐야 한다. */
drainage: {
pipeChainages: () => number[];
setPipeChainages: (chainages: number[]) => void;
setPipeChainages: (chainages: number[] | null) => void;
};
/** 세션 복원 후 화면을 다시 세운다(편집 초안 재적재 포함). */
restore: () => void;
@@ -83,38 +83,26 @@ export interface PanelTools {
handleToolPick: (chainageM: number | null) => boolean;
/** 창 키 듣기를 잇고 뗀다 — 종단도가 숨거나 떠나면 뗀다(계획서 24-3a). */
setListening: (on: boolean) => void;
/** 사진첩 알림을 뗀다 — 종단도를 버릴 때. */
disposeTools: () => void;
}
export function createPanelTools(ctx: PanelToolsContext): PanelTools {
/** 이력이 처음 본 관 목록 — 최초 스냅샷에는 아직 키가 없어 여기로 되돌린다. */
let initialPipes: number[] | null = null;
/** 관 자리는 가게 관 초안(`pipes` · 사진에 듦)이 정본 — 찍기 직전엔 처음 본 목록만 잡아 둔다. */
function syncPipes(): void {
if (initialPipes === null) initialPipes = ctx.drainage.pipeChainages();
}
/** 스냅샷을 되돌린 뒤 관 위치도 그 시점 초안으로 맞춘다(초안 없는 걸음 = 처음 목록). 같은 목록이면 조용히 끝난다. */
/** 스냅샷을 되돌린 뒤 관 위치도 그 시점 초안으로 맞춘다 — 관 자리는 가게 관 초안(`pipes` · 사진에 듦)이
* 정본 · 초안 없는 걸음 = 저장분(null · 옛 「처음 본 목록」은 판이 읽기 전 빈 목록이라 관 하나 지움 ↶ 이
* 같은 목록으로 멈췄음 · 472 덧). 같은 목록이면 조용히 끝난다. */
function restorePipes(): void {
const draft = useDesignStore(draftProjectId(), null).get("pipes");
const chainages = draft
? draft.map((pipe) => Math.round(pipe.chainage_m * 100) / 100)
: initialPipes;
if (chainages) ctx.drainage.setPipeChainages(chainages);
ctx.drainage.setPipeChainages(
draft ? draft.map((pipe) => Math.round(pipe.chainage_m * 100) / 100) : null,
);
}
// 계획선 편집만 되돌리면 구조물 위치가 어긋난다(사용자 확정 ⑥ — 범위는 B05 조작 전부).
/** 찍기 직전(세울 때 · 쉬는 동안 온 값 덮을 때 · 연속 조작 멈출 때) 처음 본 관 목록을 잡는다 —
* 그래야 그 목록이 조작 **전** 값으로 잡혀 되돌리기가 시작 자리로 돌아온다(2026-09-04 실측). */
const inner = createProfileHistory(
() => {
ctx.restore();
restorePipes();
},
100,
syncPipes,
);
const history: ProfileHistory = { ...inner, pause: () => (syncPipes(), inner.pause()) };
const history = createProfileHistory(() => {
ctx.restore();
restorePipes();
}, 100);
setPageHistory(history); // 페이지 사진첩 하나 — 노선 편집기도 이것으로 쌓고 되돌림(346-4)
// [자유지정] — 적용은 직선화 결과와 같은 길(applyEdits · 이력 · 막기 규칙)(215-1).
@@ -173,10 +161,10 @@ export function createPanelTools(ctx: PanelToolsContext): PanelTools {
},
canResetToSaved: ctx.canRestoreSaved,
// 자유지정 동안 ↶ ↷ = 자유지정 안 한 걸음(367-3) — 큰 이력은 안 건드림.
onUndo: () => (tools.mode() === "free" ? (free.undo(), freeView.redraw()) : inner.undo()),
onRedo: () => (tools.mode() === "free" ? (free.redo(), freeView.redraw()) : inner.redo()),
canUndo: () => (tools.mode() === "free" ? free.canUndo() : inner.canUndo()),
canRedo: () => (tools.mode() === "free" ? free.canRedo() : inner.canRedo()),
onUndo: () => (tools.mode() === "free" ? (free.undo(), freeView.redraw()) : history.undo()),
onRedo: () => (tools.mode() === "free" ? (free.redo(), freeView.redraw()) : history.redo()),
canUndo: () => (tools.mode() === "free" ? free.canUndo() : history.canUndo()),
canRedo: () => (tools.mode() === "free" ? free.canRedo() : history.canRedo()),
hasStraightRuns: () => {
const alignment = ctx.alignment();
return alignment ? hasStraightRuns(alignment) : false;
@@ -400,5 +388,7 @@ export function createPanelTools(ctx: PanelToolsContext): PanelTools {
window.addEventListener("keydown", onEscape, true);
} else stopHold();
};
return { tools, history, handleToolPick, setListening };
// 삭제 직후 등 다시 그리기 전에도 ↶ ↷ 켜짐을 맞춤(472 덧 — 종단 ↶ 가 꺼진 채 남던 흠)
const disposeTools = onPageHistory({ change: () => tools.syncHistory() });
return { tools, history, handleToolPick, setListening, disposeTools };
}