71 lines
4.3 KiB
JavaScript
71 lines
4.3 KiB
JavaScript
|
|
// Loaded by normal Hub pages; dormant when the remote feature is disabled.
|
||
|
|
(async () => {
|
||
|
|
if (/^\/sag\/\d+\/v5\/?$/.test(location.pathname)) return;
|
||
|
|
const {api, bootstrap, requestId} = await import('/static/js/remote-api.js');
|
||
|
|
try { await bootstrap(); } catch (_) { return; }
|
||
|
|
const panel = document.createElement('div');
|
||
|
|
panel.style.cssText = 'position:fixed;right:12px;top:74px;z-index:1025;background:var(--bg-card,#fff);border:1px solid #ccd6df;border-radius:8px;padding:6px;display:flex;gap:8px;align-items:center;font-size:12px';
|
||
|
|
const link = document.createElement('a'); link.href = '/remote/manage'; link.textContent = 'Fjernbetjening';
|
||
|
|
const button = document.createElement('button'); button.className = 'btn btn-sm btn-outline-secondary'; button.textContent = 'Følg i denne fane';
|
||
|
|
panel.append(link, button); document.body.append(panel);
|
||
|
|
const previousTabId = sessionStorage.getItem('hubRemoteTab');
|
||
|
|
const tabId = requestId();
|
||
|
|
let following = sessionStorage.getItem('hubRemoteFollow') === 'yes';
|
||
|
|
// Browsers copy sessionStorage when duplicating a tab. Detect a living original
|
||
|
|
// so a duplicate cannot silently take over its remote connection.
|
||
|
|
if (typeof BroadcastChannel !== 'undefined') {
|
||
|
|
const channel = new BroadcastChannel('hub-remote-tabs');
|
||
|
|
let duplicate = false;
|
||
|
|
channel.onmessage = ({data}) => {
|
||
|
|
if (data.type === 'probe' && data.previous === tabId) channel.postMessage({type:'occupied',target:data.target});
|
||
|
|
if (data.type === 'occupied' && data.target === tabId) duplicate = true;
|
||
|
|
};
|
||
|
|
if (previousTabId) {
|
||
|
|
channel.postMessage({type:'probe',previous:previousTabId,target:tabId});
|
||
|
|
await new Promise(resolve => setTimeout(resolve, 150));
|
||
|
|
if (duplicate) { following = false; sessionStorage.setItem('hubRemoteFollow', 'no'); }
|
||
|
|
}
|
||
|
|
window.addEventListener('pagehide', () => channel.close(), {once:true});
|
||
|
|
}
|
||
|
|
sessionStorage.setItem('hubRemoteTab', tabId);
|
||
|
|
let sequence = 0, pending = false;
|
||
|
|
let dirty = false;
|
||
|
|
document.addEventListener('input', event => { if (event.isTrusted && !panel.contains(event.target)) dirty = true; });
|
||
|
|
document.addEventListener('change', event => { if (event.isTrusted && !panel.contains(event.target)) dirty = true; });
|
||
|
|
const label = () => { button.textContent = following ? 'Stop med at følge' : 'Følg i denne fane'; };
|
||
|
|
async function enable() {
|
||
|
|
const result = await api('/follow', {tab_id: tabId, enable: true});
|
||
|
|
following = result.following; sequence = result.sequence; sessionStorage.setItem('hubRemoteFollow', following ? 'yes' : 'no'); label();
|
||
|
|
}
|
||
|
|
button.onclick = async () => {
|
||
|
|
if (pending) return;
|
||
|
|
pending = true; button.disabled = true;
|
||
|
|
try {
|
||
|
|
if (following) { await api('/follow', {tab_id: tabId, disable: true}); following = false; sessionStorage.setItem('hubRemoteFollow', 'no'); label(); }
|
||
|
|
else await enable();
|
||
|
|
} catch (error) { button.title = error.message; }
|
||
|
|
finally { pending = false; button.disabled = false; }
|
||
|
|
};
|
||
|
|
async function poll() {
|
||
|
|
if (!following || pending || document.hidden) return;
|
||
|
|
pending = true;
|
||
|
|
try {
|
||
|
|
const result = await api('/follow', {tab_id: tabId, after: sequence});
|
||
|
|
following = result.following; sequence = result.sequence; label();
|
||
|
|
if (!following) sessionStorage.setItem('hubRemoteFollow', 'no');
|
||
|
|
if (result.selection) {
|
||
|
|
const path = `/sag/${result.selection.case_id}`;
|
||
|
|
if (!location.pathname.match(new RegExp(`^${path}(/|$)`))) {
|
||
|
|
// Keep an in-progress user edit visible before leaving the page.
|
||
|
|
const editing = dirty || ['INPUT', 'TEXTAREA', 'SELECT'].includes(document.activeElement?.tagName);
|
||
|
|
if (!editing || confirm('Fjernbetjeningen har valgt en anden sag. Skift nu?')) location.assign(path);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} catch (error) { button.title = 'Forbindelse afbrudt · ' + error.message; }
|
||
|
|
finally { pending = false; }
|
||
|
|
}
|
||
|
|
if (following) { try { await enable(); } catch (_) { following = false; } }
|
||
|
|
label(); setInterval(poll, 3000);
|
||
|
|
document.addEventListener('visibilitychange', () => { if (!document.hidden) poll(); });
|
||
|
|
})();
|