Keep the place search, language listener, logo gaze and Google key for the page session

An engine switch no longer recreates them: with a layer session they live until the page lifetime aborts; a host without one keeps the per-application lifetime.
This commit is contained in:
German Khokhlov committed 2026-11-03 17:13:07 +04:00
1 parent f0c2523ac4
commit 35ed499ae4
2 files changed
+55 -22

No files matched your search

+21 -9
View File
@@ -39,15 +39,27 @@ export async function createApplicationScene({
signal: layerSession?.lifetime.signal ?? signal,
});
if (layerSession) layerSession.operations = operations;
defer(initLogoGaze());
const previousKey = window.__GOOGLE_MAPS_API_KEY__;
if (googleApiKey) {
window.__GOOGLE_MAPS_API_KEY__ = googleApiKey;
defer(() => {
if (window.__GOOGLE_MAPS_API_KEY__ !== googleApiKey) return;
if (previousKey === undefined) delete window.__GOOGLE_MAPS_API_KEY__;
else window.__GOOGLE_MAPS_API_KEY__ = previousKey;
});
// The logo's gaze and the page's Google key belong to the page session
// when there is one: an engine switch keeps them.
const pageChrome = layerSession ? (layerSession.chrome ??= {}) : null;
const own = pageChrome
? (release) =>
layerSession.lifetime.signal.addEventListener('abort', release, {
once: true,
})
: defer;
if (!pageChrome?.sceneChrome) {
if (pageChrome) pageChrome.sceneChrome = true;
own(initLogoGaze());
const previousKey = window.__GOOGLE_MAPS_API_KEY__;
if (googleApiKey) {
window.__GOOGLE_MAPS_API_KEY__ = googleApiKey;
own(() => {
if (window.__GOOGLE_MAPS_API_KEY__ !== googleApiKey) return;
if (previousKey === undefined) delete window.__GOOGLE_MAPS_API_KEY__;
else window.__GOOGLE_MAPS_API_KEY__ = previousKey;
});
}
}
// A cached renderer is built once, by the first application that asks for
// its engine, and later applications reuse it warm. Everything this closure
+34 -13
View File
@@ -31,6 +31,11 @@ export function pageEngineKind() {
return resolveEngineKind({ search: globalThis.location?.search, storage });
}
/** The page-session state shared by every application on that session. */
function sessionChrome(layerSession) {
return (layerSession.chrome ??= {});
}
/** Compose one engine session. Destroy it before starting another. */
export function createStandaloneApplication({
googleApiKey,
@@ -64,22 +69,38 @@ export function createStandaloneApplication({
let catalog;
const application = createApplication({
createScene: async (context) => {
// The page's language listener and place search belong to the page
// session when there is one (an engine switch keeps them), else to
// this application.
const session = layerSession ? sessionChrome(layerSession) : null;
// A language switch applies in place; the page's own markup follows.
context.defer(
onLocaleChange(() => {
if (!session?.locale) {
const offLocale = onLocaleChange(() => {
applyDocumentLanguage(document, getLocale());
applyDocumentTranslations(document);
}),
);
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,
});
});
if (session) {
session.locale = offLocale;
layerSession.lifetime.signal.addEventListener('abort', offLocale, {
once: true,
});
} else context.defer(offLocale);
}
const createPlaceSearch = (signal) =>
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,
});
placeSearch = session
? (session.placeSearch ??= createPlaceSearch(
layerSession.lifetime.signal,
))
: createPlaceSearch(context.signal);
const scene = await createStandaloneScene({
...context,
googleApiKey,