Skip to content

Commit 8eeb04c

Browse files
Merge pull request #6460 from nguyentrannhan/develop
Develop
2 parents 512ec39 + c5ceceb commit 8eeb04c

File tree

12 files changed

+142
-86
lines changed

12 files changed

+142
-86
lines changed

apps/chat/src/app/pages/topicDiscussion/TopicDiscussionBox.tsx

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { MentionReactInput, ReplyMessageBox, UserMentionList } from '@mezon/comp
22
import { useAuth, useTopics } from '@mezon/core';
33
import {
44
fetchMessages,
5-
messagesActions,
65
selectAllChannelMemberIds,
76
selectCurrentChannel,
87
selectCurrentChannelId,
@@ -111,14 +110,6 @@ const TopicDiscussionBox = () => {
111110
} else {
112111
const topic = (await createTopic()) as ApiSdTopic;
113112
if (topic) {
114-
dispatch(
115-
messagesActions.updateToBeTopicMessage({
116-
channelId: currentChannelId as string,
117-
messageId: currentTopicInitMessage?.id as string,
118-
topicId: topic.id as string,
119-
creatorId: userProfile?.user?.id as string
120-
})
121-
);
122113
await sleep(10);
123114
await sendMessageTopic(content, mentions, attachments, references, topic.id || '');
124115
}

apps/mobile/src/app/navigation/Authentication/index.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@ import moment from 'moment';
1111
import { Dimensions, NativeModules, Platform } from 'react-native';
1212
import BottomSheetRootListener from '../../components/BottomSheetRootListener';
1313
import CallingModalWrapper from '../../components/CallingModalWrapper';
14+
import ModalRootListener from '../../components/ModalRootListener';
1415
import useTabletLandscape from '../../hooks/useTabletLandscape';
1516
import HomeScreenTablet from '../../screens/home/HomeScreenTablet';
17+
import ChannelMessageListener from '../../screens/home/homedrawer/ChannelMessageListener';
18+
import ChannelMessageReactionListener from '../../screens/home/homedrawer/ChannelMessageReactionListener';
1619
import HomeDefaultWrapper from '../../screens/home/homedrawer/HomeDefaultWrapper';
1720
import ChannelVoicePopup from '../../screens/home/homedrawer/components/ChannelVoicePopup';
1821
import { RenderVideoDetail } from '../../screens/home/homedrawer/components/RenderVideoDetail';
@@ -28,9 +31,6 @@ import { MessagesStacks } from './stacks/MessagesStacks';
2831
import { NotificationStacks } from './stacks/NotificationStacks';
2932
import { ServersStacks } from './stacks/ServersStacks';
3033
import { SettingStacks } from './stacks/SettingStacks';
31-
import ChannelMessageListener from "../../screens/home/homedrawer/ChannelMessageListener";
32-
import ChannelMessageReactionListener from "../../screens/home/homedrawer/ChannelMessageReactionListener";
33-
import ModalRootListener from "../../components/ModalRootListener";
3434
const RootStack = createStackNavigator();
3535
const { SharedPreferences } = NativeModules;
3636

apps/mobile/src/app/screens/home/homedrawer/BackNativeListener.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import { ActionEmitEvent } from '@mezon/mobile-components';
21
import { selectDmGroupCurrentId, selectHiddenBottomTabMobile } from '@mezon/store';
32
import { useDrawerStatus } from '@react-navigation/drawer';
43
import { DrawerActions, useNavigation, useNavigationState } from '@react-navigation/native';
5-
import React, { useEffect, useMemo, useState } from 'react';
6-
import { Alert, BackHandler, DeviceEventEmitter, View } from 'react-native';
4+
import React, { useEffect, useMemo } from 'react';
5+
import { Alert, BackHandler, View } from 'react-native';
76
import { useSelector } from 'react-redux';
87
import { APP_SCREEN } from '../../../navigation/ScreenTypes';
98

apps/mobile/src/app/screens/home/homedrawer/components/ClanMenu/ClanMenu/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useBottomSheetModal } from '@gorhom/bottom-sheet';
22
import { useMarkAsRead, usePermissionChecker } from '@mezon/core';
33
import { ActionEmitEvent, Icons } from '@mezon/mobile-components';
4-
import { baseColor, useTheme } from '@mezon/mobile-ui';
4+
import { useTheme } from '@mezon/mobile-ui';
55
import { appActions, categoriesActions, selectCurrentClan, selectIsShowEmptyCategory, useAppDispatch } from '@mezon/store-mobile';
66
import { EPermission } from '@mezon/utils';
77
import { useNavigation } from '@react-navigation/native';
@@ -10,7 +10,7 @@ import { useTranslation } from 'react-i18next';
1010
import { DeviceEventEmitter, Text, View } from 'react-native';
1111
import { ScrollView } from 'react-native-gesture-handler';
1212
import { useSelector } from 'react-redux';
13-
import { IMezonMenuItemProps, IMezonMenuSectionProps, MezonClanAvatar, MezonMenu, MezonSwitch, reserve } from '../../../../../../componentUI';
13+
import { IMezonMenuItemProps, IMezonMenuSectionProps, MezonClanAvatar, MezonMenu, MezonSwitch } from '../../../../../../componentUI';
1414
import MezonButtonIcon from '../../../../../../componentUI/MezonButtonIcon';
1515
import DeleteClanModal from '../../../../../../components/DeleteClanModal';
1616
import { APP_SCREEN, AppStackScreenProps } from '../../../../../../navigation/ScreenTypes';

libs/components/src/lib/components/ChannelTopbar/TopBarComponents/PinnedMessages/index.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useAppParams, useEscapeKeyClose, useOnClickOutside } from '@mezon/core';
1+
import { ColorRoleProvider, useAppParams, useEscapeKeyClose, useOnClickOutside } from '@mezon/core';
22
import { PinMessageEntity, pinMessageActions, selectCurrentChannelId, selectTheme, useAppDispatch } from '@mezon/store';
33
import { ApiMessageAttachment } from 'mezon-js/api.gen';
44
import { RefObject, useRef, useState } from 'react';
@@ -35,14 +35,16 @@ const PinnedMessages = ({ onClose, rootRef, mode }: PinnedMessagesProps) => {
3535
const modalDeleteRef = useRef(null);
3636
const [openDeletePinMessage, closeDeletePinMessage] = useModal(() => {
3737
return (
38-
<ModalDeletePinMess
39-
pinMessage={unpinMess?.pinMessage as PinMessageEntity}
40-
contentString={unpinMess?.contentString}
41-
handlePinMessage={() => handleUnPinMessage(unpinMess?.pinMessage.message_id || '')}
42-
closeModal={closeDeletePinMessage}
43-
attachments={unpinMess?.attachments as ApiMessageAttachment[]}
44-
modalref={modalDeleteRef}
45-
/>
38+
<ColorRoleProvider>
39+
<ModalDeletePinMess
40+
pinMessage={unpinMess?.pinMessage as PinMessageEntity}
41+
contentString={unpinMess?.contentString}
42+
handlePinMessage={() => handleUnPinMessage(unpinMess?.pinMessage.message_id || '')}
43+
closeModal={closeDeletePinMessage}
44+
attachments={unpinMess?.attachments as ApiMessageAttachment[]}
45+
modalref={modalDeleteRef}
46+
/>
47+
</ColorRoleProvider>
4648
);
4749
}, [unpinMess]);
4850

libs/components/src/lib/components/ChannelTopbar/TopBarComponents/Threads/ThreadModal/ThreadList.tsx

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,57 @@
11
import { useOnScreen } from '@mezon/core';
22
import { ThreadsEntity } from '@mezon/store';
3-
import { MutableRefObject, useEffect } from 'react';
3+
import { useEffect, useRef } from 'react';
44
import GroupThreads from './GroupThreads';
55
import { getActiveThreads, getJoinedThreadsWithinLast30Days, getThreadsOlderThan30Days } from './hepler';
66

77
type ThreadListProps = {
8-
hasMore: boolean;
98
isLoading: boolean;
109
loadMore: () => void | undefined | null;
1110
threads: ThreadsEntity[];
12-
preventClosePannel: MutableRefObject<boolean>;
11+
preventClosePannel: React.MutableRefObject<boolean>;
1312
};
1413

15-
export default function ThreadList({ hasMore, isLoading, loadMore, threads, preventClosePannel }: ThreadListProps) {
14+
export default function ThreadList({ isLoading, threads, loadMore, preventClosePannel }: ThreadListProps) {
15+
const ulRef = useRef<HTMLUListElement | null>(null);
1616
const activeThreads = getActiveThreads(threads);
1717
const joinedThreads = getJoinedThreadsWithinLast30Days(threads);
1818
const oldThreads = getThreadsOlderThan30Days(threads);
1919

20-
const { measureRef, isIntersecting, observer } = useOnScreen();
20+
const { measureRef, isIntersecting, observer } = useOnScreen({ root: ulRef.current });
21+
22+
const lastThread = threads[threads.length - 1];
23+
24+
const isLastInActive = activeThreads.includes(lastThread);
25+
const isLastInJoined = joinedThreads.includes(lastThread);
26+
const isLastInOld = oldThreads.includes(lastThread);
2127

2228
useEffect(() => {
23-
if (isIntersecting && hasMore) {
29+
if (isIntersecting) {
2430
loadMore();
2531
observer?.disconnect();
2632
}
27-
}, [isIntersecting, hasMore, loadMore]);
33+
}, [isIntersecting, loadMore]);
2834

2935
return (
30-
<ul className="pb-4 pr-4 pl-4">
31-
<GroupThreads preventClosePannel={preventClosePannel} title="Active Threads" threads={activeThreads} />
32-
<GroupThreads preventClosePannel={preventClosePannel} title="Joined Threads (Last 30 Days)" threads={joinedThreads} />
33-
<GroupThreads preventClosePannel={preventClosePannel} title="Older Threads" threads={oldThreads} measureRef={measureRef} />
36+
<ul ref={ulRef} className="pb-4 pr-4 pl-4 overflow-y-auto h-[500px]">
37+
<GroupThreads
38+
preventClosePannel={preventClosePannel}
39+
title="Active Threads"
40+
threads={activeThreads}
41+
measureRef={isLastInActive ? measureRef : undefined}
42+
/>
43+
<GroupThreads
44+
preventClosePannel={preventClosePannel}
45+
title="Joined Threads (Last 30 Days)"
46+
threads={joinedThreads}
47+
measureRef={isLastInJoined ? measureRef : undefined}
48+
/>
49+
<GroupThreads
50+
preventClosePannel={preventClosePannel}
51+
title="Older Threads"
52+
threads={oldThreads}
53+
measureRef={isLastInOld ? measureRef : undefined}
54+
/>
3455
{isLoading && <li>Loading...</li>}
3556
</ul>
3657
);

libs/components/src/lib/components/ChannelTopbar/TopBarComponents/Threads/ThreadModal/index.tsx

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,34 +84,40 @@ const ThreadModal = ({ onClose, rootRef }: ThreadsProps) => {
8484
const [page, setPage] = useState(1);
8585
const [hasMore, setHasMore] = useState(false);
8686
const [isLoading, setIsLoading] = useState(false);
87-
88-
const fetchThreads = async () => {
87+
const fetchThreads = async (pageNumber: number) => {
8988
setIsLoading(true);
9089
try {
9190
const body = {
9291
channelId: currentChannelId,
9392
clanId: currentClanId ?? '',
94-
page: page,
93+
page: pageNumber,
9594
noCache: true
9695
};
9796

9897
const res = await dispatch(threadsActions.fetchThreads(body));
9998
const newThreads = Array.isArray(res?.payload) ? res.payload : [];
100-
const endResult = newThreads.length < LIMIT;
101-
setHasMore(!endResult);
99+
const isLastPage = newThreads.length < LIMIT;
100+
setHasMore(!isLastPage);
102101
} catch (error) {
103102
console.error('Error fetching threads:', error);
104103
}
105104
setIsLoading(false);
106105
};
106+
107107
useEffect(() => {
108-
fetchThreads();
109-
}, [page, currentChannelId]);
108+
fetchThreads(1);
109+
}, []);
110110

111111
const loadMore = useCallback(() => {
112-
setPage((page) => page + 1);
113-
setIsLoading(true);
114-
}, []);
112+
if (hasMore) {
113+
setPage((prevPage) => {
114+
const nextPage = prevPage + 1;
115+
fetchThreads(nextPage);
116+
return nextPage;
117+
});
118+
}
119+
}, [hasMore]);
120+
115121
return (
116122
<div
117123
ref={modalRef}
@@ -146,14 +152,8 @@ const ThreadModal = ({ onClose, rootRef }: ThreadsProps) => {
146152
</ul>
147153
)}
148154
{showThreadList && (
149-
<div className="h-[500px] overflow-y-auto">
150-
<ThreadList
151-
preventClosePannel={preventClosePannel}
152-
hasMore={hasMore}
153-
isLoading={isLoading}
154-
loadMore={loadMore}
155-
threads={threadFetched}
156-
/>
155+
<div className="h-[500px] ">
156+
<ThreadList preventClosePannel={preventClosePannel} isLoading={isLoading} loadMore={loadMore} threads={threadFetched} />
157157
</div>
158158
)}
159159
{showEmpty && <EmptyThread onClick={handleCreateThread} />}

