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