Merge the Research Gallery shell's view address (shareable pages P1)
This commit is contained in:
commit
dfed65c8af
1 changed files with 31 additions and 3 deletions
|
|
@ -67,7 +67,7 @@
|
|||
:header="showHeader"
|
||||
:groups="navGroups"
|
||||
:active="activeKey"
|
||||
@update:active="onSelect">
|
||||
@update:active="onRailSelect">
|
||||
|
||||
<!-- #brand: the DX-Maps logo mark, left of the title (a compass-star glyph, self-drawn SVG — no
|
||||
external asset, offline/F-Droid safe; the accent green matches the admin shell). -->
|
||||
|
|
@ -216,6 +216,7 @@ import { helpFor } from './src/experimentalHelp.js'
|
|||
import { TAB_INFO } from './src/tabInfo.js'
|
||||
import MapInfo from '@map/components/info/MapInfo.vue'
|
||||
import { loadScriptOnce, whenTagDefined } from '@map/utils/embedScript.js'
|
||||
import { readViewKeys, writeViewKeys, onAddressChange, urlOwnerOf } from '@map/composables/useViewAddress.js'
|
||||
|
||||
// THE HOST PAGE'S LANGUAGE, by the same ladder every nested map already uses (library/i18n
|
||||
// detectLocale): ?lang= / ?locale= on the page URL, then <html lang>. '' when the page says nothing.
|
||||
|
|
@ -1130,6 +1131,11 @@ export default defineComponent({
|
|||
// A map's own "?" asks for its help with a composed doxa:help event (library HelpButton).
|
||||
this._onHostedHelp = (e) => this.onHostedHelp(e)
|
||||
this.$el.addEventListener('doxa:help', this._onHostedHelp)
|
||||
// Back / Forward re-open the tab the address names (useViewAddress), and never write. Only where a page OWNS
|
||||
// its address: on a partner's page a popstate is the partner's own navigation, and re-reading the URL there
|
||||
// would snap a host's fixed `tab` attribute back to the default. The owner is read per event: a host may set
|
||||
// profile-config after mount.
|
||||
this._offAddress = onAddressChange(({ tab }) => { if (urlOwnerOf(this.cfg)) this.openFromAddress(tab) })
|
||||
},
|
||||
// Release the media-query listener. This element is a custom element a host can add and REMOVE at
|
||||
// will (a cap-5 SPA is mounted and unmounted by shells, tabs and the studio), and a live listener
|
||||
|
|
@ -1137,6 +1143,7 @@ export default defineComponent({
|
|||
beforeUnmount() {
|
||||
if (this._langObs) { this._langObs.disconnect(); this._langObs = null }
|
||||
if (this._onHostedHelp) { this.$el.removeEventListener('doxa:help', this._onHostedHelp); this._onHostedHelp = null }
|
||||
if (this._offAddress) { this._offAddress(); this._offAddress = null }
|
||||
if (!this._mql || !this._onMedia) return
|
||||
if (this._mql.removeEventListener) this._mql.removeEventListener('change', this._onMedia)
|
||||
else if (this._mql.removeListener) this._mql.removeListener(this._onMedia)
|
||||
|
|
@ -1440,10 +1447,11 @@ export default defineComponent({
|
|||
this._honouredTab = true
|
||||
},
|
||||
// The tab a HOST asked to open first: the `tab` attribute, then profile-config.tab, then ?tab= on
|
||||
// the page URL (so an iframe src or a shared link can deep-link). '' when nobody asked.
|
||||
// the page URL (so an iframe src or a shared link can deep-link). '' when nobody asked. The URL is read
|
||||
// through useViewAddress: the first ?tab= wins, and a value that is not a plain id reads as absent.
|
||||
requestedTab() {
|
||||
let q = ''
|
||||
try { q = new URLSearchParams(location.search).get('tab') || '' } catch { /* non-browser */ }
|
||||
try { q = readViewKeys(location.search).tab } catch { /* non-browser */ }
|
||||
return String(this.tab || this.cfg.tab || q || '').trim()
|
||||
},
|
||||
// The index to open on mount: the requested tab when it exists and is enabled at this width,
|
||||
|
|
@ -1496,6 +1504,26 @@ export default defineComponent({
|
|||
const i = this.tabs.findIndex(t => t.id === key)
|
||||
if (i !== -1) this.select(i)
|
||||
},
|
||||
// ★ THE PAGE ADDRESS (shareable pages, useViewAddress). A READER's pick in the rail is the one switch that
|
||||
// writes ?tab=, as a push, so a reload keeps the tab, a sent link opens it, and Back returns to the previous one.
|
||||
// Who writes is the page's urlOwner: 'app' (our own leaf page) writes history, 'host' (DX Life) gets a
|
||||
// dxm-address event and its router writes, and a partner's page is never written. Every other switch is not a
|
||||
// choice and writes nothing: the manifest's re-select, the device fallback, a host's `tab` attribute, Back and
|
||||
// Forward. Nor is there a first-paint write: a bare URL means the device's default tab, and pinning a phone's
|
||||
// default into the address would send a desktop reader to it.
|
||||
onRailSelect(key) {
|
||||
const before = this.activeKey
|
||||
this.onSelect(key)
|
||||
if (this.activeKey !== before) writeViewKeys({ tab: this.activeKey }, { owner: urlOwnerOf(this.cfg), push: true, el: this.$el })
|
||||
},
|
||||
// Back / Forward: the tab the address names, else the page's configured first tab (profile-config.tab), else the
|
||||
// device default. Not the `tab` attribute: a host with a router re-points it from this same popstate, and until
|
||||
// it does, it still names the tab being left.
|
||||
openFromAddress(tab) {
|
||||
const want = tab || String(this.cfg.tab || '').trim()
|
||||
const i = want ? this.tabs.findIndex(t => t.id === want) : -1
|
||||
this.select(i >= 0 && !this.isDesktopOnly(want) ? i : this.firstVisibleIndex())
|
||||
},
|
||||
// Resolve a tree-relative ref ("./x" / "x") against the tree base. If base is '' we keep it
|
||||
// relative to THIS document — but this bundle's own folder is <base>/doxa-maps-spa/, so a
|
||||
// co-located leaf at <base>/big-picture/... is one level UP: prefix '../'.
|
||||
|
|
|
|||
Loading…
Reference in a new issue