From b4ee2321cf1a4e9a9d9656e9a545144dd2aa7e57 Mon Sep 17 00:00:00 2001 From: Sameh Khamis Date: Sun, 1 Nov 2026 13:43:57 -0800 Subject: [PATCH] feat(globe): answer both reset buttons through the globe actions store The top-center and cockpit reset buttons call the location controls' new reset() through the globe actions store, and render a reset under way from it, instead of the location controls binding their clicks and the navigation writing their labels. The store keeps each owner's reset under way like its clear, and controls replaced mid-reset keep it on the buttons. LocationControls no longer takes resetButtons. --- CHANGELOG.md | 11 +++--- docs/VUE-MIGRATION.md | 9 ++--- scripts/qa-location-controls.mjs | 4 +-- src/cockpitMarkup.test.mjs | 32 +++++++---------- src/ui/applicationShell.js | 32 +++++++++++++++-- src/ui/cockpitController.js | 1 - src/ui/commandDock.test.mjs | 2 -- src/ui/globeActions.test.mjs | 45 +++++++++++++++++++++++- src/ui/locationControls.js | 9 +++-- src/ui/locationControls.test.mjs | 5 ++- src/ui/locationNavigation.js | 21 +++--------- src/ui/placeNames.test.mjs | 1 - src/ui/shareButton.test.mjs | 23 +++++++++++++ src/ui/shellElements.js | 2 -- src/ui/stores/globeActions.js | 51 +++++++++++++++++----------- src/ui/views/CockpitView.vue | 5 ++- src/ui/views/panels/GlobeActions.vue | 4 +-- 17 files changed, 173 insertions(+), 84 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31365d3e8..0f5f0e6d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,9 +72,9 @@ are the kit's new `UiChip`. The selects are the kit's new `UiSelect`, the status badges its new `UiBadge` and the one-line empty states its new `UiEmpty`. - The top-center clear, share, tilt and north-up buttons call the shell - through the new globe actions store, which also carries the camera's tilt - and compass heading. `syncScopeControls` (`./ui/display`), + The top-center clear, share, tilt, north-up and reset buttons, and the + cockpit's reset, call the shell through the new globe actions store, + which also carries the camera's tilt and compass heading. `syncScopeControls` (`./ui/display`), `shouldHideCollapsedRightPanels` (`./ui/layout`) and `bindClearLayersControl` (`./ui/layers`) are deprecated: the Display view, the rail and the globe actions view now own what they did. `./ui/input` imports Vue @@ -113,8 +113,9 @@ landmark pills or writes the mini status: it presents the tray, including the search error (`setSearchError()`), and hands it to its `publish` option, and Core's dock renders it and calls `chooseCity()` and - `choosePoi()`. Its `elements` are now only `search`, `searchToggle` and - `resetButtons`. `createOrbitIndicator()` is replaced by + `choosePoi()`. Its `elements` are now only `search` and `searchToggle`: + `resetButtons` is gone, and the reset buttons call its new `reset()`. + `createOrbitIndicator()` is replaced by `showOrbit(active)`, which adds the ORBIT indicator to the presented tray as `orbit: { active }` (null until offered) (samehkhamis). diff --git a/docs/VUE-MIGRATION.md b/docs/VUE-MIGRATION.md index 8d88bc0a2..e3d04b7b7 100644 --- a/docs/VUE-MIGRATION.md +++ b/docs/VUE-MIGRATION.md @@ -225,10 +225,11 @@ a feature supplying only its accent. `splitFlap.js` plans, writing only the label's one text node; the toast renders what each owner's `createToast()` publishes there, on that owner's own timer, and the title bar's FPS readout what - `createFrameRateMonitor()` publishes), the globe actions (in progress: - `GlobeActions` renders the top-center bar; its clear, share, tilt and - north-up buttons call the shell through the `gev-globe-actions` store, - which also carries a clear under way and the camera's tilt and heading + `createFrameRateMonitor()` publishes), the globe actions + (`GlobeActions` renders the top-center bar; its clear, share, tilt, + north-up and reset buttons, and the cockpit's reset, call the shell + through the `gev-globe-actions` store, which also carries a clear or a + reset under way and the camera's tilt and heading that `bindCameraOrientationControls` publishes each drawn frame it changes, which only `GlobeCompass` renders; an owner publishes only while it answers the button, so a shell replaced by a newer one leaves diff --git a/scripts/qa-location-controls.mjs b/scripts/qa-location-controls.mjs index 92e10c5f9..dc80bd279 100644 --- a/scripts/qa-location-controls.mjs +++ b/scripts/qa-location-controls.mjs @@ -296,7 +296,7 @@ try { 'native reset returns through the existing camera handoff', await page.evaluate(async () => { const ui = window.__godsEyeView.styleManager; - ui._resetGlobeBtn.click(); + document.getElementById('reset-globe-view').click(); const pending = ui._globeResetPromise; if (!pending) return false; await pending; @@ -317,7 +317,7 @@ try { .getElementById('location-pills') .querySelector('button') ?.click(); - ui._resetGlobeBtn.click(); + document.getElementById('reset-globe-view').click(); ui._locationSearch.dispatchEvent( new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }), ); diff --git a/src/cockpitMarkup.test.mjs b/src/cockpitMarkup.test.mjs index a404ab381..0bc262348 100644 --- a/src/cockpitMarkup.test.mjs +++ b/src/cockpitMarkup.test.mjs @@ -795,35 +795,29 @@ test('Reset releases Contact camera ownership through its selection-preserving r assert.ok(resetStart >= 0); assert.ok(contextRelease > resetStart); assert.ok(satelliteRelease > contextRelease); - assert.match( - readShellElements.toString(), - /_cockpitResetGlobeBtn: document\.getElementById\('cockpit-reset-globe'\)/, - ); const controls = fs.readFileSync( path.join(ROOT, 'src', 'ui', 'locationControls.js'), 'utf8', ); - assert.match( - ui, - /resetButtons: \[this\._resetGlobeBtn, this\._cockpitResetGlobeBtn\]/, - ); assert.match(ui, /onReset: \(\) => this\.resetToGlobeView\(\)/); - assert.match( - controls, - /for \(const button of elements\.resetButtons\)[\s\S]*?this\.bind\(button, 'click', onReset\)/, - 'both reset controls delegate to the same supplied reset action', + assert.match(ui, /this\._connectGlobeReset\?\.\(this\._locationControls\)/); + assert.match(controls, /reset\(\) \{\s*if \(!this\.destroyed\) return this\.onReset\(\);/); + // Both reset buttons ask the one reset owner. + const globeActions = fs.readFileSync( + path.join(ROOT, 'src', 'ui', 'views', 'panels', 'GlobeActions.vue'), + 'utf8', ); + assert.match(globeActions, /id="reset-globe-view"[^>]*@click="act\('reset'\)"/); + const cockpitView = readRadioSource( + new URL('./ui/views/CockpitView.vue', import.meta.url), + 'utf8', + ); + assert.match(cockpitView, /id="cockpit-reset-globe"[^>]*@click="globe\.act\('reset'\)"/); assert.match( cockpitEnter.toString(), /Object\.assign\(this\.presence, \{\s*active: true,/, ); - assert.match( - readRadioSource( - new URL('./ui/views/CockpitView.vue', import.meta.url), - 'utf8', - ), - /id="cockpit-reset-globe"[^>]*:hidden="!active"/, - ); + assert.match(cockpitView, /id="cockpit-reset-globe"[^>]*:hidden="!active"/); }); test('Location navigation releases immediate routes before flight and deferred routes after resolution', () => { diff --git a/src/ui/applicationShell.js b/src/ui/applicationShell.js index 885bbc0a3..eed23487c 100644 --- a/src/ui/applicationShell.js +++ b/src/ui/applicationShell.js @@ -322,14 +322,14 @@ export class StyleManager extends ShellFacade { elements: { _locationSearch: this._locationSearch, _searchToggle: this._searchToggle, - _resetGlobeBtn: this._resetGlobeBtn, - _cockpitResetGlobeBtn: this._cockpitResetGlobeBtn, }, operations: { _publishLocation: (view) => useLocationStore(applicationPinia()).publish(view), _connectLocation: (controls) => useLocationStore(applicationPinia()).connect(controls), + _connectGlobeReset: (controls) => this._connectGlobeReset(controls), + _publishGlobeResetting: (busy) => this._publishGlobeResetting(busy), _beginDeferredNavigation: (...args) => this._beginDeferredNavigation(...args), _reassertNavigationHandoff: (...args) => @@ -1649,6 +1649,32 @@ export class StyleManager extends ShellFacade { ); } + /** + * Answer the globe and cockpit reset buttons through the location controls, + * or stop answering them (null). + */ + _connectGlobeReset(controls) { + const store = useGlobeActionsStore(applicationPinia()); + if (this._resetToken) store.detach(this._resetToken); + this._resetToken = controls + ? store.connect({ reset: () => controls.reset() }) + : null; + // A reset under way as the controls are replaced stays on the buttons. + if (this._resetToken && this._globeResetting != null) + store.publishResetting(this._resetToken, this._globeResetting); + } + + /** Publish a reset to the full globe view under way. */ + _publishGlobeResetting(busy) { + if (this._disposed) return; + this._globeResetting = Boolean(busy); + if (this._resetToken) + useGlobeActionsStore(applicationPinia()).publishResetting( + this._resetToken, + busy, + ); + } + /** * Stop answering the globe actions. Its clear under way goes with its * owner, and its camera state too; a newer shell's stays. @@ -1659,7 +1685,9 @@ export class StyleManager extends ShellFacade { if (this._clearLayersToken) store.detach(this._clearLayersToken); if (this._shareToken) store.detach(this._shareToken); if (this._orientationToken) store.detach(this._orientationToken); + if (this._resetToken) store.detach(this._resetToken); this._clearLayersToken = this._shareToken = this._orientationToken = null; + this._resetToken = null; } /** Wire Google Maps-style tilt and north-up camera actions. */ diff --git a/src/ui/cockpitController.js b/src/ui/cockpitController.js index d8cb65dd2..a65b437fe 100644 --- a/src/ui/cockpitController.js +++ b/src/ui/cockpitController.js @@ -97,7 +97,6 @@ export class CockpitViewController { this.tr3bToggle = document.getElementById('tr3b-toggle'); this._tr3bSignature = null; this.mapViewButton = document.getElementById('map-view-switch'); - this.resetGlobeButton = document.getElementById('cockpit-reset-globe'); this.hud = document.getElementById('cockpit-hud'); this.entryFocusOrigin = null; this.visionPrevious = document.getElementById('cockpit-vision-previous'); diff --git a/src/ui/commandDock.test.mjs b/src/ui/commandDock.test.mjs index 4e8983ac0..742cea1e6 100644 --- a/src/ui/commandDock.test.mjs +++ b/src/ui/commandDock.test.mjs @@ -169,7 +169,6 @@ test('the ORBIT indicator sits on the body while offered and lights while orbiti elements: { search: $('#location-search'), searchToggle: $('#search-toggle'), - resetButtons: [], }, cities: {}, getExpandedCity: () => null, @@ -211,7 +210,6 @@ test('the location tray renders what LocationControls publishes', async (t) => { elements: { search: $('#location-search'), searchToggle: $('#search-toggle'), - resetButtons: [], }, cities: { paris: { name: 'Paris', pois: [{ name: 'Louvre' }, { name: 'Eiffel' }] }, diff --git a/src/ui/globeActions.test.mjs b/src/ui/globeActions.test.mjs index ea0b81138..9b32908f4 100644 --- a/src/ui/globeActions.test.mjs +++ b/src/ui/globeActions.test.mjs @@ -8,6 +8,7 @@ import { createApp, nextTick } from 'vue'; import { createPinia } from 'pinia'; import { useGlobeActionsStore } from './stores/globeActions.js'; import GlobeActions from './views/panels/GlobeActions.vue'; +import CockpitView from './views/CockpitView.vue'; function mount(t) { document.body.replaceChildren(); @@ -19,6 +20,7 @@ function mount(t) { share: () => calls.push('share'), tilt: () => calls.push('tilt'), northUp: () => calls.push('northUp'), + reset: () => calls.push('reset'), }); const app = createApp(GlobeActions).use(pinia); app.mount(document.body.appendChild(document.createElement('div'))); @@ -33,7 +35,8 @@ test('every button calls its owner', (t) => { $('share-btn').click(); $('tilt-map-view').click(); $('north-up-view').click(); - assert.deepEqual(calls, ['clear', 'share', 'tilt', 'northUp']); + $('reset-globe-view').click(); + assert.deepEqual(calls, ['clear', 'share', 'tilt', 'northUp', 'reset']); }); test('the tilt and compass buttons show the published camera', async (t) => { @@ -130,3 +133,43 @@ test('the same camera state again changes nothing', () => { assert.notEqual(store.camera, kept); assert.deepEqual(store.camera, { tilted: true, heading: 13 }); }); + +test('a reset under way relabels the reset button for its owner', async (t) => { + const { store, token } = mount(t); + const reset = $('reset-globe-view'); + assert.equal(reset.getAttribute('aria-label'), 'Reset to full globe view'); + store.publishResetting(token, true); + await nextTick(); + assert.equal( + reset.getAttribute('aria-label'), + 'Resetting to full globe view', + ); + assert.equal(store.clearBusy, null, 'a reset is not a clear'); + store.detach(token); + await nextTick(); + assert.equal(reset.getAttribute('aria-label'), 'Reset to full globe view'); +}); + +test('the cockpit reset asks the reset owner and shows its reset', async (t) => { + document.body.replaceChildren(); + const pinia = createPinia(); + const store = useGlobeActionsStore(pinia); + const calls = []; + const token = store.connect({ reset: () => calls.push('reset') }); + const app = createApp(CockpitView).use(pinia); + app.mount(document.body.appendChild(document.createElement('div'))); + t.after(() => app.unmount()); + const reset = $('cockpit-reset-globe'); + assert.equal( + reset.getAttribute('aria-label'), + 'Reset cockpit to full globe view', + ); + reset.click(); + assert.deepEqual(calls, ['reset']); + store.publishResetting(token, true); + await nextTick(); + assert.equal( + reset.getAttribute('aria-label'), + 'Resetting cockpit to full globe view', + ); +}); diff --git a/src/ui/locationControls.js b/src/ui/locationControls.js index 4a94dc4e2..8977c6fc2 100644 --- a/src/ui/locationControls.js +++ b/src/ui/locationControls.js @@ -19,7 +19,8 @@ const LOCATION_MINI_SEARCHED_PLACEHOLDER = Object.freeze( * mini status, the search error and the ORBIT indicator are presented as a * plain view and handed to `publish`; Core's dock renders them and calls * `chooseCity()` and `choosePoi()`, and the scene chrome shows the indicator. - * The search field and reset buttons keep their listeners. + * The globe actions and the cockpit call `reset()`. The search field keeps its + * listeners. */ export class LocationControls { constructor({ @@ -90,8 +91,6 @@ export class LocationControls { this.bind(elements.search, 'blur', () => { if (!elements.search.value) onSearchEdit?.(); }); - for (const button of elements.resetButtons) - this.bind(button, 'click', onReset); this.present(); } bind(element, event, handler, removers = this.removers) { @@ -132,6 +131,10 @@ export class LocationControls { chooseCity(id) { if (!this.destroyed) this.onCity(id); } + /** A reset to the full globe view was asked for. */ + reset() { + if (!this.destroyed) return this.onReset(); + } /** A landmark pill of the shown city was clicked. */ choosePoi(index) { if (!this.destroyed && this.poiCity !== null) diff --git a/src/ui/locationControls.test.mjs b/src/ui/locationControls.test.mjs index 42466ee19..b62478fc8 100644 --- a/src/ui/locationControls.test.mjs +++ b/src/ui/locationControls.test.mjs @@ -61,7 +61,6 @@ function fixture() { const elements = { search: node(), searchToggle: node(), - resetButtons: [node(), node()], }; const doc = node(); doc.createElement = node; @@ -168,7 +167,7 @@ test('destruction revokes document, search, reset, city and POI actions and remo f.elements.search.value = 'Place'; f.elements.search.fire('keydown', { key: 'Enter' }); f.doc.fire('keydown', { key: 'Q' }); - f.elements.resetButtons[0].fire('click'); + f.controls.reset(); f.frames.get(0)(); assert.deepEqual(f.calls, []); assert.equal(f.views.length, published); @@ -187,7 +186,7 @@ test('location and POI keys route once while form controls retain typing', () => const f = fixture(); f.doc.fire('keydown', { key: 'W', target: { matches: () => false } }); f.doc.fire('keydown', { key: 'Q', target: { matches: () => true } }); - f.elements.resetButtons[1].fire('click'); + f.controls.reset(); assert.deepEqual(f.calls, [['poi', 'a', 1], ['reset']]); }); test('typing clears a failed search error and closing the emptied field drops it too', () => { diff --git a/src/ui/locationNavigation.js b/src/ui/locationNavigation.js index a9c9d5a71..f06515c6e 100644 --- a/src/ui/locationNavigation.js +++ b/src/ui/locationNavigation.js @@ -144,7 +144,6 @@ export class LocationNavigation { elements: { search: this._locationSearch, searchToggle: this._searchToggle, - resetButtons: [this._resetGlobeBtn, this._cockpitResetGlobeBtn], }, publish: (view) => this._publishLocation?.(view), cities: CITY_POIS, @@ -156,6 +155,7 @@ export class LocationNavigation { onReset: () => this.resetToGlobeView(), }); this._connectLocation?.(this._locationControls); + this._connectGlobeReset?.(this._locationControls); } _beginWorldJumpTransition() { @@ -390,14 +390,7 @@ export class LocationNavigation { longitude: Number(Cesium.Math.toDegrees(carto.longitude).toFixed(2)), }, }; - this._resetGlobeBtn?.setAttribute( - 'aria-label', - t('Reset to full globe view'), - ); - this._cockpitResetGlobeBtn?.setAttribute( - 'aria-label', - t('Reset cockpit to full globe view'), - ); + this._publishGlobeResetting?.(false); this._globeResetPromise = null; this._cancelGlobeReset = null; resolveReset(result); @@ -410,14 +403,7 @@ export class LocationNavigation { Math.abs(height - GLOBE_VIEW.heightM) > 1000, ); }, 4200); - this._resetGlobeBtn?.setAttribute( - 'aria-label', - t('Resetting to full globe view'), - ); - this._cockpitResetGlobeBtn?.setAttribute( - 'aria-label', - t('Resetting cockpit to full globe view'), - ); + this._publishGlobeResetting?.(true); const target = flyToGlobeView(this.viewer, { onComplete: () => finish(false), onCancel: () => finish(true), @@ -436,6 +422,7 @@ export class LocationNavigation { this._locationLookup?.destroy(); this._locationControls?.destroy(); this._connectLocation?.(null); + this._connectGlobeReset?.(null); this._publishLocation?.(null); this._cancelGlobeReset?.(); this._cancelGlobeReset = null; diff --git a/src/ui/placeNames.test.mjs b/src/ui/placeNames.test.mjs index 0c224eaee..0e1536ffa 100644 --- a/src/ui/placeNames.test.mjs +++ b/src/ui/placeNames.test.mjs @@ -54,7 +54,6 @@ test('ru: location pills and the mini-status show the translated city', () => { const elements = { search: element(), searchToggle: element(), - resetButtons: [], }; const doc = { ...element(), createElement: element }; const cities = { tokyo: CITY_POIS.tokyo }; diff --git a/src/ui/shareButton.test.mjs b/src/ui/shareButton.test.mjs index bf39ac1ee..7de669a83 100644 --- a/src/ui/shareButton.test.mjs +++ b/src/ui/shareButton.test.mjs @@ -300,3 +300,26 @@ test('an older shell that answers again shows its clear and its unchanged camera older._cameraOrientationControls.destroy(); StyleManager.prototype._releaseGlobeActions.call(older); }); + +test('the location controls answer both reset buttons until they go', () => { + const store = useGlobeActionsStore(applicationPinia()); + const calls = []; + const owner = { _disposed: false }; + const controls = { reset: () => calls.push('reset') }; + StyleManager.prototype._connectGlobeReset.call(owner, controls); + store.act('reset'); + StyleManager.prototype._publishGlobeResetting.call(owner, true); + assert.equal(store.resetBusy, true); + // Controls replaced mid-reset keep the reset on the buttons. + StyleManager.prototype._connectGlobeReset.call(owner, controls); + assert.equal(store.resetBusy, true); + StyleManager.prototype._publishGlobeResetting.call(owner, false); + assert.equal(store.resetBusy, false); + StyleManager.prototype._connectGlobeReset.call(owner, null); + store.act('reset'); + assert.deepEqual(calls, ['reset']); + assert.equal(store.resetBusy, null); + // A reset finishing after the controls went changes nothing. + StyleManager.prototype._publishGlobeResetting.call(owner, false); + assert.equal(store.resetBusy, null); +}); diff --git a/src/ui/shellElements.js b/src/ui/shellElements.js index 561549296..fa24026aa 100644 --- a/src/ui/shellElements.js +++ b/src/ui/shellElements.js @@ -63,8 +63,6 @@ export function readShellElements(document = globalThis.document) { _cctvSourceBadge: document.getElementById('cctv-source-badge'), _cctvMeta: document.getElementById('cctv-meta'), _cctvSummary: document.getElementById('cctv-summary'), - _resetGlobeBtn: document.getElementById('reset-globe-view'), - _cockpitResetGlobeBtn: document.getElementById('cockpit-reset-globe'), _locationSearch: document.getElementById('location-search'), _searchToggle: document.getElementById('search-toggle'), _safeFrameOverlay: document.getElementById('safe-frame-overlay'), diff --git a/src/ui/stores/globeActions.js b/src/ui/stores/globeActions.js index d8dff5d14..58247604f 100644 --- a/src/ui/stores/globeActions.js +++ b/src/ui/stores/globeActions.js @@ -3,33 +3,43 @@ import { computed, ref, shallowReactive } from 'vue'; import { createOwners } from './owners.js'; /** - * The top-center globe actions as their view renders them. The shell - * publishes whether a clear of the selected data layers is under way and the - * camera's tilt and heading, and answers the buttons through act(). + * The top-center globe actions as their view renders them, and the cockpit's + * reset. The shell publishes whether a clear of the selected data layers or a + * reset to the full globe view is under way and the camera's tilt and + * heading, and answers the buttons through act(). */ export const useGlobeActionsStore = defineStore('gev-globe-actions', () => { const owners = createOwners(); // Who answers which action, as the computed state below reads it. const ownership = ref(0); - /** Each clear owner's clear under way, by its token. */ - const busyBy = shallowReactive(new Map()); /** - * Whether the clear owner's clear is under way; null until it says. Each - * owner keeps its own, so the button shows the one that answers it. + * Whether the work behind an action is under way, kept per owner so its + * button shows the owner that answers it; null until that owner says. */ - const clearBusy = computed(() => { - void ownership.value; - return busyBy.get(owners.ownerOf('clear')) ?? null; - }); - - /** - * @param {object} token The clear owner's, from connect(). - * @param {boolean} busy - */ - function publishClearBusy(token, busy) { - busyBy.set(token, Boolean(busy)); + function ownedBusy(name) { + const byOwner = shallowReactive(new Map()); + const busy = computed(() => { + void ownership.value; + return byOwner.get(owners.ownerOf(name)) ?? null; + }); + /** + * @param {object} token The owner's, from connect(). + * @param {boolean} value + */ + const publish = (token, value) => { + byOwner.set(token, Boolean(value)); + }; + return { byOwner, busy, publish }; } + const clearing = ownedBusy('clear'); + const resetting = ownedBusy('reset'); + /** Whether a clear of the selected data layers is under way. */ + const clearBusy = clearing.busy; + const publishClearBusy = clearing.publish; + /** Whether a reset to the full globe view is under way. */ + const resetBusy = resetting.busy; + const publishResetting = resetting.publish; /** * Whether the map reads as tilted and the camera's whole-degree heading; @@ -63,7 +73,8 @@ export const useGlobeActionsStore = defineStore('gev-globe-actions', () => { function detach(token) { owners.detach(token); - busyBy.delete(token); + clearing.byOwner.delete(token); + resetting.byOwner.delete(token); ownership.value += 1; } @@ -72,6 +83,8 @@ export const useGlobeActionsStore = defineStore('gev-globe-actions', () => { return { clearBusy, publishClearBusy, + resetBusy, + publishResetting, camera, publishCamera, connect, diff --git a/src/ui/views/CockpitView.vue b/src/ui/views/CockpitView.vue index 1c0af4be9..4ec4ea9ab 100644 --- a/src/ui/views/CockpitView.vue +++ b/src/ui/views/CockpitView.vue @@ -9,6 +9,7 @@ import { } from '../cockpitInstrumentState.js'; import { vClassToggle } from '../rail/classToggle.js'; import { useCockpitStore } from '../stores/cockpit.js'; +import { useGlobeActionsStore } from '../stores/globeActions.js'; import CockpitBriefing from './panels/CockpitBriefing.vue'; import CockpitContext from './panels/CockpitContext.vue'; import CockpitRollingValue from './panels/CockpitRollingValue.vue'; @@ -21,6 +22,8 @@ import CockpitUtilityControls from './panels/CockpitUtilityControls.vue'; // keep its listeners. const { presence, instruments, route, vision } = storeToRefs(useCockpitStore()); const active = computed(() => Boolean(presence.value?.active)); +const globe = useGlobeActionsStore(); +const { resetBusy } = storeToRefs(globe); const initialInstruments = createInstrumentState(); const initialRoute = createRouteState(); const initialVision = createVisionState(); @@ -188,7 +191,7 @@ const tickStyle = (tick) =>