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();
|
window.focus();
|
||||||
router.push(`/tickets/${event.ticket.id}`);
|
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;
|
if (!isTicketVisibleTo({ assigneeId: event.assigneeId }, currentUser)) return;
|
||||||
const notification = new Notification(`Сообщение от ${event.message.authorName}`, {
|
const notification = new Notification(`Сообщение от ${event.message.authorName}`, {
|
||||||
body: event.message.body.slice(0, 120),
|
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 (event.type === "ticket.created") {
|
||||||
if (!isTicketVisibleTo(event.ticket, currentUser)) return;
|
if (!isTicketVisibleTo(event.ticket, currentUser)) return;
|
||||||
pushToast("Новая заявка", event.ticket.subject, `/tickets/${event.ticket.id}`);
|
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;
|
if (!isTicketVisibleTo({ assigneeId: event.assigneeId }, currentUser)) return;
|
||||||
pushToast(`Сообщение от ${event.message.authorName}`, event.message.body.slice(0, 120), `/tickets/${event.ticketId}`);
|
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 =
|
export type TicketEvent =
|
||||||
| { type: "ticket.created"; ticket: TicketDTO }
|
| { type: "ticket.created"; ticket: TicketDTO }
|
||||||
| { type: "ticket.updated"; 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
|
// 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
|
// 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,
|
customerId: ticket.customerId,
|
||||||
assigneeId: dto.assigneeId,
|
assigneeId: dto.assigneeId,
|
||||||
message: messageDto,
|
message: messageDto,
|
||||||
|
ticketIsNew: params.ticketIsNew,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fire-and-forget: push delivery is a best-effort side channel for
|
// Fire-and-forget: push delivery is a best-effort side channel for
|
||||||
|
|||||||
Reference in new issue
Block a user