libs/core/src/lib/chat/contexts/ChatContext.tsx

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ import {
139139
} from 'mezon-js';
140140
import { ApiChannelDescription, ApiCreateEventRequest, ApiGiveCoffeeEvent, ApiMessageReaction } from 'mezon-js/api.gen';
141141
import { ApiChannelMessageHeader, ApiNotificationUserChannel, ApiPermissionUpdate, ApiTokenSentEvent, ApiWebhook } from 'mezon-js/dist/api.gen';
142-
import { ChannelCanvas, RemoveFriend } from 'mezon-js/socket';
142+
import { ChannelCanvas, RemoveFriend, SdTopicEvent } from 'mezon-js/socket';
143143
import React, { useCallback, useEffect, useRef } from 'react';
144144
import { useAuth } from '../../auth/hooks/useAuth';
145145
import { useCustomNavigate } from '../hooks/useCustomNavigate';
@@ -270,8 +270,7 @@ const ChatContextProvider: React.FC<ChatContextProviderProps> = ({ children }) =
270270
sender_id: message.sender_id,
271271
timestamp_seconds: message.create_time_seconds
272272
};
273-
274-
dispatch(topicsActions.setTopicLastSent({ topicId: message.topic_id || '', lastSentMess: lastMsg }));
273+
dispatch(topicsActions.setTopicLastSent({ clanId: message.clan_id || '', topicId: message.topic_id || '', lastSentMess: lastMsg }));
275274
}
276275

