Posterverse: nested in another owner's page, its tab is in the address as a ?subtab= segment
Nested (no urlOwner), the shell's pick is claimed with its depth, and the owner above records it as this shell's ?subtab= segment. First paint claims the current tab as a replace, so the segment exists before a deeper one; a link that names a row arriving with the manifest is still claimed only once the row is known. The shell reads its tab from its own segment first, then ?tab= only when it names one of its rows (a one-level partner page), on load and on Back/Forward. Each child is told its depth: 1 under an owning shell, one deeper otherwise. Pages where the shell owns the address are unchanged.
This commit is contained in:
parent
00f7d349eb
commit
07c4deae26
1 changed files with 23 additions and 8 deletions
|
|
@ -74,7 +74,7 @@ import BackToTopButton from '@map/components/BackToTopButton.vue'
|
|||
import ShellLanguageMenu from '@map/components/ShellLanguageMenu.vue'
|
||||
import { saveLocale } from '@map/layouts/app-wrapper-material/languages.js'
|
||||
import { loadScriptOnce, whenTagDefined } from '@map/utils/embedScript.js'
|
||||
import { readViewKeys, writeViewKeys, onAddressChange, urlOwnerOf, ownAddress } from '@map/composables/useViewAddress.js'
|
||||
import { readViewKeys, claimView, onAddressChange, urlOwnerOf, ownAddress, depthOf, subtabAt } from '@map/composables/useViewAddress.js'
|
||||
import { translate, LOCALES } from './src/strings.js'
|
||||
import { SECTIONS, TABS, resolveTabs } from './src/tabs.js'
|
||||
|
||||
|
|
@ -236,9 +236,11 @@ export default defineComponent({
|
|||
// A nested plugin's choice inside a tab (?pane=, ?place=) reaches the address through the owner: recorded
|
||||
// only while this page owns its address, never a tab switch, and the event stops here.
|
||||
this._offOwn = ownAddress(this.$el, () => urlOwnerOf(this.cfg))
|
||||
// Back / Forward re-apply the tab from the address and never write (writing would lose Forward).
|
||||
// Back / Forward re-apply the tab from the address and never write (writing would lose Forward). Nested, this
|
||||
// shell's tab is its own ?subtab= segment, never the owner's ?tab=.
|
||||
this._offAddress = onAddressChange(({ tab }) => {
|
||||
const i = this.tabs.findIndex((t) => t.id === tab)
|
||||
const id = urlOwnerOf(this.cfg) ? tab : this.nestedTab()
|
||||
const i = this.tabs.findIndex((t) => t.id === id)
|
||||
this.select(i >= 0 ? i : 0, { fromHistory: true })
|
||||
})
|
||||
this.loadManifest()
|
||||
|
|
@ -268,10 +270,20 @@ export default defineComponent({
|
|||
let q = ''
|
||||
try { q = readViewKeys(location.search).tab } catch { /* non-browser */ }
|
||||
// On a page whose address this shell owns, the URL (a reload, a shared link) beats a baked cfg.tab, or the
|
||||
// first-paint replace would overwrite the link with the default. Elsewhere the host's config leads.
|
||||
const order = urlOwnerOf(this.cfg) ? [this.tab, q, this.cfg.tab] : [this.tab, this.cfg.tab, q]
|
||||
// first-paint replace would overwrite the link with the default. Nested in another owner's page, this shell's
|
||||
// tab is its ?subtab= segment (a deep link), and the host's config leads the rest.
|
||||
const order = urlOwnerOf(this.cfg) ? [this.tab, q, this.cfg.tab] : [this.nestedTab(true), this.tab, this.cfg.tab, this.nestedTab()]
|
||||
return String(order.find((v) => v) || '').trim()
|
||||
},
|
||||
// Nested (no owner here): this shell's segment of ?subtab=, else ?tab= when it names one of its own rows (a
|
||||
// one-level partner page). Rows come from the full list, so a row that only arrives with the manifest still
|
||||
// counts. An owner's own ?tab= (bundle__profile) never names one of them. segmentOnly: the segment alone.
|
||||
nestedTab(segmentOnly = false) {
|
||||
let seg = '', q = ''
|
||||
try { seg = subtabAt(location.search, depthOf(this.cfg)); q = readViewKeys(location.search).tab } catch { /* non-browser */ }
|
||||
if (seg || segmentOnly) return seg
|
||||
return TABS.some((t) => t.id === q) ? q : ''
|
||||
},
|
||||
initialIndex() {
|
||||
const i = this.tabs.findIndex((t) => t.id === this.requestedTab())
|
||||
return i >= 0 ? i : 0
|
||||
|
|
@ -344,8 +356,9 @@ export default defineComponent({
|
|||
return '../' + r
|
||||
},
|
||||
// The tab is written to the address by the ONE owner (urlOwner in profile-config: 'app' on our own pages,
|
||||
// 'host' when a host's router writes, absent on a partner's page = read only). A reader's choice is a push;
|
||||
// first paint is a replace; Back / Forward never write.
|
||||
// 'host' when a host's router writes). Nested, it is announced, and the owner above records it as this shell's
|
||||
// ?subtab= segment; on a partner's page nothing above listens. A reader's choice is a push; first paint is a
|
||||
// replace, and nested it is REQUIRED, so the segment exists before a deeper one; Back / Forward never write.
|
||||
select(i, { fromHistory = false, firstPaint = false } = {}) {
|
||||
const prevIndex = this.activeIndex
|
||||
this.activeIndex = i
|
||||
|
|
@ -358,7 +371,7 @@ export default defineComponent({
|
|||
if (!t) return
|
||||
// Tell the host which plugin is showing (CustomEvent 'tab-change', detail[0] = { id, label }).
|
||||
if (prevIndex !== i || !this._announced) { this._announced = true; this.$emit('tab-change', { id: t.id, label: this.tabLabel(t) }) }
|
||||
if (!fromHistory) writeViewKeys({ tab: t.id }, { owner: urlOwnerOf(this.cfg), push: !firstPaint, el: this.$el })
|
||||
if (!fromHistory) claimView({ tab: t.id }, { owner: urlOwnerOf(this.cfg), push: !firstPaint, el: this.$el, depth: depthOf(this.cfg) })
|
||||
if (!t.scriptUrl) return // applyManifest selects again once the manifest lands
|
||||
// A heavy tab's slot exists only after its v-if subtree renders, so mount on the next tick.
|
||||
if (!t.mounted) this.$nextTick(() => { if (this.activeIndex === i) this.mountElement(i) })
|
||||
|
|
@ -380,6 +393,8 @@ export default defineComponent({
|
|||
if (this.assetsBase) pc.assetsBase = this.assetsBase
|
||||
// The host owns its URL, hash and title: a nested plugin must not write them.
|
||||
pc.urlSync = false
|
||||
// A shell nested in this tab claims the ?subtab= segment one below this shell's own.
|
||||
pc.addressDepth = urlOwnerOf(this.cfg) ? 1 : depthOf(this.cfg) + 1
|
||||
// The plugin's own name for its print header: this tab's localized label.
|
||||
pc.mapTitle = this.tabLabel(t)
|
||||
return pc
|
||||
|
|
|
|||
Loading…
Reference in a new issue