mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
fix(street-level): review round — safer docking, mount retry, provider fallthrough
- Only a user's own collapse docks a floating window; cockpit entry, restores and the Cyber accordion no longer dock it or delete its saved place, and the accordion leaves floating windows alone. - The viewer host records an adapter as active only after its mount succeeds, so a library that failed to load once is retried; concurrent opens share one mount, and unmounting mid-mount leaves nothing active. - openNearest tries every active provider; one provider's error (no key, offline) no longer hides the others' imagery. - The SINCE readout shows its cut-off date as soon as the committed value matches the thumb, even while the slider keeps focus. - A floating window that was only dragged is bounded to the viewport and scrolls instead of running off-screen. - getStats summarises coverage (summarizeCoverage) instead of building a full UI snapshot every second; disable() uses credits.hideAll(); smaller cleanups in the viewer host and sequence snapshot. - Unit tests: panel docking and header double press, viewer-host mount retry/sharing/cancel, coverage summary. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
5877f24f0b
commit
6207e4144e
12 files changed
+425
-55
No files matched your search
@@ -6,6 +6,8 @@
|
||||
export function createViewerHost({ state, parts }) {
|
||||
/** @type {{id: string, adapter: object, unsubscribe: () => void}|null} */
|
||||
let active = null;
|
||||
/** @type {{id: string, promise: Promise<object>}|null} */
|
||||
let mounting = null;
|
||||
let openSeq = 0;
|
||||
|
||||
function notify() {
|
||||
@@ -51,20 +53,50 @@ export function createViewerHost({ state, parts }) {
|
||||
if (current !== sequenceId) entry.instance.selectSequence(sequenceId);
|
||||
}
|
||||
|
||||
async function mount(entry) {
|
||||
if (active?.id === entry.def.id) return active.adapter;
|
||||
/**
|
||||
* Mount a provider's viewer adapter in the host. The adapter becomes
|
||||
* `active` only once its mount succeeded, so a failed mount (a library
|
||||
* that did not load) is retried on the next open; concurrent opens for the
|
||||
* same provider share one mount.
|
||||
*/
|
||||
function mount(entry) {
|
||||
if (active?.id === entry.def.id) return Promise.resolve(active.adapter);
|
||||
if (mounting?.id === entry.def.id) return mounting.promise;
|
||||
if (active) {
|
||||
active.adapter.close();
|
||||
active.unsubscribe();
|
||||
active.adapter.unmount();
|
||||
active = null;
|
||||
}
|
||||
const { adapter } = { adapter: entry.instance.viewer };
|
||||
const unsubscribe = adapter.onPose(applyPose);
|
||||
active = { id: entry.def.id, adapter, unsubscribe };
|
||||
await adapter.mount(state.street.host);
|
||||
adapter.setRenderMode?.(state.street.renderMode);
|
||||
return adapter;
|
||||
const adapter = entry.instance.viewer;
|
||||
const promise = (async () => {
|
||||
const unsubscribe = adapter.onPose(applyPose);
|
||||
try {
|
||||
await adapter.mount(state.street.host);
|
||||
} catch (error) {
|
||||
unsubscribe();
|
||||
throw error;
|
||||
}
|
||||
if (mounting?.promise !== promise) {
|
||||
// Unmounted (layer off, provider switched) while loading.
|
||||
unsubscribe();
|
||||
adapter.unmount();
|
||||
throw new Error('Street-level viewer was closed');
|
||||
}
|
||||
active = { id: entry.def.id, adapter, unsubscribe };
|
||||
adapter.setRenderMode?.(state.street.renderMode);
|
||||
return adapter;
|
||||
})();
|
||||
mounting = { id: entry.def.id, promise };
|
||||
promise.then(
|
||||
() => {
|
||||
if (mounting?.promise === promise) mounting = null;
|
||||
},
|
||||
() => {
|
||||
if (mounting?.promise === promise) mounting = null;
|
||||
},
|
||||
);
|
||||
return promise;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,6 +204,7 @@ export function createViewerHost({ state, parts }) {
|
||||
/** Tear the mounted adapter down (layer disabled or destroyed). */
|
||||
function unmount() {
|
||||
close();
|
||||
mounting = null;
|
||||
if (!active) return;
|
||||
active.unsubscribe();
|
||||
active.adapter.unmount();
|
||||
|
||||
Reference in new issue
Block a user