Fix duplicate new-ticket notification (toast + desktop push both fired)
appendMessage() publishes ticket.created and message.created for the same first message of a new ticket. TicketToasts and DesktopNotifications listened to both independently, so one new customer ticket produced two toasts/two chimes/two OS notifications. message.created now carries ticketIsNew so both subscribers can skip it when ticket.created already covered the same event.
This commit is contained in:
1 parent
87cf045715
commit
b2534b7ce8
4 files changed
+16
-3
No files matched your search
@@ -25,7 +25,7 @@ export function DesktopNotifications({ currentUser }: { currentUser: { id: strin
|
||||
window.focus();
|
||||
router.push(`/tickets/${event.ticket.id}`);
|
||||
};
|
||||
} else if (event.type === "message.created" && event.message.authorType === "customer") {
|
||||
} else if (event.type === "message.created" && event.message.authorType === "customer" && !event.ticketIsNew) {
|
||||
if (!isTicketVisibleTo({ assigneeId: event.assigneeId }, currentUser)) return;
|
||||
const notification = new Notification(`Сообщение от ${event.message.authorName}`, {
|
||||
body: event.message.body.slice(0, 120),
|
||||
|
||||
@@ -92,7 +92,7 @@ export function TicketToasts({ currentUser }: { currentUser: { id: string; role:
|
||||
if (event.type === "ticket.created") {
|
||||
if (!isTicketVisibleTo(event.ticket, currentUser)) return;
|
||||
pushToast("Новая заявка", event.ticket.subject, `/tickets/${event.ticket.id}`);
|
||||
} else if (event.type === "message.created" && event.message.authorType === "customer") {
|
||||
} else if (event.type === "message.created" && event.message.authorType === "customer" && !event.ticketIsNew) {
|
||||
if (!isTicketVisibleTo({ assigneeId: event.assigneeId }, currentUser)) return;
|
||||
pushToast(`Сообщение от ${event.message.authorName}`, event.message.body.slice(0, 120), `/tickets/${event.ticketId}`);
|
||||
}
|
||||
|
||||
+13
-1
@@ -4,7 +4,19 @@ import type { TicketDTO, MessageDTO } from "@/lib/tickets/types";
|
||||
export type TicketEvent =
|
||||
| { type: "ticket.created"; ticket: TicketDTO }
|
||||
| { type: "ticket.updated"; ticket: TicketDTO }
|
||||
| { type: "message.created"; ticketId: string; customerId: string; assigneeId: string | null; message: MessageDTO };
|
||||
| {
|
||||
type: "message.created";
|
||||
ticketId: string;
|
||||
customerId: string;
|
||||
assigneeId: string | null;
|
||||
message: MessageDTO;
|
||||
// True when this message is the ticket's very first — subscribers that
|
||||
// already show a "new ticket" toast/notification off the sibling
|
||||
// ticket.created event (published for the same message, see
|
||||
// appendMessage in lib/tickets/service.ts) should skip this one too,
|
||||
// otherwise a single incoming ticket doubles up as two notifications.
|
||||
ticketIsNew: boolean;
|
||||
};
|
||||
|
||||
// Stashed on globalThis rather than relying on Node's module cache to give
|
||||
// us a singleton: Next.js dev mode reloads this module on every edit (hot
|
||||
|
||||
@@ -164,6 +164,7 @@ async function appendMessage(params: {
|
||||
customerId: ticket.customerId,
|
||||
assigneeId: dto.assigneeId,
|
||||
message: messageDto,
|
||||
ticketIsNew: params.ticketIsNew,
|
||||
});
|
||||
|
||||
// Fire-and-forget: push delivery is a best-effort side channel for
|
||||
|
||||
Reference in new issue
Block a user