feat(종단보기): 346-2 덧 2 B05 종단 보기 · 3D 측점선도 갈아끼운 상세로 — 보일 때만 · 숨었으면 다시 보일 때 · 횡단 보기 없이도
- design_view_profile_sections: 노선마다 상세 갈아끼움을 듣고 종단도 · 표 · 3D 측점선 다시(보일 때만 · 숨으면 flushSwap 이 다시 보일 때) · 가게 stations 도 들어 횡단 보기를 안 열어도 갈아끼움(먼저 부른 쪽만 · 다음은 「같은 목록」) - design_view_profile: 받는 줄만(보임 · 떠날 때 끊음 · 다시 보일 때 flushSwap) - 갈아끼움 알림판 B06_Section_Swap_Bus(가져오기 없음 · 돌고 도는 가져오기 막음) — 조정창 값 · 암 경계 옮김을 어느 보기가 갈아끼웠든 한 번 · 횡단 보기는 알림으로 다시 그림 - 시험: 종단 보기 보임 7 → 8 · 숨음 = 안 그림 · 다시 보임 = 6 · 3D 측점선 같은 차례 · 옛 시험 둘(342-1 화면 선 = listedBase · 323-9 열쇠 모듈 진짜로) 맞춤 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QfHKQs7J3hQELKMWQMUJEy
This commit is contained in:
@@ -38,6 +38,9 @@ import {
|
||||
useStationKeyList,
|
||||
} from "./B06_Section_Station_Keys";
|
||||
import { sameStationList, swapCrossSections } from "./logic/B06_Section_Station_Swap";
|
||||
import { emitSwap, type DetailListener } from "./B06_Section_Swap_Bus";
|
||||
|
||||
export { onAnySwap } from "./B06_Section_Swap_Bus";
|
||||
|
||||
const cache = new Map<string, SectionDetailResponse>();
|
||||
const pending = new Map<string, Promise<SectionDetailResponse>>();
|
||||
@@ -111,8 +114,6 @@ export async function loadSectionDetail(
|
||||
return request;
|
||||
}
|
||||
|
||||
/** 새 상세 · 이어 받은 측점의 누가거리 옮김(옛 0.01 m 글 → 새 글 · 조작값 맵을 옮길 때). */
|
||||
type DetailListener = (detail: SectionDetailResponse, moves: ReadonlyMap<string, string>) => void;
|
||||
const listeners = new Map<string, Set<DetailListener>>();
|
||||
|
||||
/** 상세 객체가 갈아끼워짐(측점 수가 바뀜 · 346-2 4파) — 쥔 옛 객체를 버리고 새것으로 다시 그릴 것. */
|
||||
@@ -154,6 +155,7 @@ export async function swapSectionStations(
|
||||
await withDraftShapes(swap.detail, projectId); // 새 측점에도 구조물 그림 자료(323-4)
|
||||
withStructureAreas(swap.detail);
|
||||
if (cache.get(key) !== swap.detail) return null; // 그 사이 다른 갈아끼움 · 새로 받음
|
||||
emitSwap(swap.detail, swap.moves); // 세션 값 옮김 · 다시 그림(어느 보기든)
|
||||
listeners.get(key)?.forEach((fn) => fn(swap.detail, swap.moves));
|
||||
return { detail: swap.detail, moves: swap.moves };
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/* =============================================================================
|
||||
* B06_Section_Swap_Bus.ts
|
||||
* 상세 갈아끼움 알림판(PLAN 346-2) — 측점 수가 바뀌어 `Section_Store` 가 상세 객체를 갈아끼우면 여기로 알림.
|
||||
* 가져오는 것 없음 — 세션 조작값 맵(`_UI_Page_Link_Session`) · 암 경계 저장소(`_UI_Page_Persist`)가 모듈을 읽을 때
|
||||
* 붙어도 `Section_Store` 와 돌고 도는 가져오기가 안 생김.
|
||||
* ========================================================================== */
|
||||
|
||||
import type { SectionDetailResponse } from "./B06_Section_Api_Types";
|
||||
|
||||
/** 새 상세 · 이어 받은 측점의 누가거리 옮김(옛 0.01 m 글 → 새 글 · 조작값 맵을 옮길 때). */
|
||||
export type DetailListener = (
|
||||
detail: SectionDetailResponse,
|
||||
moves: ReadonlyMap<string, string>,
|
||||
) => void;
|
||||
|
||||
const anyListeners = new Set<DetailListener>();
|
||||
|
||||
/** 어느 노선이든 상세가 갈아끼워지면 부름(조정창 값 · 암 경계 옮김 · 다시 그림) — 돌려준 함수로 끊음. */
|
||||
export function onAnySwap(fn: DetailListener): () => void {
|
||||
anyListeners.add(fn);
|
||||
return () => anyListeners.delete(fn);
|
||||
}
|
||||
|
||||
/** 갈아끼운 쪽(`Section_Store`)이 부름. */
|
||||
export function emitSwap(detail: SectionDetailResponse, moves: ReadonlyMap<string, string>): void {
|
||||
anyListeners.forEach((fn) => fn(detail, moves));
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
import { culvertCardState } from "./B06_Section_UI_Cross_View_Structure";
|
||||
import type { PipeRevetChoice } from "../A00_Common/design/design_structure_pipe_calc";
|
||||
import { renameChainageKeys } from "./logic/B06_Section_Station_Swap";
|
||||
import { onAnySwap } from "./B06_Section_Swap_Bus";
|
||||
|
||||
/** 세션에 담기는 측점별 조작값 한 겹 맵. */
|
||||
export interface SessionMap<V> {
|
||||
@@ -65,6 +66,9 @@ export function moveSessionMaps(moves: ReadonlyMap<string, string>): void {
|
||||
}
|
||||
}
|
||||
|
||||
// 상세 갈아끼움(어느 보기가 했든)마다 한 번 — 조정창 값을 옮긴 측점 자리로
|
||||
onAnySwap((_detail, moves) => moveSessionMaps(moves));
|
||||
|
||||
export function createSessionMap<V>(
|
||||
sessionKey: () => string | null,
|
||||
accept: (value: unknown) => V | undefined,
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
type SectionDetailResponse,
|
||||
} from "./B06_Section_Api_Fetch";
|
||||
import { invalidateSectionDetail } from "./B06_Section_Section_Store";
|
||||
import { onAnySwap } from "./B06_Section_Swap_Bus";
|
||||
import type { DesignViewSave } from "../A00_Common/design/design_shared";
|
||||
import { buildCrossPatches, type CrossPatchSources } from "./B06_Section_UI_Page_Patches";
|
||||
import {
|
||||
@@ -87,6 +88,9 @@ export function reloadKeyedStores(): void {
|
||||
keyedStores.forEach((store) => store.load());
|
||||
}
|
||||
|
||||
// 상세 갈아끼움(어느 보기가 했든)마다 한 번 — 암 경계 · 암 경사를 새 목록 누가거리로 다시 읽음
|
||||
onAnySwap(() => reloadKeyedStores());
|
||||
|
||||
/** 세션 열쇠 글(`aislo:draft:rockb:{p}:{r}`)의 프로젝트 · 노선 — 저장소가 측점 열쇠 창구로 읽고 씀. */
|
||||
function keyedScope(storageKey: string): { projectId: string; routeId: number } | null {
|
||||
const [projectId, route] = storageKey.split(":").slice(-2);
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
/* =============================================================================
|
||||
* B06_Section_UI_Page_Station_Swap.ts
|
||||
* 횡단 보기가 계산 묶음 측점을 따라감(PLAN 346-2 4파) — 가게 `stations` 가 측점 목록을 바꾸면(늘고 줄면)
|
||||
* 상세 객체를 갈아끼우고(`swapSectionStations`) 조정창 값 · 암 경계 · 암 경사를 새 자리로 옮긴 뒤 보일 때 카드 ·
|
||||
* 종단도를 다시(카드는 보이는 것 먼저 · 다시 셈은 그 길이 맡음 · 안 보이면 다시 보일 때 그림).
|
||||
* 상세 객체를 갈아끼우고(`swapSectionStations` · 조정창 값 · 암 경계 · 암 경사 옮김은 `onAnySwap` 이 맡음) 보일 때
|
||||
* 카드 · 종단도를 다시(카드는 보이는 것 먼저 · 다시 셈은 그 길이 맡음 · 안 보이면 다시 보일 때 그림).
|
||||
* 종단 보기도 같은 가게를 듣고 같은 함수를 부름 — 먼저 부른 쪽이 갈아끼우고 다음 쪽은 「같은 목록」.
|
||||
* ========================================================================== */
|
||||
|
||||
import { useDesignStore } from "../A00_Common/design/design_store";
|
||||
import { swapSectionStations } from "./B06_Section_Section_Store";
|
||||
import { moveSessionMaps } from "./B06_Section_UI_Page_Link_Session";
|
||||
import { reloadKeyedStores } from "./B06_Section_UI_Page_Persist";
|
||||
import { onAnySwap, swapSectionStations } from "./B06_Section_Section_Store";
|
||||
|
||||
/** 묶음 측점을 따라감 — 돌려준 함수로 끊음. `redraw` = 캐시에서 상세를 다시 읽어 카드 · 그림 다시. */
|
||||
export function followSwaps(
|
||||
@@ -18,14 +17,14 @@ export function followSwaps(
|
||||
redraw: () => Promise<void>,
|
||||
): () => void {
|
||||
if (!projectId) return () => undefined;
|
||||
return useDesignStore(projectId, null).subscribe("stations", (stations) => {
|
||||
// 누가 갈아끼웠든(종단 보기가 먼저 불렀어도) 보이면 다시 그림 — 한 페이지 한 노선
|
||||
const stopRedraw = onAnySwap(() => void (host.visible() && redraw()));
|
||||
const stopStore = useDesignStore(projectId, null).subscribe("stations", (stations) => {
|
||||
const route = routeId();
|
||||
if (route === null || !stations?.length) return;
|
||||
void swapSectionStations(projectId, route, stations).then((swap) => {
|
||||
if (!swap) return; // 같은 목록 — 제자리 갱신 길이 맡음
|
||||
moveSessionMaps(swap.moves); // 조정창 값(반폭 · 기슭막이 · 유입 · 집수정 · 추가 벽)
|
||||
reloadKeyedStores(); // 암 경계 · 암 경사 = 측점 열쇠 세션 → 새 목록 누가거리로
|
||||
if (host.visible()) void redraw();
|
||||
});
|
||||
if (route !== null && stations?.length) void swapSectionStations(projectId, route, stations);
|
||||
});
|
||||
return () => {
|
||||
stopRedraw();
|
||||
stopStore();
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user