feat: enhance message notification handling with improved navigation and notification logic
This commit is contained in:
@@ -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 roomPath = isDm
|
const navigateToRoom = () => {
|
||||||
? getDirectRoomPath(roomId, eventId)
|
if (!mx) return;
|
||||||
: getHomeRoomPath(roomId, eventId);
|
try {
|
||||||
|
const roomIdOrAlias = getCanonicalAliasOrRoomId(mx, roomId);
|
||||||
// Check if running in Electron
|
if (mDirects.has(roomId)) {
|
||||||
const isElectron = 'electron' in window;
|
navigate(getDirectRoomPath(roomIdOrAlias, eventId));
|
||||||
const hasElectronNotification = (window as any).electron?.notification?.show;
|
return;
|
||||||
|
}
|
||||||
console.log('Notification check:', {
|
const orphanParents = getOrphanParents(roomToParents, roomId);
|
||||||
isElectron,
|
if (orphanParents.length > 0) {
|
||||||
hasElectronNotification,
|
const parentSpace = guessPerfectParent(mx, roomId, orphanParents) ?? orphanParents[0];
|
||||||
isTauri: isTauri(),
|
const pSpaceIdOrAlias = getCanonicalAliasOrRoomId(mx, parentSpace);
|
||||||
username,
|
navigate(getSpaceRoomPath(pSpaceIdOrAlias, roomIdOrAlias, eventId));
|
||||||
messageBody
|
return;
|
||||||
});
|
}
|
||||||
|
navigate(getHomeRoomPath(roomIdOrAlias, eventId));
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[Notifications] Navigate error:', err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (isTauri()) {
|
if (isTauri()) {
|
||||||
|
const roomPath = isDm
|
||||||
|
? getDirectRoomPath(roomId, eventId)
|
||||||
|
: getHomeRoomPath(roomId, eventId);
|
||||||
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(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user