277276
try {
@@ -1581,6 +1580,30 @@ const ChatContextProvider: React.FC<ChatContextProviderProps> = ({ children }) =
15811580
dispatch(channelAppSlice.actions.setJoinChannelAppData({ dataUpdate: joinChannelAppData }));
15821581
}, []);
15831582

1583+
const onsdtopicevent = useCallback(async (sdTopicEvent: SdTopicEvent) => {
1584+
dispatch(
1585+
messagesActions.updateToBeTopicMessage({
1586+
channelId: sdTopicEvent?.channel_id as string,
1587+
messageId: sdTopicEvent?.message_id as string,
1588+
topicId: sdTopicEvent?.id as string,
1589+
creatorId: sdTopicEvent?.user_id as string
1590+
})
1591+
);
1592+
dispatch(
1593+
topicsActions.addTopic({
1594+
clanId: sdTopicEvent.clan_id,
1595+
topic: {
1596+
id: sdTopicEvent.id,
1597+
clan_id: sdTopicEvent.clan_id,
1598+
channel_id: sdTopicEvent.channel_id,
1599+
message_id: sdTopicEvent.message_id,
1600+
last_sent_message: sdTopicEvent.last_sent_message,
1601+
message: sdTopicEvent.message
1602+
}
1603+
})
1604+
);
1605+
}, []);
1606+
15841607
const setCallbackEventFn = React.useCallback(
15851608
(socket: Socket) => {
15861609
socket.onvoicejoined = onvoicejoined;
@@ -1678,6 +1701,8 @@ const ChatContextProvider: React.FC<ChatContextProviderProps> = ({ children }) =
16781701
socket.onclanupdated = onclanupdated;
16791702

16801703
socket.onJoinChannelAppEvent = onJoinChannelAppEvent;
1704+
1705+
socket.onsdtopicevent = onsdtopicevent;
16811706
},
16821707
// eslint-disable-next-line react-hooks/exhaustive-deps
16831708
[
@@ -1725,7 +1750,8 @@ const ChatContextProvider: React.FC<ChatContextProviderProps> = ({ children }) =
17251750
onmessagebuttonclicked,
17261751
onwebrtcsignalingfwd,
17271752
onclanupdated,
1728-
onJoinChannelAppEvent
1753+
onJoinChannelAppEvent,
1754+
onsdtopicevent
17291755
]
17301756
);
17311757

