feat: enhance message notification handling with improved navigation and notification logic

This commit is contained in:
2026-02-27 22:45:14 +11:00
parent f8af51b75c
commit b400c4d6c3

View File

@@ -14,15 +14,19 @@ import { EmojiStyle, settingsAtom } from '../../state/settings';
import { allInvitesAtom } from '../../state/room-list/inviteList';
import { usePreviousValue } from '../../hooks/usePreviousValue';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { getDirectRoomPath, getHomeRoomPath, getInboxInvitesPath } from '../pathUtils';
import { getDirectRoomPath, getHomeRoomPath, getSpaceRoomPath, getInboxInvitesPath } from '../pathUtils';
import {
getMemberDisplayName,
getNotificationType,
getUnreadInfo,
isNotificationEvent,
getOrphanParents,
guessPerfectParent,
} from '../../utils/room';
import { NotificationType, UnreadInfo } from '../../../types/matrix/room';
import { getMxIdLocalPart, mxcUrlToHttp } from '../../utils/matrix';
import { getMxIdLocalPart, mxcUrlToHttp, getCanonicalAliasOrRoomId } from '../../utils/matrix';
import { mDirectAtom } from '../../state/mDirectList';
import { roomToParentsAtom } from '../../state/room/roomToParents';
import { useSelectedRoom } from '../../hooks/router/useSelectedRoom';
import { useInboxNotificationsSelected } from '../../hooks/router/useInbox';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
@@ -166,6 +170,8 @@ function MessageNotifications() {
const useAuthentication = useMediaAuthentication();
const [showNotifications] = useSetting(settingsAtom, 'showNotifications');
const [notificationSound] = useSetting(settingsAtom, 'isNotificationSounds');
const mDirects = useAtomValue(mDirectAtom);
const roomToParents = useAtomValue(roomToParentsAtom);
const navigate = useNavigate();
const notificationSelected = useInboxNotificationsSelected();
@@ -196,56 +202,47 @@ function MessageNotifications() {
eventId: string;
isDm: boolean;
}) => {
// In DMs, room name is the username, so don't duplicate it
const body = messageBody
? (isDm ? messageBody : `${username}: ${messageBody}`)
: `New message from ${username}`;
// Build the path to navigate to on click
const roomPath = isDm
? getDirectRoomPath(roomId, eventId)
: getHomeRoomPath(roomId, eventId);
// Check if running in Electron
const isElectron = 'electron' in window;
const hasElectronNotification = (window as any).electron?.notification?.show;
console.log('Notification check:', {
isElectron,
hasElectronNotification,
isTauri: isTauri(),
username,
messageBody
});
const notificationTitle = `${username} - Paarrot`;
const notificationBody = messageBody || 'New message';
/** Replicates TitleBar click navigation logic */
const navigateToRoom = () => {
if (!mx) return;
try {
const roomIdOrAlias = getCanonicalAliasOrRoomId(mx, roomId);
if (mDirects.has(roomId)) {
navigate(getDirectRoomPath(roomIdOrAlias, eventId));
return;
}
const orphanParents = getOrphanParents(roomToParents, roomId);
if (orphanParents.length > 0) {
const parentSpace = guessPerfectParent(mx, roomId, orphanParents) ?? orphanParents[0];
const pSpaceIdOrAlias = getCanonicalAliasOrRoomId(mx, parentSpace);
navigate(getSpaceRoomPath(pSpaceIdOrAlias, roomIdOrAlias, eventId));
return;
}
navigate(getHomeRoomPath(roomIdOrAlias, eventId));
} catch (err) {
console.error('[Notifications] Navigate error:', err);
}
};
if (isTauri()) {
const roomPath = isDm
? getDirectRoomPath(roomId, eventId)
: getHomeRoomPath(roomId, eventId);
sendNotification({
title: roomName,
body,
title: notificationTitle,
body: notificationBody,
path: roomPath,
onClick: () => {
if (!window.closed) navigate(roomPath);
},
});
} else if (isElectron && hasElectronNotification) {
// Use Electron desktop notifications
const notificationTitle = `${username} - Paarrot`;
const notificationBody = messageBody || 'New message';
console.log('Sending Electron notification:', { title: notificationTitle, body: notificationBody });
(window as any).electron.notification.show({
title: notificationTitle,
body: notificationBody,
icon: roomAvatar,
}).catch((err: any) => console.error('Electron notification error:', err));
} else {
// Fallback to web Notification API - also use custom format
const notificationTitle = `${username} - Paarrot`;
const notificationBody = messageBody || 'New message';
console.log('Sending web notification:', { title: notificationTitle, body: notificationBody });
// Use renderer window.Notification — works in both Electron and browser.
// Main-process Notification click events are unreliable on Windows without
// full COM/AUMID registration, so we keep everything in the renderer.
const noti = new window.Notification(notificationTitle, {
icon: roomAvatar,
badge: roomAvatar,
@@ -254,8 +251,9 @@ function MessageNotifications() {
});
noti.onclick = () => {
window.focus();
if (!window.closed) navigate(roomPath);
// Tell main process to bring window to front
(window as any).electron?.window?.focus();
if (!window.closed) navigateToRoom();
noti.close();
notifRef.current = undefined;
};
@@ -264,7 +262,7 @@ function MessageNotifications() {
notifRef.current = noti;
}
},
[mx, navigate]
[mx, navigate, mDirects, roomToParents]
);
const playSound = useCallback(() => {