From 6b05bd242cc5479ce3f9be4ae21d0ce7e047be93 Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Wed, 30 Sep 2026 04:48:20 +0000 Subject: [PATCH] Simple Research: "What can this map do?" becomes the map's top round control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The research map draws the ⓘ as the first button of its own control column (MapInfoButton), and the gallery's Simple Research row switches to trigger: 'control' in the same commit, so the tab never shows two ⓘ, and never shows none. At mount the map tells the gallery that its control is coming, so the floating ⓘ does not flash while a slow phone loads. A failure or an unmount withdraws that promise, and the floating ⓘ comes back at once. On a page with no gallery nothing answers, and the map is unchanged. --- plugin-designs/doxa-maps-spa/src/tabInfo.js | 1 + .../doxa-research-map/research-map.vue | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/plugin-designs/doxa-maps-spa/src/tabInfo.js b/plugin-designs/doxa-maps-spa/src/tabInfo.js index 54279d00e..bf504092e 100644 --- a/plugin-designs/doxa-maps-spa/src/tabInfo.js +++ b/plugin-designs/doxa-maps-spa/src/tabInfo.js @@ -96,6 +96,7 @@ export const TAB_INFO = { }, 'research-map-plus-grid': { storageKey: 'research-map-plus-grid', + trigger: 'control', pos: { top: '56px', side: '56px' }, leadKey: 'mapInfo.tab.research-map-plus-grid.lead', takeawayKey: 'mapInfo.tab.research-map-plus-grid.takeaway', diff --git a/plugin-designs/doxa-research-map/research-map.vue b/plugin-designs/doxa-research-map/research-map.vue index e593682e4..679f97278 100644 --- a/plugin-designs/doxa-research-map/research-map.vue +++ b/plugin-designs/doxa-research-map/research-map.vue @@ -177,6 +177,9 @@ import HamburgerButton from '@map/components/map-controls/HamburgerButton.vue' import GeocoderComponent from '@map/components/map-controls/GeocoderComponent.vue' import ShareButton from '@map/components/map-controls/ShareButton.vue' import MapControlButton from '@map/components/map-controls/MapControlButton.vue' +// "What can this map do?", as the top control. By path like the rest: the map-controls barrel would pull +// the whole 'mapInfo' catalogue area into this bundle. +import MapInfoButton from '@map/components/map-controls/MapInfoButton.vue' // PERF: SideMenuDrawer is unused in the current research-map template (the // ResearchMapSideMenu sibling renders the actual menu). Removed entirely from @@ -3002,6 +3005,29 @@ function applyContainerScale(width) { } } +// ★ THE ⓘ CONTROL IS COMING, SO SAY SO BEFORE THE GALLERY DRAWS ITS FLOATING ONE. The control column +// renders only at appReady, after the style AND the people-group data, and a slow phone gets there late. +// At mount this map tells the gallery's MapInfo that a control is on its way, and the MapInfo waits for +// the map rather than flashing its floating ⓘ and swapping it out. A failure (mapError) or an unmount +// withdraws the promise, so the floating ⓘ shows at once and the popup can always be opened. With no +// MapInfo (a standalone page) nothing answers and nothing changes. This is Prayer Progress's contract. +function announceInfoPending(pending) { + const el = rmRoot.value + if (!el) return + try { el.dispatchEvent(new CustomEvent('dxmaps:mapinfo-pending', { bubbles: true, composed: true, detail: { pending } })) } catch { /* no CustomEvent */ } +} +// A MapInfo that mounted after this map asked into the void; it announces itself, and we answer again. +const reannounceInfoPending = () => { if (!appReady.value && !mapError.value) announceInfoPending(true) } +watch(mapError, (e) => { if (e) announceInfoPending(false) }) +onMounted(() => { + announceInfoPending(true) + window.addEventListener('dxmaps:mapinfo-host', reannounceInfoPending) +}) +onBeforeUnmount(() => { + window.removeEventListener('dxmaps:mapinfo-host', reannounceInfoPending) + if (!appReady.value) announceInfoPending(false) +}) + onMounted(async () => { // uiStore.init() registers the page-level ResizeObserver that drives // updateBreakpoint() — without this, breakpoint stays at default 'desktop' @@ -3202,6 +3228,10 @@ onBeforeUnmount(() => { + +