// SPDX-License-Identifier: AGPL-3.0-or-later
import {
LitElement,
html,
css,
} from "//shared.localhost:8888/third_party/lit/lit-all.min.js";
export class NotificationPanel extends LitElement {
static properties = {
open: { type: Boolean, reflect: true },
notifications: { type: Array, state: true },
};
static styles = css`
@import url("//system.localhost:8888/notification_panel.css");
`;
constructor() {
super();
this.open = false;
this.notifications = [];
this.handleKeyDown = this.handleKeyDown.bind(this);
}
connectedCallback() {
super.connectedCallback();
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListeners();
}
updated(changedProperties) {
if (changedProperties.has("open")) {
if (this.open) {
requestAnimationFrame(() => {
document.addEventListener("keydown", this.handleKeyDown);
});
} else {
this.removeEventListeners();
}
}
}
removeEventListeners() {
document.removeEventListener("keydown", this.handleKeyDown);
}
handleKeyDown(e) {
if (e.key === "Escape") {
this.close();
}
}
close() {
this.open = false;
this.dispatchEvent(
new CustomEvent("panel-closed", {
bubbles: true,
composed: true,
})
);
}
handleBackdropClick(e) {
if (e.target.classList.contains("backdrop")) {
this.close();
}
}
handleNotificationClick(notification, e) {
// Don't handle click if dismiss button was clicked
if (e.target.closest(".notification-dismiss")) {
return;
}
this.dispatchEvent(
new CustomEvent("notification-click", {
bubbles: true,
composed: true,
detail: { notification },
})
);
}
handleDismiss(notification, e) {
e.stopPropagation();
this.dispatchEvent(
new CustomEvent("notification-dismiss", {
bubbles: true,
composed: true,
detail: { notification },
})
);
}
handleClearAll() {
this.dispatchEvent(
new CustomEvent("notification-clear-all", {
bubbles: true,
composed: true,
})
);
}
formatTimeAgo(timestamp) {
if (!timestamp) {
return "";
}
const now = Date.now();
const diff = now - timestamp;
const seconds = Math.floor(diff / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (days > 0) {
return `${days}d ago`;
}
if (hours > 0) {
return `${hours}h ago`;
}
if (minutes > 0) {
return `${minutes}m ago`;
}
return "Just now";
}
renderNotificationIcon(notification) {
if (notification.iconUrl) {
return html``;
}
return html`