Versie 0.2.0

This commit is contained in:
Atreides Assets committed 2026-10-29 11:57:29 +01:00
commit e77d8fd373
495 files changed
+81026

No files matched your search

+123
View File
@@ -0,0 +1,123 @@
// Generated, do not edit. sha256:a469a46a90e6bcc2ab27a831978cd788d57e02abb6e3347f99750cb9fb53c286
import { claimNextCommand, resolveCommand } from './data/commands.js';
import { CONFIG, PLACE_LABELS, hashFromLocation, commandTooLate } from '../shared/config.js';
import { t } from './i18n/index.js';
import { esc } from './ui/escape.js';
const TAB = (globalThis.crypto?.randomUUID?.() || `tab-${Date.now()}-${Math.random()}`).slice(0, 40);
const KAN = Object.freeze(['navigate', 'locate']);
let bezig = false;
export function initCommands() {
document.addEventListener('commands-changed', () => { pakOp(); });
pakOp();
}
export async function pakOp() {
if (bezig) return;
bezig = true;
try {
const opdracht = await claimNextCommand(TAB, KAN);
if (opdracht) await voerUit(opdracht);
} catch { }
finally { bezig = false; }
}
async function voerUit(opdracht) {
if (opdracht.kind === 'locate') {
await resolveCommand(opdracht.id, TAB, 'done', hashFromLocation(location.hash));
return;
}
if (opdracht.kind !== 'navigate') {
await resolveCommand(opdracht.id, TAB, 'rejected', t('commands.unknownKind'));
return;
}
const hash = opdracht.payload && typeof opdracht.payload.hash === 'string' ? opdracht.payload.hash : '';
if (!hash.startsWith('#/')) {
await resolveCommand(opdracht.id, TAB, 'rejected', t('commands.badTarget'));
return;
}
if (commandTooLate(opdracht.expiresAt)) {
await resolveCommand(opdracht.id, TAB, 'expired', t('commands.tooLate'));
return;
}
const doorgaan = await aftellen(plekNaam(opdracht.payload));
if (!doorgaan) {
await resolveCommand(opdracht.id, TAB, 'rejected', t('commands.stopped'));
return;
}
location.hash = hash;
await resolveCommand(opdracht.id, TAB, 'done');
}
function plekNaam({ route, tab, sub }) {
const label = (id) => { try { return t(PLACE_LABELS[id] || `nav.${id}`); } catch { return id; } };
return [label(route), tab && label(tab), sub && label(sub)].filter(Boolean).join(' → ');
}
let directVoortaan = false;
function toonBalk(inhoud) {
const bar = document.createElement('div');
bar.className = 'cmd-bar';
bar.setAttribute('role', 'alert');
bar.innerHTML = inhoud;
document.body.appendChild(bar);
return bar;
}
const knop = (data, tekst, soort = 'secondary') =>
`<button type="button" class="btn btn-${soort} btn-sm" ${data}>${tekst}</button>`;
const knoppen = (...items) => `<div class="cmd-bar-buttons">${items.join('')}</div>`;
function meldDirect(plek) {
const bar = toonBalk(`<span class="cmd-bar-text">${t('commands.movedTo')} <strong>${esc(plek)}</strong></span>`
+ knoppen(knop('data-countdown-back', t('commands.countdownBack'))));
const weg = setTimeout(() => bar.remove(), CONFIG.COMMANDS.NOTICE_SECONDS * 1000);
bar.querySelector('[data-countdown-back]').addEventListener('click', () => {
directVoortaan = false;
clearTimeout(weg);
bar.remove();
});
}
function aftellen(plek) {
if (directVoortaan) { meldDirect(plek); return Promise.resolve(true); }
const seconden = CONFIG.COMMANDS.COUNTDOWN_SECONDS;
return new Promise((klaar) => {
let over = seconden;
const tekst = () => `${t('commands.goingTo')} <strong>${esc(plek)}</strong> (${over})`;
const bar = toonBalk(`<span class="cmd-bar-text">${tekst()}</span>`
+ knoppen(
knop('data-now', t('commands.goNow'), 'primary'),
knop('data-always', t('commands.goAlways')),
knop('data-stop', t('commands.stop')),
));
const op = (doorgaan) => {
clearInterval(tik);
document.removeEventListener('keydown', opEscape);
bar.remove();
klaar(doorgaan);
};
const opEscape = (e) => { if (e.key === 'Escape') op(false); };
bar.querySelector('[data-stop]').addEventListener('click', () => op(false));
const nu = bar.querySelector('[data-now]');
nu.addEventListener('click', () => op(true));
nu.focus();
bar.querySelector('[data-always]').addEventListener('click', () => { directVoortaan = true; op(true); });
document.addEventListener('keydown', opEscape);
const tik = setInterval(() => {
over -= 1;
if (over <= 0) { op(true); return; }
bar.querySelector('.cmd-bar-text').innerHTML = tekst();
}, 1000);
});
}