Files
Git-Manager-Gui/renderer/tray-menu.js
T
2026-10-22 09:13:21 +00:00

81 lines
3.3 KiB
JavaScript

// 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);
})();