feat(panels): render each panel's state classes from the store

A panel's collapsed, dock-pinned, dock-pinned-top, layout-auto-collapsed
and accordion-collapsed classes are drawn by its root's v-panel-state from
the gev-panel-chrome store. PanelChrome, its restore, the layout
controller, both rails and the side accordion present each panel's state
there instead of writing its classes; the rails call onCollapse(panel,
{collapsed, auto}). The directive applies a change in a synchronous
watcher, since the rails measure a panel in the task that opens or closes
it.

Destroying the chrome inside Cockpit now puts back the panels Cockpit's
entry closed while it can still present them. Without a shell, the voice
tools' set_panel_open reports that there is no panel to open. QA scripts
present the states they set instead of writing the classes.
This commit is contained in:
Sameh Khamis committed 2026-10-31 23:51:47 -07:00
1 parent dd3a2c87f9
commit 95523e09cd
37 files changed
+404 -135

No files matched your search

+9 -4
View File
@@ -6,6 +6,7 @@ import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { createPinia } from 'pinia';
import { msg, t } from './i18n/index.js';
import { followPanelState, readPanelState } from './ui/rail/panelState.js';
import { usePanelChromeStore } from './ui/stores/panelChrome.js';
// Exercise the installed event routes and central close method, without WebGL.
@@ -108,18 +109,22 @@ function harness({ hidden = false, selected = true, noChips = false } = {}) {
window.clearTimeout = (id) => timers.delete(id);
window.performance = { now: () => now };
document.defaultView = window;
const methods = new Function('createHoverDisclosure', 'collapsePanelOnEscape', 'document', 'window', 'clearTimeout', 'performance', 'requestAnimationFrame', 't', 'msg',
`return ({${shellMethod('_initAutoHoverPanel').toString()},\n${shellMethod('_collapsePanelOnEscape').toString()},\n${shellMethod('setPanelCollapsed').toString()},\n${shellMethod('_syncPanelCollapseButton').toString()}});`)(
createHoverDisclosure, collapsePanelOnEscape, document, window, (id) => timers.delete(id), { now: () => now }, () => {}, t, msg,
const methods = new Function('createHoverDisclosure', 'collapsePanelOnEscape', 'document', 'window', 'clearTimeout', 'performance', 'requestAnimationFrame', 't', 'msg', 'readPanelState',
`return ({${shellMethod('_initAutoHoverPanel').toString()},\n${shellMethod('_collapsePanelOnEscape').toString()},\n${shellMethod('setPanelCollapsed').toString()},\n${shellMethod('_presentPanel').toString()}});`)(
createHoverDisclosure, collapsePanelOnEscape, document, window, (id) => timers.delete(id), { now: () => now }, () => {}, t, msg, readPanelState,
);
const saves = [];
const claims = [];
let shareSyncs = 0;
const chromeStore = usePanelChromeStore(createPinia());
const chromeToken = chromeStore.connect({});
// The trays' roots draw the store's state, as v-panel-state does.
followPanelState(chromeStore, 'control-panel', panel);
followPanelState(chromeStore, 'location-bar', location);
const manager = {
_lifetime: { frame() {} },
_chromeStore: chromeStore,
_chromeToken: chromeStore.connect({}),
_chromeToken: chromeToken,
_panelLayout: { _leftStackPreferredPanelId: null, _rightStackPreferredPanelId: null },
...methods,
_savePanelCollapsedState(...args) { saves.push(args); },