Files
gods-eye-view/src/standalone/application.js
T
Sameh Khamis a2f61d4def feat: load Google 3D with short-lived server tokens
Without a browser key, the app asks its server for a short-lived Google
access token (GET /api/google/tiles-token, answering accessToken and
expiresAt) and loads Photorealistic 3D Tiles directly with it as a
header. A tile refused for an expired token gets a renewed one and is
retried once. A server that does not offer tokens changes nothing: the
app continues through ion or the keyless globe as before.
2026-10-04 10:49:06 -07:00

76 lines
2.7 KiB
JavaScript

import { createStandaloneCatalog } from './catalog.js';
import { createStandalonePlaceSearch } from './placeSearch.js';
import { CITY_POIS } from '../locations.js';
import { createApplication } from '../app/application.js';
import { createStandaloneScene } from './scene.js';
import { createStandaloneControls } from './controls.js';
import { createStandaloneData } from './data.js';
import { createStandaloneTools } from './tools.js';
import { createGoogleTokenSource } from '../maps/googleTokens.js';
// The existing controls and layer catalog contain page-scoped state.
let constructed = false;
/** Compose the standalone application once per page. Reload to start again. */
export function createStandaloneApplication({
googleApiKey,
cesiumToken,
geospatial = {},
voice = {},
allowQaRegistration = false,
}) {
if (constructed)
throw new Error('The standalone application already owns this page');
constructed = true;
const loadingScreen = document.getElementById('loading-screen');
const loaderStatus = loadingScreen.querySelector('.loader-status');
let placeSearch;
let catalog;
return createApplication({
createScene: async (context) => {
placeSearch = createStandalonePlaceSearch({
// The bundled city and landmark data the offline name provider reads.
// The search package takes it as plain data rather than importing it,
// so it stays free of application state.
presets: CITY_POIS,
...geospatial,
resolveApiKey: () => googleApiKey,
signal: context.signal,
});
const scene = await createStandaloneScene({
...context,
googleApiKey,
// Without a key, Google 3D can still load with tokens from the
// app's server when it offers them.
googleTokens: googleApiKey ? null : createGoogleTokenSource(),
cesiumToken,
loaderStatus,
});
catalog = createStandaloneCatalog({
nepalBoundaryResolver: (signal) =>
scene.operations.annotationResolver.resolveRegionRingForQuery(
'Nepal',
signal,
placeSearch,
// The locator draws the border whenever it arrives.
{ budgetMs: Infinity },
),
signal: context.signal,
surface: scene.operations.surface,
});
return scene;
},
createControls: (context) =>
createStandaloneControls({
...context,
loaderStatus,
placeSearch,
catalog,
}),
createData: (context) =>
createStandaloneData({ ...context, allowQaRegistration, catalog }),
createTools: (context) =>
createStandaloneTools({ ...context, loadingScreen, placeSearch, voice }),
});
}