mirror of
https://github.com/sol1/rustguac.git
synced 2026-10-25 13:09:56 +00:00
connect: leaving fullscreen keeps the session, with a button back
The launcher tore the session down whenever the tab left fullscreen, so holding Escape, F11 or a gesture from the OS ended it. Leaving fullscreen now keeps the session at the tab's size and shows a Fullscreen button that goes back; only Exit, or the session ending, closes it. Tested with the browser's fullscreen events faked, since headless Chromium refuses the real request.
This commit is contained in:
+6
-3
@@ -1141,12 +1141,15 @@ html:not([data-role-level="4"]) .admin-only { display: none !important; }
|
||||
border: 3px solid rgba(255,255,255,0.25); border-top-color: var(--accent, #5bc0be);
|
||||
border-radius: 50%; animation: rg-btn-spin 0.8s linear infinite;
|
||||
}
|
||||
#rg-session-exit {
|
||||
position: absolute; top: 10px; right: 14px; z-index: 5001;
|
||||
#rg-session-exit { position: absolute; top: 10px; right: 14px; }
|
||||
#rg-session-fs { position: absolute; top: 10px; right: 104px; }
|
||||
#rg-session-fs[hidden] { display: none; }
|
||||
.rg-session-btn {
|
||||
z-index: 5001;
|
||||
height: 32px; padding: 0 var(--s-3, 14px);
|
||||
background: rgba(20,24,38,0.72); color: var(--text, #e0e0e0);
|
||||
border: 1px solid var(--border, #333); border-radius: var(--radius, 2px);
|
||||
font-family: monospace; font-size: var(--fz-sm, 16px); cursor: pointer;
|
||||
opacity: 0.35; transition: opacity 0.15s;
|
||||
}
|
||||
#rg-session-exit:hover { opacity: 1; background: var(--surface, #16213e); border-color: var(--primary, #e94560); color: var(--text, #e0e0e0); }
|
||||
.rg-session-btn:hover { opacity: 1; background: var(--surface, #16213e); border-color: var(--primary, #e94560); color: var(--text, #e0e0e0); }
|
||||
|
||||
+15
-2
@@ -422,7 +422,8 @@
|
||||
} else fsRefused();
|
||||
var ov = document.createElement('div'); ov.id = 'rg-session-overlay';
|
||||
ov.innerHTML = '<div id="rg-session-spinner"></div>' +
|
||||
'<button id="rg-session-exit" type="button" title="Exit">× Exit</button>' +
|
||||
'<button id="rg-session-fs" class="rg-session-btn" type="button" title="Back to fullscreen" hidden>⛶ Fullscreen</button>' +
|
||||
'<button id="rg-session-exit" class="rg-session-btn" type="button" title="Leave the session">× Exit</button>' +
|
||||
'<iframe id="rg-session-frame" allow="fullscreen; clipboard-read; clipboard-write" title="Session"></iframe>';
|
||||
document.body.appendChild(ov);
|
||||
if (btn) { btn.classList.add('loading'); btn.disabled = true; }
|
||||
@@ -450,11 +451,23 @@
|
||||
// the settle check covers both.
|
||||
if (!started) armSettle();
|
||||
}
|
||||
else if (enteredFs) { teardown(); }
|
||||
// Leaving fullscreen (Escape held, F11, the OS) keeps the session:
|
||||
// it carries on at the tab's size and the button takes it back
|
||||
// to fullscreen. Only Exit, or the session ending, closes it.
|
||||
else if (enteredFs) { showFsButton(true); }
|
||||
if (document.fullscreenElement) showFsButton(false);
|
||||
}
|
||||
function showFsButton(on) {
|
||||
var b = document.getElementById('rg-session-fs'); if (b) b.hidden = !on;
|
||||
if (!on) { var f = document.getElementById('rg-session-frame'); try { if (f) f.focus(); } catch (e) {} }
|
||||
}
|
||||
window.addEventListener('message', onMsg);
|
||||
document.addEventListener('fullscreenchange', onFsChange);
|
||||
document.getElementById('rg-session-exit').addEventListener('click', teardown);
|
||||
document.getElementById('rg-session-fs').addEventListener('click', function () {
|
||||
// A click is a fresh gesture, so the browser allows fullscreen again.
|
||||
try { var p = req && req.call(el); if (p && p.catch) p.catch(function () {}); } catch (e) {}
|
||||
});
|
||||
// Create the session at the measured viewport size — the size the
|
||||
// frame paints into — so there is nothing to resize afterwards.
|
||||
function startConnect() {
|
||||
|
||||
@@ -55,3 +55,50 @@ test('a non-fullscreen entry connects the old way, with no frame', async ({ page
|
||||
expect(await page.locator('#rg-session-overlay').count()).toBe(0);
|
||||
if (popup) await popup.close();
|
||||
});
|
||||
|
||||
// Leaving fullscreen (Escape held, F11, the OS) must not end the session: the
|
||||
// frame stays at the tab's size and a button takes it back to fullscreen.
|
||||
// Headless Chromium refuses real fullscreen, so the browser's side is faked:
|
||||
// fullscreenElement is set and cleared and fullscreenchange fired, exactly
|
||||
// what the launcher listens to.
|
||||
test('leaving fullscreen keeps the session and offers to go back', async ({ page }) => {
|
||||
await page.addInitScript(() => {
|
||||
let fs = null;
|
||||
Object.defineProperty(Document.prototype, 'fullscreenElement', { configurable: true, get: () => fs });
|
||||
// Like a real browser, the change event fires after the call returns.
|
||||
const change = (el) => new Promise((resolve) => setTimeout(() => {
|
||||
fs = el;
|
||||
document.dispatchEvent(new Event('fullscreenchange'));
|
||||
resolve();
|
||||
}, 50));
|
||||
Element.prototype.requestFullscreen = function () { return change(document.documentElement); };
|
||||
document.exitFullscreen = function () { return change(null); };
|
||||
window.__leaveFullscreen = () => document.exitFullscreen();
|
||||
});
|
||||
await installApi(page);
|
||||
await page.goto('/connections.html');
|
||||
await settle(page);
|
||||
await page.locator('.folder-row').filter({ hasText: /acme/ }).first().click();
|
||||
const kiosk = page.locator('.entries-table tbody tr').filter({ hasText: 'kiosk' });
|
||||
await kiosk.locator('button', { hasText: /^Connect/ }).first().click();
|
||||
|
||||
const overlay = page.locator('#rg-session-overlay');
|
||||
const back = page.locator('#rg-session-fs');
|
||||
await expect(overlay).toBeVisible();
|
||||
await expect(back).toBeHidden();
|
||||
|
||||
// The user leaves fullscreen: the session is still there.
|
||||
await page.evaluate(() => window.__leaveFullscreen());
|
||||
await expect(overlay).toBeVisible();
|
||||
await expect(page.locator('#rg-session-frame')).toHaveCount(1);
|
||||
await expect(back).toBeVisible();
|
||||
|
||||
// The button goes back to fullscreen and hides itself.
|
||||
await back.click();
|
||||
await expect(back).toBeHidden();
|
||||
await expect(overlay).toBeVisible();
|
||||
|
||||
// Exit still ends it.
|
||||
await page.locator('#rg-session-exit').click();
|
||||
await expect(overlay).toHaveCount(0);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user