fix(notifications): click navigates to specific message, not inbox
CI / Build & Quality Checks (push) Successful in 10m30s
CI / Trigger Desktop Build (push) Successful in 7s

OS notifications now show the real message body ("user: text" instead
of "New inbox notification from user"), clicking jumps directly to the
room at the triggering event, and window.focus() brings the tab to
front. Reminder toasts also link to the specific event via eventId.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-18 18:37:19 -04:00
parent 2b5c6fd606
commit f054abfbd2
2 changed files with 13 additions and 8 deletions
+3 -2
View File
@@ -299,11 +299,12 @@ Themes:
--- ---
### [ ] P5-20 · Quick Reply from Browser Notification ### [~] P5-20 · Quick Reply from Browser Notification
**What:** Inline reply field in browser notification toasts via Notification Actions API. Reply sends as threaded reply to the triggering message. **What:** Inline reply field in browser notification toasts via Notification Actions API. Reply sends as threaded reply to the triggering message.
**[AUDIT REQUIRED]** (1) Verify browser Notification Actions API support in target browsers. (2) Confirmed: service worker EXISTS at `src/sw.ts` — add `notificationclick` handler there. **[AUDIT REQUIRED]** (1) Verify browser Notification Actions API support in target browsers. (2) Confirmed: service worker EXISTS at `src/sw.ts` — add `notificationclick` handler there.
**Complexity:** Medium-High. **Complexity:** Medium-High.
**Partial Fix Applied ⚠️ UNTESTED:** Notifications now (a) show the real message body (`username: message` instead of "New inbox notification from..."), (b) click navigates directly to the room at the specific event (not the inbox), (c) `window.focus()` called on click so the tab comes to front, (d) reminder toasts also link to the specific event. Full inline-reply via Notification Actions API still needs the SW `push`+`notificationclick` pipeline (requires switching from `new Notification()` to `showNotification()` through the SW).
--- ---
+10 -6
View File
@@ -19,7 +19,6 @@ import {
getDirectRoomPath, getDirectRoomPath,
getHomeRoomPath, getHomeRoomPath,
getInboxInvitesPath, getInboxInvitesPath,
getInboxNotificationsPath,
} from '../pathUtils'; } from '../pathUtils';
import { mDirectAtom } from '../../state/mDirectList'; import { mDirectAtom } from '../../state/mDirectList';
import { import {
@@ -255,6 +254,10 @@ function MessageNotifications() {
eventId: string; eventId: string;
body?: string; body?: string;
}) => { }) => {
const roomPath = mDirects.has(roomId)
? getDirectRoomPath(roomId, eventId)
: getHomeRoomPath(roomId, eventId);
if (document.hasFocus()) { if (document.hasFocus()) {
setToast({ setToast({
id: `${roomId}-${eventId}-${Date.now()}`, id: `${roomId}-${eventId}-${Date.now()}`,
@@ -263,7 +266,7 @@ function MessageNotifications() {
body: (body ?? '').slice(0, 80), body: (body ?? '').slice(0, 80),
roomName, roomName,
roomId, roomId,
hashPath: mDirects.has(roomId) ? getDirectRoomPath(roomId) : getHomeRoomPath(roomId), hashPath: roomPath,
}); });
return; return;
} }
@@ -271,12 +274,13 @@ function MessageNotifications() {
const noti = new window.Notification(roomName, { const noti = new window.Notification(roomName, {
icon: roomAvatar, icon: roomAvatar,
badge: roomAvatar, badge: roomAvatar,
body: `New inbox notification from ${username}`, body: body ? `${username}: ${body}`.slice(0, 120) : username,
silent: true, silent: true,
}); });
noti.onclick = () => { noti.onclick = () => {
if (!window.closed) navigate(getInboxNotificationsPath()); window.focus();
navigate(roomPath);
noti.close(); noti.close();
notifRef.current = undefined; notifRef.current = undefined;
}; };
@@ -400,8 +404,8 @@ function ReminderMonitor() {
firedRef.current.add(key); firedRef.current.add(key);
const room = mx.getRoom(r.roomId); const room = mx.getRoom(r.roomId);
const hashPath = mDirects.has(r.roomId) const hashPath = mDirects.has(r.roomId)
? getDirectRoomPath(r.roomId) ? getDirectRoomPath(r.roomId, r.eventId)
: getHomeRoomPath(r.roomId); : getHomeRoomPath(r.roomId, r.eventId);
setToast({ setToast({
id: `reminder-${key}`, id: `reminder-${key}`,
displayName: 'Reminder', displayName: 'Reminder',