+ {!isPreviewMode &&
{feedItemBaseContent}
}
= (props) => {
[],
);
+ const instantDiscussionMessage = useSelector(selectInstantDiscussionMessagesOrder);
+
const handleFeedItemUpdate = useCallback(
(item: CommonFeed, isRemoved: boolean) => {
- dispatch(
- inboxActions.updateFeedItem({
- item,
- isRemoved,
- }),
- );
-
- if (!isRemoved && item.data.lastMessage?.ownerId === userId) {
- document
- .getElementById("feedLayoutWrapper")
- ?.scrollIntoView({ behavior: "smooth" });
+ if(!instantDiscussionMessage.has(item.data.id)) {
+ dispatch(
+ inboxActions.updateFeedItem({
+ item,
+ isRemoved,
+ }),
+ );
+
+ if (!isRemoved && item.data.lastMessage?.ownerId === userId) {
+ document
+ .getElementById("feedLayoutWrapper")
+ ?.scrollIntoView({ behavior: "smooth" });
+ }
}
},
- [dispatch],
+ [dispatch, instantDiscussionMessage],
);
const handleFeedItemUnfollowed = useCallback(
diff --git a/src/shared/hooks/useCases/useInboxItems.ts b/src/shared/hooks/useCases/useInboxItems.ts
index 818f69db7..e9fefd046 100644
--- a/src/shared/hooks/useCases/useInboxItems.ts
+++ b/src/shared/hooks/useCases/useInboxItems.ts
@@ -7,17 +7,21 @@ import {
checkIsFeedItemFollowLayoutItemWithFollowData,
FeedItemFollowLayoutItemWithFollowData,
FeedLayoutItemWithFollowData,
+ InboxItemBatch,
InboxItemsBatch as ItemsBatch,
} from "@/shared/interfaces";
import { InboxItem, Timestamp } from "@/shared/models";
import {
inboxActions,
InboxItems,
+ NewInboxItems,
optimisticActions,
selectFilteredInboxItems,
selectInboxItems,
+ selectInstantDiscussionMessagesOrder,
selectOptimisticInboxFeedItems,
} from "@/store/states";
+import { useDeepCompareEffect } from "react-use";
interface Return
extends Pick {
@@ -71,6 +75,9 @@ export const useInboxItems = (
): Return => {
const dispatch = useDispatch();
const optimisticInboxItems = useSelector(selectOptimisticInboxFeedItems);
+ const instantDiscussionMessages = useSelector(
+ selectInstantDiscussionMessagesOrder,
+ );
const [newItemsBatches, setNewItemsBatches] = useState([]);
const [lastUpdatedAt, setLastUpdatedAt] = useState(null);
const inboxItems = useSelector(selectInboxItems);
@@ -244,6 +251,33 @@ export const useInboxItems = (
unread,
]);
+ const [notListedFeedItems, setNotListedFeedItems] = useState[]>([]);
+
+ useDeepCompareEffect(() => {
+ if(notListedFeedItems.length > 0 && notListedFeedItems.length === instantDiscussionMessages.size) {
+ const updatedFeedItems = notListedFeedItems.map((item) => {
+ const itemData = item?.item as FeedItemFollowLayoutItemWithFollowData;
+ const feedItemData = itemData.feedItem?.data;
+ const messageUpdatedAt = instantDiscussionMessages.get(feedItemData?.discussionId ?? "")?.timestamp || instantDiscussionMessages.get(feedItemData.id)?.timestamp;
+ return {
+ ...item,
+ item: {
+ ...itemData,
+ feedItem: {
+ ...itemData.feedItem,
+ updatedAt: messageUpdatedAt,
+ }
+ }
+ }
+ }) as NewInboxItems[];
+
+ setNotListedFeedItems([]);
+ dispatch(inboxActions.addNewInboxItems(updatedFeedItems));
+ dispatch(optimisticActions.clearInstantDiscussionMessagesOrder());
+ }
+
+ },[notListedFeedItems, instantDiscussionMessages]);
+
useEffect(() => {
if (!lastBatch || !userId) {
return;
@@ -264,16 +298,23 @@ export const useInboxItems = (
);
if (finalData.length > 0 && isMounted) {
- dispatch(inboxActions.addNewInboxItems(finalData));
- finalData.forEach(({item}) => {
- const itemData = (item as FeedItemFollowLayoutItemWithFollowData).feedItem?.data;
-
+ const newItems: InboxItemBatch[] = [];
+ finalData.forEach((item: InboxItemBatch) => {
+ const itemData = (item.item as FeedItemFollowLayoutItemWithFollowData)?.feedItem?.data;
+
+ if(instantDiscussionMessages.has(itemData?.discussionId ?? "") || instantDiscussionMessages.has(itemData?.id)) {
+ setNotListedFeedItems((prev) => [...prev, item]);
+ } else {
+ newItems.push(item);
+ }
if(optimisticInboxItems.has(itemData.id)) {
dispatch(optimisticActions.removeOptimisticInboxFeedItemState({id: itemData.id}));
} else if (itemData?.discussionId && optimisticInboxItems.has(itemData?.discussionId)) {
dispatch(optimisticActions.removeOptimisticInboxFeedItemState({id: itemData?.discussionId}));
}
})
+
+ newItems.length > 0 && dispatch(inboxActions.addNewInboxItems(newItems));
}
} catch (error) {
Logger.error(error);
@@ -285,7 +326,8 @@ export const useInboxItems = (
return () => {
isMounted = false;
};
- }, [lastBatch]);
+ }, [lastBatch, instantDiscussionMessages]);
+
return {
...inboxItems,
diff --git a/src/store/states/inbox/actions.ts b/src/store/states/inbox/actions.ts
index 3400fe54e..004ad09be 100644
--- a/src/store/states/inbox/actions.ts
+++ b/src/store/states/inbox/actions.ts
@@ -2,7 +2,7 @@ import { createAsyncAction, createStandardAction } from "typesafe-actions";
import { FeedLayoutItemWithFollowData } from "@/shared/interfaces";
import { ChatChannel, CommonFeed, LastMessageContentWithMessageId } from "@/shared/models";
import { InboxActionType } from "./constants";
-import { InboxItems, InboxSearchState } from "./types";
+import { InboxItems, InboxSearchState, NewInboxItems } from "./types";
export const resetInbox = createStandardAction(InboxActionType.RESET_INBOX)<{
onlyIfUnread?: boolean;
@@ -26,15 +26,7 @@ export const getInboxItems = createAsyncAction(
export const addNewInboxItems = createStandardAction(
InboxActionType.ADD_NEW_INBOX_ITEMS,
-)<
- {
- item: FeedLayoutItemWithFollowData;
- statuses: {
- isAdded: boolean;
- isRemoved: boolean;
- };
- }[]
->();
+)();
export const updateInboxItem = createStandardAction(
InboxActionType.UPDATE_INBOX_ITEM,
diff --git a/src/store/states/inbox/types.ts b/src/store/states/inbox/types.ts
index 58542ac2a..c18c75a67 100644
--- a/src/store/states/inbox/types.ts
+++ b/src/store/states/inbox/types.ts
@@ -20,6 +20,14 @@ export interface InboxItems {
unread: boolean;
}
+export interface NewInboxItems {
+ item: FeedLayoutItemWithFollowData;
+ statuses: {
+ isAdded: boolean;
+ isRemoved: boolean;
+ };
+}
+
export type LastState = Pick<
InboxState,
| "items"
@@ -39,3 +47,4 @@ export interface InboxState {
lastReadState: LastState | null;
lastUnreadState: LastState | null;
}
+
diff --git a/src/store/states/optimistic/actions.ts b/src/store/states/optimistic/actions.ts
index 5c741c01d..4a94826bb 100644
--- a/src/store/states/optimistic/actions.ts
+++ b/src/store/states/optimistic/actions.ts
@@ -41,6 +41,16 @@ export const clearOptimisticDiscussionMessages = createStandardAction(
OptimisticActionType.CLEAR_OPTIMISTIC_DISCUSSION_MESSAGES,
)();
+export const setInstantDiscussionMessagesOrder = createStandardAction(
+ OptimisticActionType.SET_INSTANT_DISCUSSION_MESSAGES_ORDER,
+)<{
+ discussionId: string;
+}>();
+
+export const clearInstantDiscussionMessagesOrder = createStandardAction(
+ OptimisticActionType.CLEAR_INSTANT_DISCUSSION_MESSAGES_ORDER,
+)();
+
export const clearCreatedOptimisticFeedItem = createStandardAction(
OptimisticActionType.CLEAR_CREATED_OPTIMISTIC_FEED_ITEM,
)();
diff --git a/src/store/states/optimistic/constants.ts b/src/store/states/optimistic/constants.ts
index 78d33e072..9bca26b87 100644
--- a/src/store/states/optimistic/constants.ts
+++ b/src/store/states/optimistic/constants.ts
@@ -7,6 +7,9 @@ export enum OptimisticActionType {
SET_OPTIMISTIC_DISCUSSION_MESSAGES = "@OPTIMISTIC/SET_OPTIMISTIC_DISCUSSION_MESSAGES",
CLEAR_OPTIMISTIC_DISCUSSION_MESSAGES = "@OPTIMISTIC/CLEAR_OPTIMISTIC_DISCUSSION_MESSAGES",
+ SET_INSTANT_DISCUSSION_MESSAGES_ORDER = "@OPTIMISTIC/SET_INSTANT_DISCUSSION_MESSAGES_ORDER",
+ CLEAR_INSTANT_DISCUSSION_MESSAGES_ORDER = "@OPTIMISTIC/CLEAR_INSTANT_DISCUSSION_MESSAGES_ORDER",
+
CLEAR_CREATED_OPTIMISTIC_FEED_ITEM = "@OPTIMISTIC/CLEAR_CREATED_OPTIMISTIC_FEED_ITEM",
RESET_OPTIMISTIC_STATE = "RESET_OPTIMISTIC_STATE",
}
diff --git a/src/store/states/optimistic/reducer.ts b/src/store/states/optimistic/reducer.ts
index b29d452c2..a437af2cd 100644
--- a/src/store/states/optimistic/reducer.ts
+++ b/src/store/states/optimistic/reducer.ts
@@ -6,6 +6,7 @@ import {
OptimisticState
} from "./types";
import { generateOptimisticFeedItemFollowWithMetadata } from "@/shared/utils";
+import { Timestamp } from "@/shared/models";
type Action = ActionType;
@@ -14,10 +15,53 @@ const initialState: OptimisticState = {
optimisticInboxFeedItems: new Map(),
optimisticDiscussionMessages: new Map(),
createdOptimisticFeedItems: new Map(),
+ instantDiscussionMessagesOrder: new Map(),
};
export const reducer = createReducer(initialState)
.handleAction(actions.resetOptimisticState, () => initialState)
+ .handleAction(actions.setInstantDiscussionMessagesOrder, (state, { payload }) =>
+ produce(state, (nextState) => {
+ const updatedMap = new Map(nextState.instantDiscussionMessagesOrder);
+ const { discussionId } = payload;
+
+ if(updatedMap.size > 1 && updatedMap.has(discussionId)) {
+ const keys = Array.from(updatedMap.keys());
+
+ keys.forEach((key) => {
+ const orderValue = updatedMap.get(key)?.order || 2;
+ const timestampValue = updatedMap.get(key)?.timestamp || Timestamp.fromDate(new Date());
+ updatedMap.set(key, {
+ order: orderValue === 1 ? 1 : orderValue - 1,
+ timestamp: timestampValue
+ });
+ });
+ }
+
+ if(updatedMap.has(discussionId)) {
+ updatedMap.set(discussionId, {
+ order: updatedMap.size || 1,
+ timestamp: Timestamp.fromDate(new Date())
+ });
+ } else {
+ updatedMap.set(discussionId, {
+ order: (updatedMap.size + 1) || 1,
+ timestamp: Timestamp.fromDate(new Date())
+ });
+ }
+ nextState.instantDiscussionMessagesOrder = updatedMap;
+ }),
+ )
+ .handleAction(actions.clearInstantDiscussionMessagesOrder, (state) =>
+ produce(state, (nextState) => {
+ const updatedMap = new Map();
+
+ // updatedMap.delete(payload);
+
+ // Assign the new Map back to the state
+ nextState.instantDiscussionMessagesOrder = updatedMap;
+ }),
+ )
.handleAction(actions.setOptimisticFeedItem, (state, { payload }) =>
produce(state, (nextState) => {
const updatedMap = new Map(nextState.optimisticFeedItems);
diff --git a/src/store/states/optimistic/selectors.ts b/src/store/states/optimistic/selectors.ts
index 6bedea23d..bed310b5e 100644
--- a/src/store/states/optimistic/selectors.ts
+++ b/src/store/states/optimistic/selectors.ts
@@ -12,3 +12,6 @@ export const selectOptimisticDiscussionMessages = (state: AppState) =>
export const selectCreatedOptimisticFeedItems = (state: AppState) =>
state.optimistic.createdOptimisticFeedItems;
+
+export const selectInstantDiscussionMessagesOrder = (state: AppState) =>
+ state.optimistic.instantDiscussionMessagesOrder;
diff --git a/src/store/states/optimistic/types.ts b/src/store/states/optimistic/types.ts
index 4a24fa8c3..fe11016df 100644
--- a/src/store/states/optimistic/types.ts
+++ b/src/store/states/optimistic/types.ts
@@ -2,10 +2,15 @@ import {
FeedItemFollowLayoutItem
} from "@/shared/interfaces";
import { CreateDiscussionMessageDto } from "@/shared/interfaces/api/discussionMessages";
+import { Timestamp } from "@/shared/models";
export interface OptimisticState {
createdOptimisticFeedItems: Map;
optimisticFeedItems: Map;
optimisticInboxFeedItems: Map;
optimisticDiscussionMessages: Map;
+ instantDiscussionMessagesOrder: Map;
}
diff --git a/src/store/store.tsx b/src/store/store.tsx
index 623c46b39..915483972 100644
--- a/src/store/store.tsx
+++ b/src/store/store.tsx
@@ -33,7 +33,8 @@ const mapFields: Array = [
"createdOptimisticFeedItems",
"optimisticFeedItems",
"optimisticInboxFeedItems",
- "optimisticDiscussionMessages"
+ "optimisticDiscussionMessages",
+ "instantDiscussionMessagesOrder"
];
const mapTransformer = createTransform(