- 다시 셈(refreshCrossDesigns) 부르는 곳 = 묶음 cross 단계 하나(design_shared savedCross) - 종단 미리 셈 · B06 설계 맞춤 · 3D 업데이트 = pipelineCross · reconcilePagePipeline(▲ 한 번 = cross 한 번) - 입력 칸 밖 세션 고침(노견 · 소단 · 단면 유형 · 조정창)은 forceCross 로 같은 입력이어도 한 번 더 - 카드 그리기 · 횡단 보기 면적 쓰기 지움 · 다시 셈 창구가 면적을 늘 얹음(바뀐 측점만 알림) - 저장 안 한 조정창 값을 상세 가게가 읽을 때 얹음(새 Section_Adjusts · B05 만 열어도 같은 면적) - 새 test_384_4_cross_window · 옛 약속 시험 넷 새 약속으로 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
97 lines
4.4 KiB
TypeScript
97 lines
4.4 KiB
TypeScript
/* =============================================================================
|
|
* B05_Profile_UI_Profile_Preview.ts
|
|
* 계획선 편집 → 횡단 설계 프리뷰 반영 (패널 본체에서 분리, 2026-09-02 · 700줄 한계).
|
|
*
|
|
* 계획고가 바뀌면 측점별 횡단 단면적도 바뀐다 — 다시 셈은 계산 묶음 cross 단계 **한 곳**(`design_shared`
|
|
* savedCross · 387-4)이 하고 여기서는 그 차례만 기다림(▲ 한 번 = cross 한 번). 예전에는 그리기가 낡음을 보면
|
|
* 여기서도 따로 다시 셈 → 묶음과 두 번 셈.
|
|
* 기다리는 동안 「다시 계산 중」 · 묶음 차례가 cross 를 지났는데 남은 낡음은 곡선을 그리고 그 측점만 표시(342-1 · 349-0f).
|
|
* ========================================================================== */
|
|
|
|
import type { AlignmentEdits, ProfileAlignment } from "./logic/B05_Profile_UI_Profile_Alignment";
|
|
import { holdScreenAlignment } from "../B06_Section/B06_Section_Cross_Refresh";
|
|
import { staleChainages } from "../B06_Section/B06_Section_UI_Section_Common";
|
|
import type { SectionDetailResponse } from "../B06_Section/B06_Section_Api_Fetch";
|
|
import { pagePipeline, pipelineCross } from "../A00_Common/design/design_pipeline_page";
|
|
import { useDesignStore } from "../A00_Common/design/design_store";
|
|
import type { DesignPipeline, PipelineEvent } from "../A00_Common/design/logic/design_pipeline";
|
|
|
|
/** cross 를 지났다고 볼 단계(cross 가 같은 입력이라 건너뛰어도 뒤 단계가 알림). */
|
|
const AFTER_CROSS = new Set(["cross", "footprint", "masshaul"]);
|
|
/** 묶음 차례가 cross 를 못 낸 채 끝나도(단계 실패) 「다시 계산 중」을 푸는 때(ms). */
|
|
const DRAFT_WAIT_MS = 3000;
|
|
|
|
export interface CrossPreviewContext {
|
|
projectId: string;
|
|
detail: () => SectionDetailResponse | null;
|
|
routeId: () => number | null;
|
|
edits: () => AlignmentEdits;
|
|
/** 화면이 쥔 계획선(측점 한 벌) — 다시 셈 · B06 · 3D 가 같은 선을 받음(342-1). */
|
|
alignment: () => ProfileAlignment | null;
|
|
/** 부를 때마다 읽음 — 보기마다 다름. */
|
|
debounceMs: () => number;
|
|
/** 반영이 끝난 뒤 다시 그린다 — 다시 계산한 측점 누가거리를 넘긴다(횡단 카드 갱신용). */
|
|
onApplied: (updated: number[]) => void;
|
|
}
|
|
|
|
export interface CrossPreview {
|
|
/** 묶음에 cross 다시 부탁(같은 입력이면 안 셈). */
|
|
schedule: () => void;
|
|
/**
|
|
* 그리기가 잰 낡음 지문 — 돌려주는 값 = 묶음 cross 차례를 기다리는 중인가. 차례가 지난 뒤에도 남은 낡음은
|
|
* false — 곡선은 그리고 그 측점만 표시(342-1 · 사용자 확정 10-16). `_draft` = 옛 갈래(노선 초안) · 같은 길.
|
|
*/
|
|
scheduleIfStale: (key: string, _draft?: boolean) => boolean;
|
|
/** 패널을 걷을 때 기다림 타이머를 끈다. */
|
|
dispose: () => void;
|
|
}
|
|
|
|
export function createCrossPreview(ctx: CrossPreviewContext): CrossPreview {
|
|
let warned = "";
|
|
const release = holdScreenAlignment((routeId) =>
|
|
routeId === ctx.routeId() ? ctx.alignment() : null,
|
|
);
|
|
|
|
/** 기다리는 묶음 차례 — 그 차례 cross(또는 뒤 단계)가 오면 풂. */
|
|
let awaiting: number | null = null;
|
|
let waitTimer = 0;
|
|
let watched: DesignPipeline | null = null;
|
|
const onStage = (event: PipelineEvent): void => {
|
|
if (event.kind === "stage" && event.generation === awaiting && AFTER_CROSS.has(event.stage))
|
|
awaiting = null;
|
|
};
|
|
const stopGeneration = useDesignStore(ctx.projectId, null).subscribe("generation", (gen) => {
|
|
const pipe = pagePipeline(ctx.projectId);
|
|
if (!pipe || gen === null) return;
|
|
if (watched !== pipe) (watched = pipe).subscribe(onStage, "다시 셈 대기");
|
|
awaiting = gen;
|
|
window.clearTimeout(waitTimer);
|
|
waitTimer = window.setTimeout(() => {
|
|
if (awaiting !== gen) return;
|
|
awaiting = null;
|
|
ctx.onApplied([]);
|
|
}, DRAFT_WAIT_MS);
|
|
});
|
|
const warnLeft = (key: string): void => {
|
|
if (!key || key === warned) return;
|
|
warned = key;
|
|
console.warn(
|
|
`[횡단] 다시 셈 뒤에도 낡은 측점 ${staleChainages(key).length}곳 — 곡선은 그리고 그 측점만 표시`,
|
|
staleChainages(key),
|
|
);
|
|
};
|
|
|
|
return {
|
|
scheduleIfStale(key) {
|
|
if (awaiting === null) warnLeft(key);
|
|
return key !== "" && awaiting !== null;
|
|
},
|
|
schedule: () => pipelineCross(ctx.projectId),
|
|
dispose() {
|
|
window.clearTimeout(waitTimer);
|
|
stopGeneration();
|
|
release();
|
|
},
|
|
};
|
|
}
|