openvibers/openvibe.shared Commits

Dock: keep "in a window" to the page (#202)

OP OpenVibers committed 14 days ago · f612597037 · 3 files, +13 −12

The pop-out window belongs to one page in one browser, closes with it, and no other device can open it again
(the browser wants a click). The Network's network.dock-state@1 has no such key, so 4.54.0 made a refused PUT
and a retry on every pop-out; that ends too.

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex 60bd3cf..c2b2e0e 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -6,6 +6,11 @@ A release is the git tag `vX.Y.Z`; consumers pin the tag's tarball (see README).
## Unreleased
++- **The Dock keeps "in a window" to the page.** The pop-out window belongs to one page in one browser, closes with it,
++ and no other device can open it again (the browser wants a click), so the Dock no longer sends `popped` to the
++ Network. That also ends the refused PUT and its retry that 4.54.0 made on every pop-out, since the Network's
++ `network.dock-state@1` contract has no such key.
++
## 4.54.0 — 2026-10-30
- **The Dock pops out into a window of its own** (Dock plan K-D4). On a desktop browser that can (Chromium's Document
ddiff --git a/dock.js b/dock.js
iindex 51c96d6..e20e648 100644
---- a/dock.js
++++ b/dock.js
@@@ -78,13 +78,7 @@
const body = pending; pending = {};
if (!Object.keys(body).length) return;
try {
-- let r = await call('/api/v1/me/dock', { method: 'PUT', body: JSON.stringify(body) });
-- // A Network whose state contract does not know "popped" yet refuses the whole body; ask again without it,
-- // so the Dock's place and its tab still reach the Network.
-- if (!r && 'popped' in body) {
-- const rest = { ...body }; delete rest.popped;
-- r = await call('/api/v1/me/dock', { method: 'PUT', body: JSON.stringify(rest) });
-- }
++ const r = await call('/api/v1/me/dock', { method: 'PUT', body: JSON.stringify(body) });
if (r && r.state && !Object.keys(pending).length) { doc = { ...doc, state: r.state, counts: r.counts || counts() }; notify(); badges(); }
} catch { /* offline, or no route yet: the copy stands and the next change tries again */ }
}
@@@ -725,7 +719,9 @@
win.document.body.appendChild(el);
win.addEventListener('pagehide', () => { if (popped && !pipClosing) backToPage(); });
paintPop();
-- save({ open: true, popped: true });
++ // Whether the Dock is in a window stays with this page: the window belongs to one page in one browser, closes
++ // with it, and no other device could open it again (the browser wants a click), so the Network is not told.
++ save({ open: true });
paintPill();
}
@@@ -741,7 +737,6 @@
el.hidden = false;
layout();
paintPop();
-- save({ popped: false });
paintPill();
}
@@@ -777,7 +772,7 @@
document.documentElement.classList.remove('ovdk-sheet-open');
clear(0);
clearTimeout(chats.timer); clearTimeout(chats.unreadT);
-- save(wasPopped ? { open: false, popped: false } : { open: false });
++ save({ open: false });
if (inside) {
const back = pill && !pill.hidden ? pill : (lastFocus && lastFocus.isConnected ? lastFocus : null);
try { if (back) back.focus({ preventScroll: true }); } catch { /* */ }
ddiff --git a/test/dock-chrome.test.js b/test/dock-chrome.test.js
iindex ed89c75..931e8b4 100644
---- a/test/dock-chrome.test.js
++++ b/test/dock-chrome.test.js
@@@ -304,13 +304,14 @@ async function drag(p, from, to) {
const inWindow = await until(p, PILL, 'the pill stays');
assert.strictEqual(inWindow.text, 'In a window', 'the page keeps the pill, and it says where the Dock went');
await wait(900);
-- assert.ok(puts.some((b) => b.popped === true && b.open === true), `the Network is told the Dock is in a window (${JSON.stringify(puts)})`);
++ assert.ok(puts.some((b) => b.open === true), `the Network is told the Dock is open (${JSON.stringify(puts)})`);
++ assert.ok(!puts.some((b) => 'popped' in b), `and never where its window is: that stays with this page (${JSON.stringify(puts)})`);
// The window is closed: the panel comes back to the page.
await p.evaluate("window.__pip.close()");
await until(p, "!!document.querySelector('.ovdk')", 'the panel back on the page');
assert.strictEqual(await p.evaluate("!!window.__pip.win.document.querySelector('.ovdk')"), false, 'and out of the window');
await wait(900);
-- assert.ok(puts.some((b) => b.popped === false), `and told it is back (${JSON.stringify(puts)})`);
++ assert.ok(!puts.some((b) => 'popped' in b), `nor that it is back (${JSON.stringify(puts)})`);
await p.close();
}