refactor(app): share application components and request services

This commit is contained in:
Sameh Khamis committed 2026-09-13 22:41:11 -07:00
1 parent a0a0128a59
commit a67bc60a29
84 files changed
+2798 -1731

No files matched your search

+5 -117
View File
@@ -1,120 +1,8 @@
import { SceneDirector } from '../scenes/director.js';
import { initAnnotations } from '../annotations/index.js';
import { initGevVoiceCommands } from '../voice/gevRealtime.js';
import { installScopeMask, destroyScopeMask } from '../scopeMask.js';
import {
installRenderGovernor,
getRenderGovernorDiagnostics,
governorRequestRender,
holdContinuousRender,
releaseContinuousRender,
} from '../renderGovernor.js';
import { createApplicationTools } from '../app/tools.js';
import { startStandaloneChrome } from './startupChrome.js';
/** Attach scene tools, rendering listeners and the standalone debug handle. */
export function createStandaloneTools({
scene,
controls,
data,
loadingScreen,
placeSearch,
voice = {},
signal,
defer,
}) {
const { viewer, tileset, mapStackController } = scene;
const { styleManager, weatherEffects, cockpitCloudEffects } = controls;
const { dataManager } = data;
const sceneDirector = new SceneDirector(viewer, styleManager, dataManager);
defer(() => sceneDirector.destroy());
const annotations = initAnnotations({ viewer, tileset, placeSearch });
defer(() => {
if (window.__gevAnnotations === annotations) delete window.__gevAnnotations;
annotations.destroy();
export function createStandaloneTools(options) {
return createApplicationTools({
startChrome: startStandaloneChrome,
...options,
});
defer(
startStandaloneChrome({ loadingScreen, styleManager, dataManager, signal }),
);
// Idle render governor: flips the scene into requestRenderMode whenever
// nothing animates per frame. Installed AFTER every module above has had
// its chance to register pre-install holds. (perf wave 2)
installRenderGovernor(viewer);
// Install the explicit scope mask used by the DISPLAY controls.
installScopeMask(viewer);
defer(() => destroyScopeMask());
// The follow camera recomputes the tracked target's dead-reckon position
// every frame — tracking anything is a per-frame animation. (perf wave 2)
const removeTrackingListener = viewer.trackedEntityChanged.addEventListener(
() => {
if (viewer.trackedEntity) holdContinuousRender('tracked-entity');
else releaseContinuousRender('tracked-entity');
},
);
// Hidden-state suspension (perf wave 2): when the window/tab is hidden,
// stop the default render loop outright — a hidden canvas repaints for
// nobody, and browser rAF throttling still lets throttled frames burn
// GPU. Holder/data state is untouched, so return is seamless: restore
// the loop, refresh the one DOM surface we gated, render a frame.
const syncVisibilitySuspension = () => {
const hidden = document.hidden;
viewer.useDefaultRenderLoop = !hidden;
cockpitCloudEffects?.setSuspended?.(hidden);
if (!hidden) {
if (dataManager._panelRefreshPendingOnVisible) {
dataManager._panelRefreshPendingOnVisible = false;
dataManager._refreshTogglePanel();
}
governorRequestRender('visibility-restore');
}
};
document.addEventListener('visibilitychange', syncVisibilitySuspension);
defer(() =>
document.removeEventListener('visibilitychange', syncVisibilitySuspension),
);
defer(() => {
removeTrackingListener();
releaseContinuousRender('tracked-entity');
});
// Apply the CURRENT state too — bootstrap can complete while the tab is
// already hidden, and waiting for the next transition would leave the
// loop burning behind a hidden tab. (perf wave 2 fix)
syncVisibilitySuspension();
window.__godsEyeView = {
viewer,
styleManager,
tileset,
dataManager,
sceneDirector,
mapStackController,
annotations,
weatherEffects,
cockpitCloudEffects,
getRenderGovernorDiagnostics,
requestRender: governorRequestRender,
};
const debug = window.__godsEyeView;
defer(() => {
if (window.__godsEyeView === debug) delete window.__godsEyeView;
});
const voiceCommands = initGevVoiceCommands({
...voice,
signal,
placeSearch,
viewer,
styleManager,
dataManager,
sceneDirector,
annotations,
});
defer(() => {
voiceCommands.stop({ removeUi: true });
if (window.__gevVoiceCommands === voiceCommands)
delete window.__gevVoiceCommands;
});
debug.voiceCommands = voiceCommands;
return { sceneDirector, annotations, voiceCommands };
}