remove thread notification on read

This commit is contained in:
Ajay Bura 2026-10-24 12:16:38 +05:30
commit f979a994e0
4 changed files with 43 additions and 35 deletions

View file

@ -3,7 +3,7 @@ import { useCallback, useEffect } from 'react';
import { UnreadNotificationCounts } from 'neurone/lib/api/types';
import { useRoomsNotificationPreferencesContext } from '../../hooks/useRoomsNotificationPreferences';
import { ClientContext } from '../../../client/context';
import { AsyncStatus, useAsyncCallbackValue } from '../../hooks/useAsyncCallback';
import { useObservableValue } from '../../hooks/useObservableValue';
export type Notifications = UnreadNotificationCounts & {
threads: Map<string, UnreadNotificationCounts>;
@ -18,25 +18,10 @@ export const useBindRoomToNotificationsAtom = (
) => {
const setNotificationAtom = useSetAtom(notificationsAtom);
const roomsNotificationPreferences = useRoomsNotificationPreferencesContext();
const [unreadState] = useAsyncCallbackValue(
useCallback(async () => {
const notifications = await ct.storage.unreadNotifications.observableRead.getAll();
const threadNotifications =
await ct.storage.unreadThreadNotifications.observableRead.getAll();
return {
notifications,
threadNotifications,
};
}, [ct])
);
const unread = unreadState.status === AsyncStatus.Success ? unreadState.data : undefined;
const notifications = useObservableValue(ct.notifications);
const threadNotifications = useObservableValue(ct.threadNotifications);
const processNotifications = useCallback(() => {
const notifications = unread?.notifications.read ?? [];
const threadNotifications = unread?.threadNotifications.read ?? [];
const { mute } = roomsNotificationPreferences;
const roomToThreadsNotifications = new Map<string, Map<string, UnreadNotificationCounts>>();
@ -66,18 +51,9 @@ export const useBindRoomToNotificationsAtom = (
});
setNotificationAtom(roomToNotifications);
}, [unread, setNotificationAtom, roomsNotificationPreferences]);
}, [notifications, threadNotifications, setNotificationAtom, roomsNotificationPreferences]);
useEffect(() => {
if (unread) {
processNotifications();
}
const unsubscribeN = unread?.notifications.subscribe(() => processNotifications());
const unsubscribeTn = unread?.threadNotifications.subscribe(() => processNotifications());
return () => {
unsubscribeN?.();
unsubscribeTn?.();
};
}, [unread, processNotifications]);
processNotifications();
}, [processNotifications]);
};

View file

@ -21,6 +21,8 @@ import {
LeaveRoomStateObject,
ReadReceiptObject,
sessionValue,
UnreadNotificationsObject,
UnreadThreadNotificationsObject,
} from './storage/collections';
import { Storage } from './storage';
import { SyncContext, SyncValue } from './sync';
@ -122,6 +124,8 @@ export type ClientContext = {
roomToVersion: ObservableValue<Map<string, string>>;
roomToLatestEvent: ObservableValue<Map<string, MessageEventWithoutRoomId>>;
userReadReceipt: ObservableValue<ReadReceiptObject[]>;
notifications: ObservableValue<UnreadNotificationsObject[]>;
threadNotifications: ObservableValue<UnreadThreadNotificationsObject[]>;
roomToTimeline: ObservableValue<Map<string, Timeline>>;
pendingMemberRooms: ObservableValue<string[]>;
@ -864,6 +868,18 @@ export const createUserReceiptObservable = async (
return receiptObservable;
};
export const createNotificationsObservable = async (storage: Storage, disposer: Disposer) => {
const notifications = await storage.unreadNotifications.observableRead.getAll();
const threadNotifications = await storage.unreadThreadNotifications.observableRead.getAll();
disposer.collect(notifications, threadNotifications);
return {
notifications,
threadNotifications,
};
};
export const createLogoutObservable = (
syncObservable: ObservableValue<SyncValue>,
disposer: Disposer

View file

@ -27,6 +27,7 @@ import {
createBackupInfoObservable,
createUserReceiptObservable,
createToDeviceEventsObservable,
createNotificationsObservable,
} from './context';
import { createStorage } from './storage';
import { getAuthJSONRequest } from './request';
@ -82,6 +83,10 @@ export const initializeClient = async (session: Session): Promise<InitializeClie
const roomToReplacement = createRoomToReplacementObservable(state, disposer);
const roomToLatestEvent = await createRoomToLatestEventObservable(storage, disposer);
const userReadReceipt = await createUserReceiptObservable(session, storage, disposer);
const { notifications, threadNotifications } = await createNotificationsObservable(
storage,
disposer
);
const syncTokenObservable = await createSyncTokenObservable(storage, disposer);
const pendingMemberRooms = await createPendingMemberRoomObservable(storage, disposer);
@ -147,6 +152,8 @@ export const initializeClient = async (session: Session): Promise<InitializeClie
roomToReplacement,
roomToLatestEvent,
userReadReceipt,
notifications,
threadNotifications,
roomToCreators,
roomToVersion,
roomToTimeline,

View file

@ -366,17 +366,22 @@ export const writeUnreadThreadNotifications = async (
joinRooms: string[],
join: Record<string, JoinRoom>
): Promise<void> => {
const notificationsToRemove: UnreadThreadNotificationsObject[] = [];
const unreadThreadNotificationsObjects: UnreadThreadNotificationsObject[] = joinRooms.flatMap(
(roomId) => {
const joinRoom = join[roomId];
const unreadThreadNotifications = joinRoomUtil.roomUnreadThreadNotifications(joinRoom);
const unreadThreadNotifications = joinRoomUtil.roomUnreadThreadNotifications(joinRoom) ?? {};
if (!unreadThreadNotifications) {
return [];
}
const threadIds = Object.keys(unreadThreadNotifications);
return Object.keys(unreadThreadNotifications).map((threadId) => {
const toRemove = ct.threadNotifications.read.filter(
(n) => n.roomId === roomId && !threadIds.includes(n.threadId)
);
notificationsToRemove.push(...toRemove);
return threadIds.map((threadId) => {
const unread = unreadThreadNotifications[threadId];
const obj: UnreadThreadNotificationsObject = {
@ -391,6 +396,10 @@ export const writeUnreadThreadNotifications = async (
}
);
const toRemoveKeys = notificationsToRemove.map((n) =>
getUnreadThreadNotificationId(n.roomId, n.threadId)
);
await ct.storage.unreadThreadNotifications.write.deleteMultiple(toRemoveKeys);
await ct.storage.unreadThreadNotifications.write.putMultiple(unreadThreadNotificationsObjects);
};