import { loadGeoJSONFromPath, loadLandingPoints, getCableLegendItems, toggleCables, } from "./cables.js"; import { clearSatelliteData, getSatelliteLegendItems, loadSatellites, toggleSatellites, } from "./satellites.js"; import { loadBGPAnomalies, toggleBGP, } from "./bgp.js"; /** * Layer startup task registry. * * This module is the startup-task counterpart to the layer registry in controls.js: * - controls.js owns layer metadata such as startupPriority/startupMode/startupMessage * - this file owns the executable startup task factory for each layer id * * A startup task is registered via registerLayerStartupTask(id, taskFactory). * The taskFactory receives a startup context from main.js and must return an async * function with the signature async (layerDefinition) => void. * * Put a task here only when a layer needs dedicated startup loading work: * - preloading data at boot * - staged loading with progress/loading messages * - post-load UI refresh or warmup * * Do not put plain visibility toggles or persistent UI state here; those still belong * to the layer registry/state flow in controls.js. */ const startupTaskRegistry = new Map(); export function resolveStartupMessage(layer, key, fallback) { const message = layer?.startupMessage; if (message && typeof message === "object" && key in message) { return message[key]; } if (typeof message === "string" && message.trim()) { return message; } return fallback; } export function createLayerStartupTaskMap(context) { return Object.fromEntries( Array.from(startupTaskRegistry.entries()).map(([id, taskFactory]) => [ id, taskFactory(context), ]), ); } export function registerLayerStartupTask(id, taskFactory) { if (typeof id !== "string" || !id.trim()) { throw new Error("registerLayerStartupTask 需要有效的图层 id"); } if (typeof taskFactory !== "function") { throw new Error("registerLayerStartupTask 需要可调用的任务工厂"); } startupTaskRegistry.set(id, taskFactory); } function registerBuiltinLayerStartupTasks() { startupTaskRegistry.clear(); registerCableStartupTask(); registerSatelliteStartupTask(); registerBGPStartupTask(); } function registerCableStartupTask() { registerLayerStartupTask("cables", (context) => async (layer) => { if (!context.isCablesEnabled()) return; context.setLoadingMessage( resolveStartupMessage(layer, "prepare", "正在加载登陆点..."), ); await context.yieldFrame(12); try { await loadLandingPoints(context.scene, context.earth, { silent: true }); } catch (error) { context.reportError("登陆点", error); } if (context.isCancelled()) return; await context.yieldFrame(16); context.setLoadingMessage( resolveStartupMessage(layer, "load", "正在加载海缆..."), ); await context.yieldFrame(12); try { await loadGeoJSONFromPath(context.scene, context.earth, { silent: true }); if (!context.isCancelled() && context.isCablesEnabled()) { toggleCables(true); context.updateCableToggleUi(true); context.setLegendItems("cables", getCableLegendItems()); context.refreshLegend(); } } catch (error) { context.reportError(layer?.startupLabel || layer?.label || "海缆", error); } if (context.isCancelled()) return; await context.yieldFrame(16); }); } function registerSatelliteStartupTask() { registerLayerStartupTask("satellites", (context) => async (layer) => { if (!context.isSatellitesEnabled()) return; context.setLoadingMessage( resolveStartupMessage(layer, "load", "正在加载卫星..."), ); await context.yieldFrame(12); try { clearSatelliteData(); const loadResult = await loadSatellites({ limit: context.getInitialSatelliteLoadLimit(), }); if (!context.isCancelled() && context.isSatellitesEnabled()) { context.updateSatelliteToggleUi(true, loadResult.count); context.setLegendItems("satellites", getSatelliteLegendItems()); context.refreshLegend(); context.scheduleSatellitePositionWarmup(() => { if (!context.isCancelled() && context.isSatellitesEnabled()) { toggleSatellites(true); } }); if (context.shouldHydrateFullSatelliteSet(loadResult)) { const hydrationToken = context.nextSatelliteHydrationToken(); context.hydrateAllSatellitesInBackground( () => hydrationToken === context.getSatelliteHydrationToken() && !context.isCancelled() && context.isSatellitesEnabled(), ); } } } catch (error) { context.reportError(layer?.startupLabel || layer?.label || "卫星", error); } if (context.isCancelled()) return; await context.yieldFrame(16); }); } function registerBGPStartupTask() { registerLayerStartupTask("bgp", (context) => async (layer) => { context.setLoadingMessage( resolveStartupMessage(layer, "load", "正在加载BGP态势..."), ); await context.yieldFrame(12); try { const bgpResult = await loadBGPAnomalies(context.scene, context.earth); if (!context.isCancelled()) { toggleBGP(context.getShowBGP()); context.updateBGPHud(bgpResult); context.syncBGPKnownEventIds(); } } catch (error) { context.reportError(layer?.startupLabel || layer?.label || "BGP态势", error); } if (context.isCancelled()) return; await context.yieldFrame(16); }); } registerBuiltinLayerStartupTasks();