The queue's pixels were already right. Measured at the reference device's 424x439, #24's overlay is 424x318 -- `.main-panel`'s rect exactly -- so the `DETAIL_LOADERS` mount the issue's Direction asks for would draw the same rectangle in the same place. What was missing was the navigation model: opening the queue on Artists and pressing back moved the page *underneath* to Albums and left the queue up, which is a press that changes something the user cannot see and costs them their place. So the queue is a *place* exactly while it is an overlay, and a *control* while it is a column. A column is a thing the user docked -- back must not undock it and a navigation must not take it away -- and that reuses #24's computed mode rather than adding a breakpoint, so the drag-resizable panel width keeps deciding it. It is in neither `VIEW_TAGS` nor `DETAIL_LOADERS`, because there is nothing to mount and moving it would cost something. `.main-panel > *` computes `contain: content` under a `.main-panel` that does too, and paint containment clips the `position: fixed` a `wa-popup` falls back to on Chrome 113 (#60) -- so the detail-view mount would have broken `queue-panel`'s working context menu on the one device this is about. The panel's ancestry today is paint-free to `body`. Two details that fail silently otherwise. The entry is unwound from the panel's `open` attribute in the observer that already ran for `aria-expanded`, not at each of the four ways out -- without that the entry is orphaned and the *next* back press is the one that closes the queue, which is this defect moved one press later. And the navigation writes neither `dataset.activeView` nor `searchStore.setCurrentView`, because both describe what is *in* the main panel and the queue covers that panel without replacing it. `now-playing-view`'s copy of the button went through the helper too: it set `open` directly, so on a phone it produced exactly the queue with no entry behind it that this removes. Closes #55
55 lines
2.1 KiB
TypeScript
55 lines
2.1 KiB
TypeScript
/**
|
|
* Opening the queue, from the two buttons that do it.
|
|
*
|
|
* **The queue is a place while it is covering the content, and a
|
|
* control while it sits beside it** (#55). Those are not two components
|
|
* and not two mount points — they are the two presentations #24 already
|
|
* computes, and this is the one line that turns that measurement into a
|
|
* navigation decision.
|
|
*
|
|
* A column is a thing the user docked: back must not undock it, and
|
|
* navigating to Albums must not take it away. An overlay is a screen —
|
|
* at the reference device's 424x439 it is 424x318, which is
|
|
* `.main-panel`'s rect exactly — so it needs the two things a screen
|
|
* has and this one did not: an entry in the back stack, and a way out
|
|
* that answers the platform's own gesture. Measured before this existed:
|
|
* opening the queue on Artists and pressing back moved the page
|
|
* *underneath* to Albums and left the queue up.
|
|
*
|
|
* The mode is read off the panel rather than from a viewport width, for
|
|
* the reason `queue-panel.overlay` is computed at all: the panel is
|
|
* drag-resizable between 200 and 500px and persisted, so a breakpoint
|
|
* is wrong by up to 180px in the direction that hurts.
|
|
*/
|
|
export function queuePanelElement(): HTMLElement | null {
|
|
return document.getElementById('queue-panel');
|
|
}
|
|
|
|
/** Whether the queue is currently a screen rather than a column. */
|
|
export function queueIsAScreen(): boolean {
|
|
return queuePanelElement()?.hasAttribute('overlay') ?? false;
|
|
}
|
|
|
|
/**
|
|
* Show the queue: a navigation where it is a screen, an attribute where
|
|
* it is a column.
|
|
*
|
|
* Both routes end at the same `open` attribute on the same element —
|
|
* `index.ts` handles `navigate {view: 'queue'}` by setting it — because
|
|
* the panel's state is one fact and a second mechanism for it is a
|
|
* second thing to keep in step.
|
|
*/
|
|
export function openQueue(): void {
|
|
if (queueIsAScreen()) {
|
|
document.dispatchEvent(new CustomEvent('navigate', {
|
|
bubbles: true,
|
|
composed: true,
|
|
detail: { view: 'queue' },
|
|
}));
|
|
|
|
return;
|
|
}
|
|
|
|
queuePanelElement()?.setAttribute('open', '');
|
|
}
|