my_sea_visit nav: phase-aware NVM (hex→bud page, draw→hex) + navbar GATE VIEW → visit gate + guard reposition on resize — TDD
Spectator guard-portal + NVM/GATE VIEW routing (user-spec 2026-05-30): - The leave-the-sea guard now confirms with OK (was NVM); `_my_sea_gear.html` gains an `nvm_handler` param so a caller can swap the default leave-nav. - my_sea_visit NVM is phase-aware (`mySeaVisitNvm`): on the DRAW/spread phase it flips back to the table hex (client toggle, stays in-ecosphere → no voice guard, mirroring the owner's picker→landing); on the table hex it LEAVES to the bud's page (`billboard:bud_page`) behind the shared voice-disconnect guard. - The navbar GATE VIEW opens THIS owner's visitor gatekeeper on my_sea_visit (+ its gate page, whose page_class also carries `page-my-sea-visit`), not the viewer's own sea gate; owner pages are unchanged. - showGuard now RE-POSITIONS the open guard on resize/orientationchange (rAF-throttled) so it follows its anchor instead of stranding at its show-time coords — a cross-cutting fix (every gear-menu guard) for the portal landing off-screen after an orientation flip relocated the gear menu. Coverage: MySeaVisitNavTest (navbar→visit gate, gear NVM→mySeaVisitNvm, bud URL, OK label) + MySeaOwnerNavbarGateUnaffectedTest (owner gate untouched). Verified live in Firefox: picker NVM returns to the hex; the guard followed its anchor from 882px→54px on a simulated orientation flip, staying in-viewport. Code architected by Disco DeDisco <discodedisco@outlook.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -31,7 +31,7 @@ window.mySeaGuardedNav = window.mySeaGuardedNav || function (e, url) {
|
||||
window.location.href = url;
|
||||
},
|
||||
null, // dismiss = stay
|
||||
{ yesLabel: 'NVM' }
|
||||
{ yesLabel: 'OK' } // confirm = OK (user-spec 2026-05-30)
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -43,7 +43,10 @@ window.mySeaGuardedNav = window.mySeaGuardedNav || function (e, url) {
|
||||
{# column in portrait / row in landscape (the menu itself can't be flexed #}
|
||||
{# since applets.js force-sets display:block on open). #}
|
||||
<div class="menu-btns">
|
||||
<button type="button" class="btn btn-cancel" onclick="mySeaGuardedNav(event, '{{ nvm_url }}')">NVM</button>
|
||||
{# `nvm_handler` lets a caller swap the default leave-the-sea nav for a #}
|
||||
{# phase-aware handler (the visitor's my_sea_visit routes NVM to the bud #}
|
||||
{# page from the table hex, but back to the hex from the draw phase). #}
|
||||
<button type="button" class="btn btn-cancel" onclick="{% if nvm_handler %}{{ nvm_handler }}{% else %}mySeaGuardedNav(event, '{{ nvm_url }}'){% endif %}">NVM</button>
|
||||
{# Spectator-only BYE (Phase B) — drops presence (status=LEFT, frees seat #}
|
||||
{# 2C, kills voice). Rendered below NVM only when the caller passes a #}
|
||||
{# `leave_url`; the owner's pages never do, so their menu is unchanged. #}
|
||||
|
||||
@@ -73,9 +73,11 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Gear menu — NVM (back to /gameboard/) + BYE (drop presence, free 2C). #}
|
||||
{# Gear menu — NVM is phase-aware (mySeaVisitNvm): table hex → the bud's #}
|
||||
{# page (voice-disconnect guard); draw phase → back to the hex (client #}
|
||||
{# toggle, stays in-ecosphere, no guard). BYE drops presence + frees 2C. #}
|
||||
{% url 'my_sea_visit_leave' owner.id as leave_url %}
|
||||
{% include "apps/gameboard/_partials/_my_sea_gear.html" with leave_url=leave_url %}
|
||||
{% include "apps/gameboard/_partials/_my_sea_gear.html" with leave_url=leave_url nvm_handler="mySeaVisitNvm(event)" %}
|
||||
{# Burger fan — carries the voice sub-btn (active while voice_active). #}
|
||||
{% include "apps/gameboard/_partials/_burger.html" %}
|
||||
</div>
|
||||
@@ -323,14 +325,42 @@
|
||||
var viewBtn = document.getElementById('id_my_sea_view_draw_btn');
|
||||
var draw = document.getElementById('id_my_sea_visit_draw');
|
||||
var landing = document.querySelector('.my-sea-visit-landing');
|
||||
function _setDraw(show) {
|
||||
if (!draw) return;
|
||||
draw.style.display = show ? '' : 'none';
|
||||
if (landing) landing.style.display = show ? 'none' : '';
|
||||
if (page) page.setAttribute('data-phase', show ? 'picker' : 'landing');
|
||||
}
|
||||
if (viewBtn && draw) {
|
||||
viewBtn.addEventListener('click', function () {
|
||||
var showing = draw.style.display !== 'none';
|
||||
draw.style.display = showing ? 'none' : '';
|
||||
if (landing) landing.style.display = showing ? '' : 'none';
|
||||
if (page) page.setAttribute('data-phase', showing ? 'landing' : 'picker');
|
||||
_setDraw(draw.style.display === 'none');
|
||||
});
|
||||
}
|
||||
|
||||
// Phase-aware NVM (the gear menu's NVM calls this). On the DRAW/spread
|
||||
// phase NVM just flips back to the table hex — it stays inside the
|
||||
// my_sea_visit ecosphere (voice untouched), so NO guard, like the owner's
|
||||
// picker→landing NVM. On the table hex NVM LEAVES to the bud's page, with
|
||||
// the shared voice-disconnect guard (mySeaGuardedNav). (user-spec
|
||||
// 2026-05-30.)
|
||||
var BUD_URL = '{% url 'billboard:bud_page' owner.id %}';
|
||||
function _closeGearMenu() {
|
||||
var menu = document.getElementById('id_my_sea_menu');
|
||||
if (menu) menu.style.display = 'none';
|
||||
var gear = document.querySelector('.gear-btn[data-menu-target="id_my_sea_menu"]');
|
||||
if (gear) gear.classList.remove('active');
|
||||
}
|
||||
window.mySeaVisitNvm = function (e) {
|
||||
if (page && page.getAttribute('data-phase') === 'picker') {
|
||||
if (e && e.preventDefault) e.preventDefault();
|
||||
_setDraw(false); // back to the table hex
|
||||
_closeGearMenu();
|
||||
return;
|
||||
}
|
||||
// Table hex → leave to the bud's page (guarded if voice is live).
|
||||
if (window.mySeaGuardedNav) window.mySeaGuardedNav(e, BUD_URL);
|
||||
else window.location.href = BUD_URL;
|
||||
};
|
||||
// GATE VIEW → visitor gate.
|
||||
var gateBtn = document.getElementById('id_my_sea_gate_view_btn');
|
||||
if (gateBtn) {
|
||||
|
||||
Reference in New Issue
Block a user