mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
Keep Contact folded until both Cockpit left panels close, and keep focus in a renamed row
Opening Utilities while Data Layers is open no longer forgets that Contact was folded for the first, and closing one of them leaves Contact folded while the other is still open. Enter and Esc in a drawn shape's name keep focus in the field instead of dropping it to the page. The draw tool's destroy test now checks it stops following the board, and the Draw gate's amber-count comment sits on its function again.
This commit is contained in:
1 parent
345d5db593
commit
672a145254
7 files changed
+68
-15
No files matched your search
@@ -183,6 +183,7 @@ function fakeAnnotations() {
|
||||
return {
|
||||
calls,
|
||||
marks,
|
||||
listeners,
|
||||
changed,
|
||||
async annotate(specs, options) {
|
||||
calls.annotate.push({ specs, options });
|
||||
@@ -459,6 +460,7 @@ test('destroy releases the pointer, the handler, the listeners and the stock act
|
||||
h.tool.addVertex(-97.75, 30.26);
|
||||
assert.equal(pointerOwner(), 'draw');
|
||||
assert.ok(h.tool.diagnostics().domListeners > 0);
|
||||
assert.equal(h.annotations.listeners.size, 1, 'the rows follow the board');
|
||||
|
||||
await h.tool.destroy();
|
||||
await Promise.resolve();
|
||||
@@ -476,6 +478,7 @@ test('destroy releases the pointer, the handler, the listeners and the stock act
|
||||
'the viewer got its selecting click back',
|
||||
);
|
||||
assert.equal(h.viewer._attached.length, 0, 'the preview data source is detached');
|
||||
assert.equal(h.annotations.listeners.size, 0, 'and it no longer follows the board');
|
||||
|
||||
// Idempotent: a second destroy is harmless.
|
||||
await h.tool.destroy();
|
||||
|
||||
@@ -1385,3 +1385,27 @@ test('cockpit state cannot report entryAllowed while already active', () => {
|
||||
assert.match(state, /'contacts-inactive'/);
|
||||
assert.match(state, /'no-tracked-aircraft'/);
|
||||
});
|
||||
|
||||
test('Contact folded for one Cockpit left panel comes back only once neither is open', async () => {
|
||||
assert.match(
|
||||
ui,
|
||||
/if \(!this\._cockpitContextCollapsedForDataPanel\)\s*this\._cockpitContextCollapsedForDataPanel =\s*!this\.cockpitView\.contextCollapsed;/,
|
||||
'opening the second left panel keeps the fold the first recorded',
|
||||
);
|
||||
const { PanelChrome } = await import('./ui/panelChrome.js');
|
||||
const previous = globalThis.document;
|
||||
const panels = {};
|
||||
globalThis.document = { getElementById: (id) => panels[id] ?? null };
|
||||
const panel = (...classes) => ({ classList: { contains: (name) => classes.includes(name) } });
|
||||
try {
|
||||
const otherOpen = (id) => PanelChrome.prototype._otherCockpitLeftPanelOpen(id);
|
||||
panels['data-panel'] = panel('collapsed');
|
||||
assert.equal(otherOpen('utilities-panel'), false, 'Data Layers closed: restore');
|
||||
panels['data-panel'] = panel('collapsed', 'layout-auto-collapsed');
|
||||
assert.equal(otherOpen('utilities-panel'), true, 'Data Layers comes back: keep Contact folded');
|
||||
panels['data-panel'] = panel();
|
||||
assert.equal(otherOpen('utilities-panel'), true, 'Data Layers open: keep it folded');
|
||||
} finally {
|
||||
globalThis.document = previous;
|
||||
}
|
||||
});
|
||||
+24
-3
@@ -52,6 +52,23 @@ const COCKPIT_ENTRY_COLLAPSE_PANEL_IDS = Object.freeze([
|
||||
|
||||
/** Own panel disclosure, docking, persistence and Cockpit rail restoration. */
|
||||
export class PanelChrome {
|
||||
/**
|
||||
* Whether another left panel Cockpit keeps is open, or only folded aside
|
||||
* for this one and coming back when it closes.
|
||||
* @param {string} panelId The panel closing.
|
||||
*/
|
||||
_otherCockpitLeftPanelOpen(panelId) {
|
||||
return [...COCKPIT_LEFT_PANEL_IDS].some((id) => {
|
||||
if (id === panelId) return false;
|
||||
const panel = document.getElementById(id);
|
||||
return (
|
||||
!!panel &&
|
||||
(!panel.classList.contains('collapsed') ||
|
||||
panel.classList.contains('layout-auto-collapsed'))
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
constructor({
|
||||
elements,
|
||||
operations,
|
||||
@@ -504,8 +521,11 @@ export class PanelChrome {
|
||||
this.cockpitView?.active &&
|
||||
COCKPIT_LEFT_PANEL_IDS.has(panelId)
|
||||
) {
|
||||
this._cockpitContextCollapsedForDataPanel =
|
||||
!this.cockpitView.contextCollapsed;
|
||||
// Record the fold once: opening the other left panel after the first
|
||||
// must not forget that Contact was folded for them.
|
||||
if (!this._cockpitContextCollapsedForDataPanel)
|
||||
this._cockpitContextCollapsedForDataPanel =
|
||||
!this.cockpitView.contextCollapsed;
|
||||
if (this._cockpitContextCollapsedForDataPanel) {
|
||||
this.cockpitView.setContextCollapsed(true);
|
||||
}
|
||||
@@ -534,7 +554,8 @@ export class PanelChrome {
|
||||
nextCollapsed &&
|
||||
this.cockpitView?.active &&
|
||||
COCKPIT_LEFT_PANEL_IDS.has(panelId) &&
|
||||
this._cockpitContextCollapsedForDataPanel
|
||||
this._cockpitContextCollapsedForDataPanel &&
|
||||
!this._otherCockpitLeftPanelOpen(panelId)
|
||||
) {
|
||||
this._cockpitContextCollapsedForDataPanel = false;
|
||||
this.cockpitView.setContextCollapsed(false);
|
||||
|
||||
@@ -101,6 +101,9 @@ test('a name is saved on Enter or leaving the field; an unchanged one costs noth
|
||||
name.value = ' Ridge walk ';
|
||||
key(name, 'Enter');
|
||||
assert.deepEqual(calls, [['renameDrawMark', 'a1', 'Ridge walk']]);
|
||||
assert.equal(document.activeElement, name, 'Enter keeps focus in the field');
|
||||
name.blur();
|
||||
assert.equal(calls.length, 1, 'the blur after Enter saves nothing more');
|
||||
const pinName = control('a2', 'name');
|
||||
pinName.focus();
|
||||
pinName.blur();
|
||||
@@ -122,6 +125,7 @@ test('Escape drops the draft and stays in the list, even with the row\'s colours
|
||||
const event = key(name, 'Escape');
|
||||
assert.equal(event.defaultPrevented, true);
|
||||
assert.equal(name.value, 'Camp', 'the saved name comes back');
|
||||
assert.equal(document.activeElement, name, 'focus stays in the field');
|
||||
await nextTick();
|
||||
assert.deepEqual(calls, [], 'the draft is not saved');
|
||||
// Escape in the open colours closes them and gives focus to the swatch.
|
||||
|
||||
@@ -42,15 +42,16 @@ function onNameKey(row, event) {
|
||||
const input = event.currentTarget;
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
// Saved, and focus stays here: blurring would drop it to the page.
|
||||
commit(row, input);
|
||||
input.blur();
|
||||
input.select();
|
||||
} else if (event.key === 'Escape') {
|
||||
// Escape drops the draft before anything else, an open colour picker
|
||||
// included, and stays in the list: it must not leave Draw.
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
input.value = rowOf(row.id)?.name ?? row.name;
|
||||
input.blur();
|
||||
input.select();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user