@@ -1831,6 +1857,8 @@ const ChatContextProvider: React.FC<ChatContextProviderProps> = ({ children }) =
18311857
socket.ontokensent = () => {};
18321858
// eslint-disable-next-line @typescript-eslint/no-empty-function
18331859
socket.onJoinChannelAppEvent = () => {};
1860+
// eslint-disable-next-line @typescript-eslint/no-empty-function
1861+
socket.onsdtopicevent = () => {};
18341862
};
18351863
}, [
18361864
onchannelmessage,
@@ -1878,7 +1906,8 @@ const ChatContextProvider: React.FC<ChatContextProviderProps> = ({ children }) =
18781906
onuserstatusevent,
18791907
oneventwebhook,
18801908
ontokensent,
1881-
onJoinChannelAppEvent
1909+
onJoinChannelAppEvent,
1910+
onsdtopicevent
18821911
]);
18831912

18841913
const value = React.useMemo<ChatContextValue>(

libs/core/src/lib/chat/hooks/useChatSending.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,6 @@ export function useChatSending({ mode, channelOrDirect }: UseChatSendingOptions)
9999
topicId: topic?.id as string
100100
})
101101
);
102-
dispatch(
103-
messagesActions.updateToBeTopicMessage({
104-
channelId: channelIdOrDirectId as string,
105-
messageId: initMessageOfTopic?.id as string,
106-
topicId: topic.id as string,
107-
creatorId: userProfile?.user?.id as string
108-
})
109-
);
110102
return;
111103
}
112104
}

libs/core/src/lib/chat/hooks/useOnScreen.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useCallback, useState } from 'react';
22

3-
export const useOnScreen = ({ root = null, rootMargin = '0px', threshold = 0 } = {}) => {
3+
export const useOnScreen = ({ root = null as HTMLElement | null, rootMargin = '0px', threshold = 0 } = {}) => {
44
const [observer, setObserver] = useState<IntersectionObserver | null>(null);
55
const [isIntersecting, setIntersecting] = useState(false);
66

0 commit comments

Comments
 (0)