Files
radixOS/public/javascript/notifyBubble.js
2026-04-22 11:55:23 +02:00

157 lines
4.7 KiB
JavaScript

class NotifyBubble {
constructor(trayButton, bubbleSelector) {
this.button = trayButton;
this.bubble = document.querySelector(bubbleSelector);
this.hideTimeout = null;
this.initEvents();
this.initExistingItems();
this.updateCounter(); // 🔥 initialer Counter
}
/* =========================
SHOW / HIDE
========================== */
show() {
clearTimeout(this.hideTimeout);
this.button.classList.add("active");
// Tooltip entfernen beim Öffnen
this.button.removeAttribute('data-tooltip');
}
hide(delay = 1000) {
clearTimeout(this.hideTimeout);
this.hideTimeout = setTimeout(() => {
this.button.classList.remove("active");
// 🔥 Counter nach Schließen anzeigen
this.updateCounter();
}, delay);
}
/* =========================
COUNTER / TOOLTIP
========================== */
updateCounter() {
const items = this.bubble.querySelectorAll(".bubble-item");
const count = items.length;
if (!this.button.classList.contains("active") && count > 0) {
this.button.setAttribute('data-tooltip', `${count} neue Benachrichtigung${count > 1 ? 'en' : ''}`);
} else {
this.button.setAttribute('data-tooltip', "Keine Benachrichtigungen");
}
}
/* =========================
EVENTS
========================== */
initEvents() {
// Toggle bei Klick auf Button
this.button.addEventListener("click", (e) => {
e.stopPropagation();
if (this.button.classList.contains("active")) {
this.hide(0);
} else {
this.show();
}
});
// Klick innerhalb der Bubble soll NICHT schließen
this.bubble.addEventListener("click", (e) => {
e.stopPropagation();
});
// Klick irgendwo anders → schließen
document.addEventListener("click", () => {
if (this.button.classList.contains("active")) {
this.hide(0);
}
});
}
/* =========================
INIT EXISTING ITEMS
========================== */
initExistingItems() {
this.bubble.querySelectorAll(".bubble-item").forEach(item => {
this.attachItemEvents(item);
});
}
/* =========================
ITEM EVENTS
========================== */
attachItemEvents(item) {
item.addEventListener("click", () => {
const checkbox = item.querySelector("input[type='checkbox']");
if (checkbox) {
checkbox.checked = !checkbox.checked;
fetch('/api/NotifyTray/markAsSeen', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: item.dataset.id,
value: checkbox.checked
})
});
// 🔥 Counter ggf. aktualisieren
this.updateCounter();
}
});
}
/* =========================
ADD SINGLE ITEM
========================== */
addItem(notification) {
const item = document.createElement("label");
item.className = "bubble-item";
item.dataset.id = notification.ID;
item.innerHTML = `
<div>${notification.Message}</div>
<div style="display:flex;flex-direction:row;flex-wrap:no-wrap;justify-content:flex-end;gap:10px;align-items:center;">
<div>
<div>${dateFormat(notification.CreatedAt, 'dd.mm.yyyy HH:MM:SS')}</div>
<div>${notification.PluginName}</div>
</div>
<div>
<label class="cb cb-modern">
<input id="notification_${notification.ID}" type="checkbox">
<span class="cb-box"></span>
</label>
</div>
</div>
`;
this.attachItemEvents(item);
this.bubble.appendChild(item);
// 🔥 Counter aktualisieren
this.updateCounter();
}
/* =========================
ADD MULTIPLE ITEMS
========================== */
addItems(notifications) {
notifications.forEach(n => this.addItem(n));
}
/* =========================
CLEAR
========================== */
clear() {
this.bubble.innerHTML = "";
this.updateCounter();
}
}