Upload via GUI (85 Dateien)
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
// Zeichnet das Tray-Menü aus dem Zustand, den der Hauptprozess schickt.
|
||||
// Ohne Electron (Seite direkt im Browser geöffnet) greift ein Stub, damit sich die Optik prüfen lässt.
|
||||
(function () {
|
||||
const api = window.trayApi || {
|
||||
onState: () => {},
|
||||
action: (id) => console.log('action', id),
|
||||
resize: () => {},
|
||||
close: () => {}
|
||||
};
|
||||
|
||||
const menu = document.getElementById('menu');
|
||||
let buttons = [];
|
||||
let activeIndex = -1;
|
||||
|
||||
function setActive(index) {
|
||||
activeIndex = index;
|
||||
buttons.forEach((b, i) => b.classList.toggle('active', i === index));
|
||||
}
|
||||
|
||||
function render(state) {
|
||||
document.body.classList.toggle('light', state && state.dark === false);
|
||||
menu.textContent = '';
|
||||
buttons = [];
|
||||
activeIndex = -1;
|
||||
|
||||
for (const item of (state && state.items) || []) {
|
||||
if (item.type === 'separator') {
|
||||
const sep = document.createElement('div');
|
||||
sep.className = 'sep';
|
||||
menu.appendChild(sep);
|
||||
continue;
|
||||
}
|
||||
if (item.id === 'header' || item.id === 'status' || item.id === 'queue') {
|
||||
const line = document.createElement('div');
|
||||
line.className = item.id === 'header' ? 'header' : 'status';
|
||||
line.textContent = item.label;
|
||||
menu.appendChild(line);
|
||||
continue;
|
||||
}
|
||||
const button = document.createElement('button');
|
||||
button.className = 'item';
|
||||
button.disabled = item.enabled === false;
|
||||
button.setAttribute('role', item.type === 'checkbox' ? 'menuitemcheckbox' : 'menuitem');
|
||||
if (item.type === 'checkbox') button.setAttribute('aria-checked', String(!!item.checked));
|
||||
|
||||
const check = document.createElement('span');
|
||||
check.className = 'check';
|
||||
check.textContent = item.type === 'checkbox' && item.checked ? '✓' : '';
|
||||
const label = document.createElement('span');
|
||||
label.textContent = item.label;
|
||||
button.append(check, label);
|
||||
|
||||
button.addEventListener('click', () => api.action(item.id));
|
||||
button.addEventListener('mouseenter', () => { if (!button.disabled) setActive(buttons.indexOf(button)); });
|
||||
button.addEventListener('mouseleave', () => setActive(-1));
|
||||
menu.appendChild(button);
|
||||
buttons.push(button);
|
||||
}
|
||||
|
||||
api.resize(Math.ceil(document.body.scrollHeight));
|
||||
}
|
||||
|
||||
function move(step) {
|
||||
const enabled = buttons.map((b, i) => (b.disabled ? -1 : i)).filter((i) => i >= 0);
|
||||
if (enabled.length === 0) return;
|
||||
const pos = enabled.indexOf(activeIndex);
|
||||
const next = pos < 0 ? (step > 0 ? 0 : enabled.length - 1) : (pos + step + enabled.length) % enabled.length;
|
||||
setActive(enabled[next]);
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') api.close();
|
||||
else if (e.key === 'ArrowDown') { e.preventDefault(); move(1); }
|
||||
else if (e.key === 'ArrowUp') { e.preventDefault(); move(-1); }
|
||||
else if ((e.key === 'Enter' || e.key === ' ') && buttons[activeIndex]) { e.preventDefault(); buttons[activeIndex].click(); }
|
||||
});
|
||||
|
||||
window.__renderTray = render;
|
||||
api.onState(render);
|
||||
})();
|
||||
Reference in New Issue
Block a user