From b023d20aeaee88cb3e8f626aa41f233437a922c6 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 5 Dec 2023 11:32:40 +0400 Subject: [PATCH 1/8] add logic which clears inbox when it is in unread state --- src/pages/inbox/BaseInbox.tsx | 4 ++++ src/store/states/inbox/actions.ts | 4 +++- src/store/states/inbox/reducer.ts | 8 +++++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/pages/inbox/BaseInbox.tsx b/src/pages/inbox/BaseInbox.tsx index c0b82a4d29..93ff955a35 100644 --- a/src/pages/inbox/BaseInbox.tsx +++ b/src/pages/inbox/BaseInbox.tsx @@ -233,6 +233,10 @@ const InboxPage: FC = (props) => { useEffect(() => { fetchData(); + + return () => { + dispatch(inboxActions.resetInbox({ onlyIfUnread: true })); + }; }, [userId]); useEffect(() => { diff --git a/src/store/states/inbox/actions.ts b/src/store/states/inbox/actions.ts index 360ec377ed..d62a64992d 100644 --- a/src/store/states/inbox/actions.ts +++ b/src/store/states/inbox/actions.ts @@ -4,7 +4,9 @@ import { ChatChannel, CommonFeed } from "@/shared/models"; import { InboxActionType } from "./constants"; import { InboxItems } from "./types"; -export const resetInbox = createStandardAction(InboxActionType.RESET_INBOX)(); +export const resetInbox = createStandardAction(InboxActionType.RESET_INBOX)<{ + onlyIfUnread?: boolean; +} | void>(); export const getInboxItems = createAsyncAction( InboxActionType.GET_INBOX_ITEMS, diff --git a/src/store/states/inbox/reducer.ts b/src/store/states/inbox/reducer.ts index 08a1e165d1..c6d488bebb 100644 --- a/src/store/states/inbox/reducer.ts +++ b/src/store/states/inbox/reducer.ts @@ -413,7 +413,13 @@ const updateChatChannelItem = ( }; export const reducer = createReducer(INITIAL_INBOX_STATE) - .handleAction(actions.resetInbox, () => ({ ...INITIAL_INBOX_STATE })) + .handleAction(actions.resetInbox, (state, { payload }) => { + if (payload?.onlyIfUnread && !state.items.unread) { + return state; + } + + return { ...INITIAL_INBOX_STATE }; + }) .handleAction(actions.getInboxItems.request, (state) => produce(state, (nextState) => { nextState.items = { From 4c13f6abb4392ea560f1582b01b98accd2908204 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 5 Dec 2023 12:17:59 +0400 Subject: [PATCH 2/8] create logic to refresh unread inbox items list --- src/store/states/inbox/actions.ts | 7 ++ src/store/states/inbox/constants.ts | 5 + src/store/states/inbox/saga/index.ts | 6 ++ .../inbox/saga/refreshUnreadInboxItems.ts | 96 +++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 src/store/states/inbox/saga/refreshUnreadInboxItems.ts diff --git a/src/store/states/inbox/actions.ts b/src/store/states/inbox/actions.ts index d62a64992d..297e424736 100644 --- a/src/store/states/inbox/actions.ts +++ b/src/store/states/inbox/actions.ts @@ -23,6 +23,13 @@ export const getInboxItems = createAsyncAction( string >(); +export const refreshUnreadInboxItems = createAsyncAction( + InboxActionType.REFRESH_UNREAD_INBOX_ITEMS, + InboxActionType.REFRESH_UNREAD_INBOX_ITEMS_SUCCESS, + InboxActionType.REFRESH_UNREAD_INBOX_ITEMS_FAILURE, + InboxActionType.REFRESH_UNREAD_INBOX_ITEMS_CANCEL, +)<{ newItemsAmount: number }, void, void, string>(); + export const addNewInboxItems = createStandardAction( InboxActionType.ADD_NEW_INBOX_ITEMS, )< diff --git a/src/store/states/inbox/constants.ts b/src/store/states/inbox/constants.ts index 9a7b410e4c..bc42bc1710 100644 --- a/src/store/states/inbox/constants.ts +++ b/src/store/states/inbox/constants.ts @@ -6,6 +6,11 @@ export enum InboxActionType { GET_INBOX_ITEMS_FAILURE = "@INBOX/GET_INBOX_ITEMS_FAILURE", GET_INBOX_ITEMS_CANCEL = "@INBOX/GET_INBOX_ITEMS_CANCEL", + REFRESH_UNREAD_INBOX_ITEMS = "@INBOX/REFRESH_UNREAD_INBOX_ITEMS", + REFRESH_UNREAD_INBOX_ITEMS_SUCCESS = "@INBOX/REFRESH_UNREAD_INBOX_ITEMS_SUCCESS", + REFRESH_UNREAD_INBOX_ITEMS_FAILURE = "@INBOX/REFRESH_UNREAD_INBOX_ITEMS_FAILURE", + REFRESH_UNREAD_INBOX_ITEMS_CANCEL = "@INBOX/REFRESH_UNREAD_INBOX_ITEMS_CANCEL", + ADD_NEW_INBOX_ITEMS = "@INBOX/ADD_NEW_INBOX_ITEMS", UPDATE_INBOX_ITEM = "@INBOX/UPDATE_INBOX_ITEM", diff --git a/src/store/states/inbox/saga/index.ts b/src/store/states/inbox/saga/index.ts index f040cb9624..b71cbe048b 100644 --- a/src/store/states/inbox/saga/index.ts +++ b/src/store/states/inbox/saga/index.ts @@ -1,6 +1,7 @@ import { takeLatestWithCancel } from "@/shared/utils/saga"; import * as actions from "../actions"; import { getInboxItems } from "./getInboxItems"; +import { refreshUnreadInboxItems } from "./refreshUnreadInboxItems"; export function* mainSaga() { yield takeLatestWithCancel( @@ -8,4 +9,9 @@ export function* mainSaga() { actions.getInboxItems.cancel, getInboxItems, ); + yield takeLatestWithCancel( + actions.refreshUnreadInboxItems.request, + actions.refreshUnreadInboxItems.cancel, + refreshUnreadInboxItems, + ); } diff --git a/src/store/states/inbox/saga/refreshUnreadInboxItems.ts b/src/store/states/inbox/saga/refreshUnreadInboxItems.ts new file mode 100644 index 0000000000..7fff295390 --- /dev/null +++ b/src/store/states/inbox/saga/refreshUnreadInboxItems.ts @@ -0,0 +1,96 @@ +import { call, put, select } from "redux-saga/effects"; +import { Logger, UserService } from "@/services"; +import { InboxItemType } from "@/shared/constants"; +import { + Awaited, + ChatChannelLayoutItem, + FeedItemFollowLayoutItemWithFollowData, + FeedLayoutItemWithFollowData, +} from "@/shared/interfaces"; +import { Timestamp } from "@/shared/models"; +import * as actions from "../actions"; +import { selectInboxItems } from "../selectors"; +import { InboxItems } from "../types"; + +export function* refreshUnreadInboxItems( + action: ReturnType, +) { + const { + payload: { newItemsAmount }, + } = action; + + try { + const currentItems = (yield select(selectInboxItems)) as InboxItems; + const newItemsAmountToFetch = + newItemsAmount - (currentItems.data?.length || 0); + + if (newItemsAmountToFetch <= 0) { + return; + } + + const newInboxItems: FeedLayoutItemWithFollowData[] = []; + let startAfter: Timestamp | null = null; + let keepItemsFetching = true; + + while (keepItemsFetching) { + const { data, lastDocTimestamp, hasMore } = (yield call( + UserService.getInboxItems, + { + startAfter, + limit: 5, + unread: true, + }, + )) as Awaited>; + const chatChannelItems = data.chatChannels + .filter( + (chatChannel) => + chatChannel.messageCount > 0 && + (!currentItems.data || + currentItems.data.every( + (item) => item.itemId !== chatChannel.id, + )), + ) + .map((chatChannel) => ({ + type: InboxItemType.ChatChannel, + itemId: chatChannel.id, + chatChannel, + })); + const feedItemFollowItems = data.feedItemFollows + .filter( + (feedItemFollow) => + !currentItems.data || + currentItems.data.every( + (item) => item.itemId !== feedItemFollow.id, + ), + ) + .map( + (feedItemFollowWithMetadata) => ({ + type: InboxItemType.FeedItemFollow, + itemId: feedItemFollowWithMetadata.feedItemId, + feedItem: feedItemFollowWithMetadata.feedItem, + feedItemFollowWithMetadata: feedItemFollowWithMetadata, + }), + ); + newInboxItems.push(...chatChannelItems, ...feedItemFollowItems); + keepItemsFetching = + newInboxItems.length < newItemsAmountToFetch && hasMore; + startAfter = lastDocTimestamp; + } + + if (newInboxItems.length > 0) { + yield put( + actions.addNewInboxItems( + newInboxItems.map((item) => ({ + item, + statuses: { + isAdded: false, + isRemoved: false, + }, + })), + ), + ); + } + } catch (err) { + Logger.error(err); + } +} From 2712129b7a969226edcdcc76df2b7af0cd925b2e Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 5 Dec 2023 12:24:26 +0400 Subject: [PATCH 3/8] create converter for feed item follow with metadata to layout item --- ...llowToLayoutItemWithFollowDataConverter.ts | 25 +++++++++++++++++++ src/shared/converters/index.ts | 1 + src/store/states/inbox/saga/getInboxItems.ts | 14 +++-------- .../inbox/saga/refreshUnreadInboxItems.ts | 13 ++++------ 4 files changed, 35 insertions(+), 18 deletions(-) create mode 100644 src/shared/converters/FeedItemFollowToLayoutItemWithFollowDataConverter.ts diff --git a/src/shared/converters/FeedItemFollowToLayoutItemWithFollowDataConverter.ts b/src/shared/converters/FeedItemFollowToLayoutItemWithFollowDataConverter.ts new file mode 100644 index 0000000000..2e8cbeb739 --- /dev/null +++ b/src/shared/converters/FeedItemFollowToLayoutItemWithFollowDataConverter.ts @@ -0,0 +1,25 @@ +import { InboxItemType } from "@/shared/constants"; +import { FeedItemFollowLayoutItemWithFollowData } from "@/shared/interfaces"; +import { FeedItemFollowWithMetadata } from "@/shared/models"; +import { Converter } from "./Converter"; + +class FeedItemFollowToLayoutItemWithFollowDataConverter extends Converter< + FeedItemFollowWithMetadata, + FeedItemFollowLayoutItemWithFollowData +> { + public toTargetEntity = ( + feedItemFollowWithMetadata: FeedItemFollowWithMetadata, + ): FeedItemFollowLayoutItemWithFollowData => ({ + type: InboxItemType.FeedItemFollow, + itemId: feedItemFollowWithMetadata.feedItemId, + feedItem: feedItemFollowWithMetadata.feedItem, + feedItemFollowWithMetadata: feedItemFollowWithMetadata, + }); + + public toBaseEntity = ( + feedItemFollowLayoutItemWithFollowData: FeedItemFollowLayoutItemWithFollowData, + ): FeedItemFollowWithMetadata => + feedItemFollowLayoutItemWithFollowData.feedItemFollowWithMetadata; +} + +export default new FeedItemFollowToLayoutItemWithFollowDataConverter(); diff --git a/src/shared/converters/index.ts b/src/shared/converters/index.ts index 0853aa9193..b3bc301375 100644 --- a/src/shared/converters/index.ts +++ b/src/shared/converters/index.ts @@ -1,2 +1,3 @@ export { default as ChatChannelToDiscussionConverter } from "./ChatChannelToDiscussionConverter"; export { default as ChatMessageToUserDiscussionMessageConverter } from "./ChatMessageToUserDiscussionMessageConverter"; +export { default as FeedItemFollowToLayoutItemWithFollowDataConverter } from "./FeedItemFollowToLayoutItemWithFollowDataConverter"; diff --git a/src/store/states/inbox/saga/getInboxItems.ts b/src/store/states/inbox/saga/getInboxItems.ts index 5d7c94b8b1..8f8d6f5b23 100644 --- a/src/store/states/inbox/saga/getInboxItems.ts +++ b/src/store/states/inbox/saga/getInboxItems.ts @@ -1,10 +1,10 @@ import { call, put, select } from "redux-saga/effects"; import { UserService } from "@/services"; import { InboxItemType } from "@/shared/constants"; +import { FeedItemFollowToLayoutItemWithFollowDataConverter } from "@/shared/converters"; import { Awaited, ChatChannelLayoutItem, - FeedItemFollowLayoutItemWithFollowData, FeedLayoutItemWithFollowData, } from "@/shared/interfaces"; import { isError } from "@/shared/utils"; @@ -50,15 +50,9 @@ export function* getInboxItems( chatChannel, })) .filter((item) => item.chatChannel.messageCount > 0); - const feedItemFollowItems = - data.feedItemFollows.map( - (feedItemFollowWithMetadata) => ({ - type: InboxItemType.FeedItemFollow, - itemId: feedItemFollowWithMetadata.feedItemId, - feedItem: feedItemFollowWithMetadata.feedItem, - feedItemFollowWithMetadata: feedItemFollowWithMetadata, - }), - ); + const feedItemFollowItems = data.feedItemFollows.map((item) => + FeedItemFollowToLayoutItemWithFollowDataConverter.toTargetEntity(item), + ); const convertedData = sortItems([ ...chatChannelItems, ...feedItemFollowItems, diff --git a/src/store/states/inbox/saga/refreshUnreadInboxItems.ts b/src/store/states/inbox/saga/refreshUnreadInboxItems.ts index 7fff295390..48fa1c3b9d 100644 --- a/src/store/states/inbox/saga/refreshUnreadInboxItems.ts +++ b/src/store/states/inbox/saga/refreshUnreadInboxItems.ts @@ -1,10 +1,10 @@ import { call, put, select } from "redux-saga/effects"; import { Logger, UserService } from "@/services"; import { InboxItemType } from "@/shared/constants"; +import { FeedItemFollowToLayoutItemWithFollowDataConverter } from "@/shared/converters"; import { Awaited, ChatChannelLayoutItem, - FeedItemFollowLayoutItemWithFollowData, FeedLayoutItemWithFollowData, } from "@/shared/interfaces"; import { Timestamp } from "@/shared/models"; @@ -63,13 +63,10 @@ export function* refreshUnreadInboxItems( (item) => item.itemId !== feedItemFollow.id, ), ) - .map( - (feedItemFollowWithMetadata) => ({ - type: InboxItemType.FeedItemFollow, - itemId: feedItemFollowWithMetadata.feedItemId, - feedItem: feedItemFollowWithMetadata.feedItem, - feedItemFollowWithMetadata: feedItemFollowWithMetadata, - }), + .map((item) => + FeedItemFollowToLayoutItemWithFollowDataConverter.toTargetEntity( + item, + ), ); newInboxItems.push(...chatChannelItems, ...feedItemFollowItems); keepItemsFetching = From a574facd97c639ddb934dd6fb8dc3f61988d9ea4 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 5 Dec 2023 12:27:02 +0400 Subject: [PATCH 4/8] create converter for chat channel to layout item --- .../ChatChannelToLayoutItemConverter.ts | 23 +++++++++++++++++++ src/shared/converters/index.ts | 1 + src/store/states/inbox/saga/getInboxItems.ts | 16 ++++--------- .../inbox/saga/refreshUnreadInboxItems.ts | 16 ++++--------- 4 files changed, 34 insertions(+), 22 deletions(-) create mode 100644 src/shared/converters/ChatChannelToLayoutItemConverter.ts diff --git a/src/shared/converters/ChatChannelToLayoutItemConverter.ts b/src/shared/converters/ChatChannelToLayoutItemConverter.ts new file mode 100644 index 0000000000..5299541b79 --- /dev/null +++ b/src/shared/converters/ChatChannelToLayoutItemConverter.ts @@ -0,0 +1,23 @@ +import { InboxItemType } from "@/shared/constants"; +import { ChatChannelLayoutItem } from "@/shared/interfaces"; +import { ChatChannel } from "@/shared/models"; +import { Converter } from "./Converter"; + +class ChatChannelToLayoutItemConverter extends Converter< + ChatChannel, + ChatChannelLayoutItem +> { + public toTargetEntity = ( + chatChannel: ChatChannel, + ): ChatChannelLayoutItem => ({ + type: InboxItemType.ChatChannel, + itemId: chatChannel.id, + chatChannel, + }); + + public toBaseEntity = ( + chatChannelLayoutItem: ChatChannelLayoutItem, + ): ChatChannel => chatChannelLayoutItem.chatChannel; +} + +export default new ChatChannelToLayoutItemConverter(); diff --git a/src/shared/converters/index.ts b/src/shared/converters/index.ts index b3bc301375..033587d03e 100644 --- a/src/shared/converters/index.ts +++ b/src/shared/converters/index.ts @@ -1,3 +1,4 @@ export { default as ChatChannelToDiscussionConverter } from "./ChatChannelToDiscussionConverter"; +export { default as ChatChannelToLayoutItemConverter } from "./ChatChannelToLayoutItemConverter"; export { default as ChatMessageToUserDiscussionMessageConverter } from "./ChatMessageToUserDiscussionMessageConverter"; export { default as FeedItemFollowToLayoutItemWithFollowDataConverter } from "./FeedItemFollowToLayoutItemWithFollowDataConverter"; diff --git a/src/store/states/inbox/saga/getInboxItems.ts b/src/store/states/inbox/saga/getInboxItems.ts index 8f8d6f5b23..d69503832f 100644 --- a/src/store/states/inbox/saga/getInboxItems.ts +++ b/src/store/states/inbox/saga/getInboxItems.ts @@ -1,12 +1,10 @@ import { call, put, select } from "redux-saga/effects"; import { UserService } from "@/services"; -import { InboxItemType } from "@/shared/constants"; -import { FeedItemFollowToLayoutItemWithFollowDataConverter } from "@/shared/converters"; import { - Awaited, - ChatChannelLayoutItem, - FeedLayoutItemWithFollowData, -} from "@/shared/interfaces"; + ChatChannelToLayoutItemConverter, + FeedItemFollowToLayoutItemWithFollowDataConverter, +} from "@/shared/converters"; +import { Awaited, FeedLayoutItemWithFollowData } from "@/shared/interfaces"; import { isError } from "@/shared/utils"; import * as actions from "../actions"; import { selectInboxItems } from "../selectors"; @@ -44,11 +42,7 @@ export function* getInboxItems( }, )) as Awaited>; const chatChannelItems = data.chatChannels - .map((chatChannel) => ({ - type: InboxItemType.ChatChannel, - itemId: chatChannel.id, - chatChannel, - })) + .map((item) => ChatChannelToLayoutItemConverter.toTargetEntity(item)) .filter((item) => item.chatChannel.messageCount > 0); const feedItemFollowItems = data.feedItemFollows.map((item) => FeedItemFollowToLayoutItemWithFollowDataConverter.toTargetEntity(item), diff --git a/src/store/states/inbox/saga/refreshUnreadInboxItems.ts b/src/store/states/inbox/saga/refreshUnreadInboxItems.ts index 48fa1c3b9d..5c890047cc 100644 --- a/src/store/states/inbox/saga/refreshUnreadInboxItems.ts +++ b/src/store/states/inbox/saga/refreshUnreadInboxItems.ts @@ -1,12 +1,10 @@ import { call, put, select } from "redux-saga/effects"; import { Logger, UserService } from "@/services"; -import { InboxItemType } from "@/shared/constants"; -import { FeedItemFollowToLayoutItemWithFollowDataConverter } from "@/shared/converters"; import { - Awaited, - ChatChannelLayoutItem, - FeedLayoutItemWithFollowData, -} from "@/shared/interfaces"; + ChatChannelToLayoutItemConverter, + FeedItemFollowToLayoutItemWithFollowDataConverter, +} from "@/shared/converters"; +import { Awaited, FeedLayoutItemWithFollowData } from "@/shared/interfaces"; import { Timestamp } from "@/shared/models"; import * as actions from "../actions"; import { selectInboxItems } from "../selectors"; @@ -50,11 +48,7 @@ export function* refreshUnreadInboxItems( (item) => item.itemId !== chatChannel.id, )), ) - .map((chatChannel) => ({ - type: InboxItemType.ChatChannel, - itemId: chatChannel.id, - chatChannel, - })); + .map((item) => ChatChannelToLayoutItemConverter.toTargetEntity(item)); const feedItemFollowItems = data.feedItemFollows .filter( (feedItemFollow) => From e15c33472bf20747f827b60ab46e73c68821c346 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 5 Dec 2023 12:28:28 +0400 Subject: [PATCH 5/8] add logic to refresh unread inbox items to hook --- src/shared/hooks/useCases/useInboxItems.ts | 2 ++ .../hooks/useCases/useUnreadInboxItems.ts | 29 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/shared/hooks/useCases/useUnreadInboxItems.ts diff --git a/src/shared/hooks/useCases/useInboxItems.ts b/src/shared/hooks/useCases/useInboxItems.ts index e52ed2c95a..91aee3b7a3 100644 --- a/src/shared/hooks/useCases/useInboxItems.ts +++ b/src/shared/hooks/useCases/useInboxItems.ts @@ -18,6 +18,7 @@ import { FeedItemFollowWithMetadata, } from "@/shared/models"; import { inboxActions, InboxItems, selectInboxItems } from "@/store/states"; +import { useUnreadInboxItems } from "./useUnreadInboxItems"; interface Return extends Pick { @@ -128,6 +129,7 @@ export const useInboxItems = ( const userId = user?.uid; const unread = options?.unread; const lastBatch = newItemsBatches[0]; + useUnreadInboxItems(options?.unread); const fetch = () => { dispatch( diff --git a/src/shared/hooks/useCases/useUnreadInboxItems.ts b/src/shared/hooks/useCases/useUnreadInboxItems.ts new file mode 100644 index 0000000000..df59936d0e --- /dev/null +++ b/src/shared/hooks/useCases/useUnreadInboxItems.ts @@ -0,0 +1,29 @@ +import { useDispatch, useSelector } from "react-redux"; +import { usePreviousDistinct, useUpdateEffect } from "react-use"; +import { selectUserStreamsWithNotificationsAmount } from "@/pages/Auth/store/selectors"; +import { inboxActions } from "@/store/states"; + +export const useUnreadInboxItems = (unread?: boolean): void => { + const dispatch = useDispatch(); + const notificationsAmount = useSelector( + selectUserStreamsWithNotificationsAmount(), + ); + const previousNotificationsAmount = usePreviousDistinct(notificationsAmount); + + useUpdateEffect(() => { + if ( + !unread || + !notificationsAmount || + (typeof previousNotificationsAmount === "number" && + notificationsAmount < previousNotificationsAmount) + ) { + return; + } + + dispatch( + inboxActions.refreshUnreadInboxItems.request({ + newItemsAmount: notificationsAmount, + }), + ); + }, [notificationsAmount]); +}; From 0c736f438dc94111c4af9895493b7f525cbb2796 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 5 Dec 2023 13:59:07 +0400 Subject: [PATCH 6/8] fix stopping of the new unread items fetch --- .../hooks/useCases/useUnreadInboxItems.ts | 6 +--- src/store/states/inbox/actions.ts | 2 +- .../inbox/saga/refreshUnreadInboxItems.ts | 31 ++++++++++--------- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/shared/hooks/useCases/useUnreadInboxItems.ts b/src/shared/hooks/useCases/useUnreadInboxItems.ts index df59936d0e..10d5eed1f9 100644 --- a/src/shared/hooks/useCases/useUnreadInboxItems.ts +++ b/src/shared/hooks/useCases/useUnreadInboxItems.ts @@ -20,10 +20,6 @@ export const useUnreadInboxItems = (unread?: boolean): void => { return; } - dispatch( - inboxActions.refreshUnreadInboxItems.request({ - newItemsAmount: notificationsAmount, - }), - ); + dispatch(inboxActions.refreshUnreadInboxItems.request()); }, [notificationsAmount]); }; diff --git a/src/store/states/inbox/actions.ts b/src/store/states/inbox/actions.ts index 297e424736..aad2217412 100644 --- a/src/store/states/inbox/actions.ts +++ b/src/store/states/inbox/actions.ts @@ -28,7 +28,7 @@ export const refreshUnreadInboxItems = createAsyncAction( InboxActionType.REFRESH_UNREAD_INBOX_ITEMS_SUCCESS, InboxActionType.REFRESH_UNREAD_INBOX_ITEMS_FAILURE, InboxActionType.REFRESH_UNREAD_INBOX_ITEMS_CANCEL, -)<{ newItemsAmount: number }, void, void, string>(); +)(); export const addNewInboxItems = createStandardAction( InboxActionType.ADD_NEW_INBOX_ITEMS, diff --git a/src/store/states/inbox/saga/refreshUnreadInboxItems.ts b/src/store/states/inbox/saga/refreshUnreadInboxItems.ts index 5c890047cc..1dd2e32228 100644 --- a/src/store/states/inbox/saga/refreshUnreadInboxItems.ts +++ b/src/store/states/inbox/saga/refreshUnreadInboxItems.ts @@ -10,22 +10,24 @@ import * as actions from "../actions"; import { selectInboxItems } from "../selectors"; import { InboxItems } from "../types"; -export function* refreshUnreadInboxItems( - action: ReturnType, -) { - const { - payload: { newItemsAmount }, - } = action; +const checkCanKeepFetchingByDate = ( + firstDocTimestamp: Timestamp | null, + lastDocTimestamp: Timestamp | null, +): boolean => { + if (!firstDocTimestamp) { + return true; + } + if (!lastDocTimestamp) { + return false; + } + + return lastDocTimestamp.seconds >= firstDocTimestamp.seconds; +}; +export function* refreshUnreadInboxItems() { try { const currentItems = (yield select(selectInboxItems)) as InboxItems; - const newItemsAmountToFetch = - newItemsAmount - (currentItems.data?.length || 0); - - if (newItemsAmountToFetch <= 0) { - return; - } - + const { firstDocTimestamp } = currentItems; const newInboxItems: FeedLayoutItemWithFollowData[] = []; let startAfter: Timestamp | null = null; let keepItemsFetching = true; @@ -64,7 +66,8 @@ export function* refreshUnreadInboxItems( ); newInboxItems.push(...chatChannelItems, ...feedItemFollowItems); keepItemsFetching = - newInboxItems.length < newItemsAmountToFetch && hasMore; + hasMore && + checkCanKeepFetchingByDate(firstDocTimestamp, lastDocTimestamp); startAfter = lastDocTimestamp; } From 3fd41f62c22ae43f85451a0dee97a60ed3d22cc7 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 5 Dec 2023 14:25:20 +0400 Subject: [PATCH 7/8] add cancel of unread inbox items refresh on unmount --- src/shared/hooks/useCases/useUnreadInboxItems.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/shared/hooks/useCases/useUnreadInboxItems.ts b/src/shared/hooks/useCases/useUnreadInboxItems.ts index 10d5eed1f9..6b3ae8f6c0 100644 --- a/src/shared/hooks/useCases/useUnreadInboxItems.ts +++ b/src/shared/hooks/useCases/useUnreadInboxItems.ts @@ -1,3 +1,4 @@ +import { useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; import { usePreviousDistinct, useUpdateEffect } from "react-use"; import { selectUserStreamsWithNotificationsAmount } from "@/pages/Auth/store/selectors"; @@ -22,4 +23,14 @@ export const useUnreadInboxItems = (unread?: boolean): void => { dispatch(inboxActions.refreshUnreadInboxItems.request()); }, [notificationsAmount]); + + useEffect(() => { + return () => { + dispatch( + inboxActions.refreshUnreadInboxItems.cancel( + "Cancel unread inbox items refresh on unmount", + ), + ); + }; + }, []); }; From c137236c32e22b3af6ce026d074a7193dfaf5d4b Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Tue, 5 Dec 2023 17:00:24 +0400 Subject: [PATCH 8/8] remove dates check for keep items fetching flag --- .../inbox/saga/refreshUnreadInboxItems.ts | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/store/states/inbox/saga/refreshUnreadInboxItems.ts b/src/store/states/inbox/saga/refreshUnreadInboxItems.ts index 1dd2e32228..f2f61f2681 100644 --- a/src/store/states/inbox/saga/refreshUnreadInboxItems.ts +++ b/src/store/states/inbox/saga/refreshUnreadInboxItems.ts @@ -10,24 +10,9 @@ import * as actions from "../actions"; import { selectInboxItems } from "../selectors"; import { InboxItems } from "../types"; -const checkCanKeepFetchingByDate = ( - firstDocTimestamp: Timestamp | null, - lastDocTimestamp: Timestamp | null, -): boolean => { - if (!firstDocTimestamp) { - return true; - } - if (!lastDocTimestamp) { - return false; - } - - return lastDocTimestamp.seconds >= firstDocTimestamp.seconds; -}; - export function* refreshUnreadInboxItems() { try { const currentItems = (yield select(selectInboxItems)) as InboxItems; - const { firstDocTimestamp } = currentItems; const newInboxItems: FeedLayoutItemWithFollowData[] = []; let startAfter: Timestamp | null = null; let keepItemsFetching = true; @@ -65,9 +50,7 @@ export function* refreshUnreadInboxItems() { ), ); newInboxItems.push(...chatChannelItems, ...feedItemFollowItems); - keepItemsFetching = - hasMore && - checkCanKeepFetchingByDate(firstDocTimestamp, lastDocTimestamp); + keepItemsFetching = hasMore; startAfter = lastDocTimestamp; }