From ac8eee48ec6e7944f7fa861df87921da85203d48 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Fri, 12 Nov 2021 18:45:45 +0300 Subject: [PATCH] Service Notifications: Fix marking as read --- src/components/middle/MessageList.tsx | 10 +++------ src/global/types.ts | 1 + src/modules/actions/api/messages.ts | 13 +++++++++-- src/modules/actions/ui/messages.ts | 5 +++-- src/modules/selectors/messages.ts | 31 +++++++++++++++++++++------ 5 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/components/middle/MessageList.tsx b/src/components/middle/MessageList.tsx index 70508df6f..50260192e 100644 --- a/src/components/middle/MessageList.tsx +++ b/src/components/middle/MessageList.tsx @@ -77,7 +77,6 @@ type StateProps = { isBot?: boolean; messageIds?: number[]; messagesById?: Record; - isUnread?: boolean; firstUnreadId?: number; isViewportNewest?: boolean; isRestricted?: boolean; @@ -125,7 +124,6 @@ const MessageList: FC = ({ messageIds, messagesById, firstUnreadId, - isUnread, isViewportNewest, threadFirstMessageId, isRestricted, @@ -174,12 +172,11 @@ const MessageList: FC = ({ }, [firstUnreadId]); // Updated only once when messages are loaded (as we want the unread divider to keep its position) - const withUnreadDivider = areMessagesLoaded && isUnread; useOnChange(() => { - if (withUnreadDivider) { + if (areMessagesLoaded) { memoUnreadDividerBeforeIdRef.current = memoFirstUnreadIdRef.current; } - }, [withUnreadDivider]); + }, [areMessagesLoaded]); useOnChange(() => { memoFocusingIdRef.current = focusingId; @@ -506,7 +503,7 @@ const MessageList: FC = ({ messageIds={messageIds || [lastMessage!.id]} messageGroups={messageGroups || groupMessages([lastMessage!])} isViewportNewest={Boolean(isViewportNewest)} - isUnread={Boolean(isUnread)} + isUnread={Boolean(firstUnreadId)} withUsers={withUsers} noAvatars={noAvatars} containerRef={containerRef} @@ -581,7 +578,6 @@ export default memo(withGlobal( isBot: Boolean(chatBot), messageIds, messagesById, - isUnread: Boolean(chat.unreadCount), firstUnreadId: selectFirstUnreadId(global, chatId, threadId), isViewportNewest: type !== 'thread' || selectIsViewportNewest(global, chatId, threadId), threadFirstMessageId: selectFirstMessageId(global, chatId, threadId), diff --git a/src/global/types.ts b/src/global/types.ts index 63cf4160d..e53ac1b86 100644 --- a/src/global/types.ts +++ b/src/global/types.ts @@ -76,6 +76,7 @@ export interface ServiceNotification { id: number; message: ApiMessage; version?: string; + isUnread?: boolean; } export type GlobalState = { diff --git a/src/modules/actions/api/messages.ts b/src/modules/actions/api/messages.ts index ff5922fe1..ce28216d5 100644 --- a/src/modules/actions/api/messages.ts +++ b/src/modules/actions/api/messages.ts @@ -485,15 +485,24 @@ addReducer('markMessageListRead', (global, actions, payload) => { return undefined; } + if (chatId === SERVICE_NOTIFICATIONS_USER_ID) { + global = { + ...global, + serviceNotifications: global.serviceNotifications.map((notification) => { + return notification.isUnread && notification.id <= maxId ? { ...notification, isUnread: false } : notification; + }), + }; + } + const viewportIds = selectViewportIds(global, chatId, threadId); const minId = selectFirstUnreadId(global, chatId, threadId); if (!viewportIds || !minId || !chat.unreadCount) { - return undefined; + return global; } const readCount = countSortedIds(viewportIds!, minId, maxId); if (!readCount) { - return undefined; + return global; } return updateChat(global, chatId, { diff --git a/src/modules/actions/ui/messages.ts b/src/modules/actions/ui/messages.ts index 4237349b9..6443190c1 100644 --- a/src/modules/actions/ui/messages.ts +++ b/src/modules/actions/ui/messages.ts @@ -43,7 +43,7 @@ import parseMessageInput from '../../../util/parseMessageInput'; const FOCUS_DURATION = 1500; const FOCUS_NO_HIGHLIGHT_DURATION = FAST_SMOOTH_MAX_DURATION + ANIMATION_END_DELAY; const POLL_RESULT_OPEN_DELAY_MS = 450; -const SERVICE_NOTIFICATIONS_MAX_AMOUNT = 1e4; +const SERVICE_NOTIFICATIONS_MAX_AMOUNT = 1e3; let blurTimeout: number | undefined; @@ -609,12 +609,13 @@ addReducer('createServiceNotification', (global, actions, payload) => { id, message, version, + isUnread: true, }; setGlobal({ ...global, serviceNotifications: [ - ...serviceNotifications, + ...serviceNotifications.slice(-SERVICE_NOTIFICATIONS_MAX_AMOUNT), serviceNotification, ], }); diff --git a/src/modules/selectors/messages.ts b/src/modules/selectors/messages.ts index ada9b965f..0ab797230 100644 --- a/src/modules/selectors/messages.ts +++ b/src/modules/selectors/messages.ts @@ -7,7 +7,7 @@ import { MAIN_THREAD_ID, } from '../../api/types'; -import { LOCAL_MESSAGE_ID_BASE } from '../../config'; +import { LOCAL_MESSAGE_ID_BASE, SERVICE_NOTIFICATIONS_USER_ID } from '../../config'; import { selectChat, selectIsChatWithBot, selectIsChatWithSelf, } from './chats'; @@ -583,19 +583,36 @@ export function selectFirstUnreadId(global: GlobalState, chatId: string, threadI return undefined; } - if (outlyingIds) { - const found = !lastReadId ? outlyingIds[0] : outlyingIds.find((id) => { - return id > lastReadId && byId[id] && (!byId[id].isOutgoing || byId[id].isFromScheduled); + const lastReadServiceNotificationId = chatId === SERVICE_NOTIFICATIONS_USER_ID + ? global.serviceNotifications.reduce((max, notification) => { + return !notification.isUnread && notification.id > max ? notification.id : max; + }, -1) + : -1; + + function findAfterLastReadId(listIds: number[]) { + if (!lastReadId) { + return listIds[0]; + } + + return listIds.find((id) => { + return ( + id > lastReadId + && byId[id] + && (!byId[id].isOutgoing || byId[id].isFromScheduled) + && id > lastReadServiceNotificationId + ); }); + } + + if (outlyingIds) { + const found = findAfterLastReadId(outlyingIds); if (found) { return found; } } if (listedIds) { - const found = !lastReadId ? listedIds[0] : listedIds.find((id) => { - return id > lastReadId && byId[id] && (!byId[id].isOutgoing || byId[id].isFromScheduled); - }); + const found = findAfterLastReadId(listedIds); if (found) { return found; }