2024-11-03 08:37:01 -05:00
|
|
|
import { Controller } from "@hotwired/stimulus"
|
|
|
|
|
import consumer from "../channels/consumer"
|
|
|
|
|
|
|
|
|
|
export default class extends Controller {
|
2024-11-07 13:00:11 -05:00
|
|
|
static targets = ["badge", "list"]
|
2024-11-03 08:37:01 -05:00
|
|
|
static values = { userId: Number }
|
|
|
|
|
|
2024-11-03 09:21:29 -05:00
|
|
|
initialize() {
|
|
|
|
|
this.subscription = null
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-03 08:37:01 -05:00
|
|
|
connect() {
|
2024-11-07 07:30:58 -05:00
|
|
|
// console.log("[Stimulus] Notifications controller connecting...")
|
2024-11-03 09:21:29 -05:00
|
|
|
|
|
|
|
|
// Clean up any existing subscription
|
2024-11-03 08:37:01 -05:00
|
|
|
if (this.subscription) {
|
2024-11-07 07:30:58 -05:00
|
|
|
// console.log("[Stimulus] Cleaning up existing subscription")
|
2024-11-03 08:37:01 -05:00
|
|
|
this.subscription.unsubscribe()
|
2024-11-03 09:21:29 -05:00
|
|
|
this.subscription = null
|
2024-11-03 08:37:01 -05:00
|
|
|
}
|
|
|
|
|
|
2024-11-03 09:21:29 -05:00
|
|
|
// Create new subscription
|
|
|
|
|
this.createSubscription()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
disconnect() {
|
2024-11-07 07:30:58 -05:00
|
|
|
// console.log("[Stimulus] Notifications controller disconnecting...")
|
2024-11-03 09:21:29 -05:00
|
|
|
if (this.subscription) {
|
|
|
|
|
this.subscription.unsubscribe()
|
|
|
|
|
this.subscription = null
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
createSubscription() {
|
2024-11-07 07:30:58 -05:00
|
|
|
// console.log("[Stimulus] Creating new notification subscription")
|
2024-11-03 08:37:01 -05:00
|
|
|
this.subscription = consumer.subscriptions.create("NotificationsChannel", {
|
|
|
|
|
connected: () => {
|
2024-11-07 07:30:58 -05:00
|
|
|
// console.log("[WebSocket] Connected to NotificationsChannel")
|
2024-11-03 08:37:01 -05:00
|
|
|
},
|
|
|
|
|
disconnected: () => {
|
2024-11-07 07:30:58 -05:00
|
|
|
// console.log("[WebSocket] Disconnected from NotificationsChannel")
|
2024-11-03 08:37:01 -05:00
|
|
|
},
|
|
|
|
|
received: (data) => {
|
2024-11-07 07:30:58 -05:00
|
|
|
// console.log("[WebSocket] Received notification:", data)
|
2024-11-03 09:21:29 -05:00
|
|
|
this.animateBadge()
|
2024-11-07 13:00:11 -05:00
|
|
|
this.prependNotification(data)
|
2024-11-03 08:37:01 -05:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-03 09:21:29 -05:00
|
|
|
animateBadge() {
|
|
|
|
|
let badge = this.hasBadgeTarget ? this.badgeTarget : null
|
2024-11-03 08:37:01 -05:00
|
|
|
|
2024-11-03 09:21:29 -05:00
|
|
|
if (!badge) {
|
|
|
|
|
badge = document.createElement("span")
|
|
|
|
|
badge.className = "badge badge-xs badge-primary absolute top-0 right-0"
|
|
|
|
|
badge.setAttribute("data-notifications-target", "badge")
|
|
|
|
|
this.element.querySelector('.btn').appendChild(badge)
|
|
|
|
|
}
|
2024-11-03 08:37:01 -05:00
|
|
|
|
2024-11-03 09:21:29 -05:00
|
|
|
// Create ping effect div if it doesn't exist
|
|
|
|
|
let pingEffect = badge.querySelector('.ping-effect')
|
|
|
|
|
if (!pingEffect) {
|
|
|
|
|
pingEffect = document.createElement("span")
|
|
|
|
|
pingEffect.className = "ping-effect absolute inline-flex h-full w-full rounded-full animate-ping bg-primary opacity-75"
|
|
|
|
|
badge.appendChild(pingEffect)
|
|
|
|
|
} else {
|
|
|
|
|
// Reset animation
|
|
|
|
|
pingEffect.remove()
|
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
|
badge.appendChild(pingEffect)
|
|
|
|
|
})
|
|
|
|
|
}
|
2024-11-03 08:37:01 -05:00
|
|
|
}
|
2024-11-07 13:00:11 -05:00
|
|
|
|
|
|
|
|
prependNotification(notification) {
|
|
|
|
|
const li = this.createNotificationListItem(notification)
|
|
|
|
|
const divider = this.listTarget.querySelector(".divider")
|
|
|
|
|
if (divider) {
|
|
|
|
|
divider.parentNode.insertBefore(li, divider.nextSibling)
|
|
|
|
|
} else {
|
|
|
|
|
this.listTarget.prepend(li)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update the badge count
|
|
|
|
|
this.updateBadge()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
createNotificationListItem(notification) {
|
|
|
|
|
const li = document.createElement("li")
|
|
|
|
|
li.innerHTML = `
|
|
|
|
|
<a href="/notifications/${notification.id}">
|
|
|
|
|
${notification.title}
|
|
|
|
|
<div class="badge badge-xs justify-self-end badge-${notification.kind}"></div>
|
|
|
|
|
</a>
|
|
|
|
|
`
|
|
|
|
|
return li
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateBadge() {
|
|
|
|
|
const badgeCount = this.listTarget.children.length
|
|
|
|
|
this.badgeTarget.textContent = badgeCount
|
|
|
|
|
this.badgeTarget.classList.toggle("hidden", badgeCount === 0)
|
|
|
|
|
}
|
2024-11-03 08:37:01 -05:00
|
|
|
}
|