Files
Aislo/A00_Common/design/design_pipeline_facilities.ts
T
eomsangdonandClaude Opus 5.5 7f3aa6da65 fix(429 [저장] 길): 노선 저장 뒤 횡단 저장 늘 한 번 · 상단측 차례 사용자 값 남김 · 추가 측점 = 계산 줄 입력 · 차례 실패 = 멈춤과 알림
- ④ 노선 저장 뒤 횡단 저장 = 고침 없어도 한 번(뒤에 나간 계획고 초안이 횡단 설계 높이에 실림)
- ⑤ 상단측 다시 셈 = 깎기 경사 · 소단을 기하 입력으로 · 사용자 조작값 목록째 승계 · 측구 끔(None) 저장분 셈
- ⑨ 추가 측점 = 묶음 입력 plusStations(stations 부터) · 가게 초안 · 되돌리기 → 묶음
- ⑨ [저장] 차례 실패 = 그 차례에서 멈춤 · 차례 이름째 알림(뒤 차례 안 보냄)
- 시험 test_429_save_path · test_design_store_save 멈춤 규칙으로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QyNXY2TUKXCFMwAca2APG
2026-10-18 15:47:10 +09:00

74 lines
3.3 KiB
TypeScript

/* =============================================================================
* A00_Common/design/design_pipeline_facilities.ts
* 계산 묶음 관 · 구조물 · 추가 측점 먹이기(PLAN 415 · 429 ⑨) — 가게 초안이 바뀌면 묶음에 넣음(비면 저장분).
* · [저장] 도중 = 안 넣음(H2) — 초안이 비는 사이 열 때 읽은 옛 저장분으로 돌지 않게 · 끝나면 `resync`
* (저장 목록 다시 읽기 · 입력 맞춤) 한 번.
* · 되돌리기 · 다시하기 = 세션만 되쓰고 가게 알림이 없음 → 묶음 입력과 견줘 다르면 넣음(415-2 · 노선 초안은
* 노선 길이 맡음).
* 저장 창구는 늦게 불러옴(묶음 시험이 화면 모듈을 안 끌게).
* ========================================================================== */
import { onPageHistory } from "../../B05_Profile/B05_Profile_UI_Profile_History";
import type { useDesignStore } from "./design_store";
import type { ChangeSource } from "./logic/design_pipeline_types";
type Key = "pipes" | "structures" | "plusStations";
const FACILITIES: ReadonlyArray<{ source: ChangeSource; key: Key }> = [
{ source: "pipe", key: "pipes" },
{ source: "structure", key: "structures" },
{ source: "plus", key: "plusStations" },
];
export interface FacilityFeed {
saving(): boolean;
/** 저장이 끝나면 `resync` 한 번 — 기다리는 동안 다시 불러도 한 번. */
afterSave(): void;
stop(): void;
}
export function feedFacilities(o: {
projectId: string;
store: ReturnType<typeof useDesignStore>;
/** 묶음이 받을 때인가(열었음 · 묶음이 가게에 쓰는 메아리 아님). */
ready: () => boolean;
gone: () => boolean;
saved: (key: Key) => unknown;
input: (key: Key) => unknown;
/** 노선 초안이 걸렸나 — 되돌리기는 노선 길이 맡음. */
routed: () => boolean;
feed: (source: ChangeSource, value: unknown) => void;
resync: () => Promise<unknown>;
}): FacilityFeed {
let savingOf: ((id: string) => boolean) | null = null;
// 한 번 불러 봄 — 덜 선 모듈(시험 싣개의 고리)은 안 받음
void import("./design_save")
.then((m) => (m.savingDesign(o.projectId), (savingOf = m.savingDesign)))
.catch(() => undefined);
const saving = (): boolean => savingOf?.(o.projectId) ?? false;
let waiting: Promise<void> | null = null;
const afterSave = (): void => {
waiting ??= (async () => {
// ponytail: 100 ms 마다 물음 — 저장 끝 알림이 생기면 그것으로
while (saving() && !o.gone()) await new Promise((done) => setTimeout(done, 100));
if (!o.gone()) await o.resync();
})().finally(() => (waiting = null));
};
const put = (source: ChangeSource, value: unknown): void =>
saving() ? afterSave() : o.feed(source, value);
const stops = [
...FACILITIES.map(({ source, key }) =>
o.store.subscribe(key, (value) => o.ready() && put(source, value ?? o.saved(key))),
),
onPageHistory({
restore: () => {
if (!o.ready() || o.routed()) return;
for (const { source, key } of FACILITIES) {
const now = o.store.get(key) ?? o.saved(key);
if (JSON.stringify(now) !== JSON.stringify(o.input(key))) put(source, now);
}
},
}),
];
return { saving, afterSave, stop: () => stops.forEach((stop) => stop()) };
}