@droppii-org/chat-mobile 0.2.67 → 0.2.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/module/components/GroupItem/index.js +154 -0
- package/lib/module/components/GroupItem/index.js.map +1 -0
- package/lib/module/core/useChatListener.js +34 -2
- package/lib/module/core/useChatListener.js.map +1 -1
- package/lib/module/hooks/groups/useFetchPublicGroup.js +39 -0
- package/lib/module/hooks/groups/useFetchPublicGroup.js.map +1 -0
- package/lib/module/hooks/groups/useJoinGroup.js +42 -0
- package/lib/module/hooks/groups/useJoinGroup.js.map +1 -0
- package/lib/module/hooks/message/usePinMessage.js +4 -2
- package/lib/module/hooks/message/usePinMessage.js.map +1 -1
- package/lib/module/hooks/message/useSendMessage.js +7 -12
- package/lib/module/hooks/message/useSendMessage.js.map +1 -1
- package/lib/module/hooks/query-keys.js +6 -0
- package/lib/module/hooks/query-keys.js.map +1 -1
- package/lib/module/hooks/useGroupPermission.js +34 -0
- package/lib/module/hooks/useGroupPermission.js.map +1 -0
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/screens/SearchConversation/TabResult.js +1 -1
- package/lib/module/screens/SearchConversation/TabResult.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatComposer.js +35 -14
- package/lib/module/screens/chat-detail/ChatComposer.js.map +1 -1
- package/lib/module/screens/chat-detail/ChatDetail.js +20 -2
- package/lib/module/screens/chat-detail/ChatDetail.js.map +1 -1
- package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxOverlay.js +5 -0
- package/lib/module/screens/chat-detail/messageToolbox/MessageToolboxOverlay.js.map +1 -1
- package/lib/module/screens/chat-detail/types.js.map +1 -1
- package/lib/module/screens/inbox/CommunityTab.js +55 -0
- package/lib/module/screens/inbox/CommunityTab.js.map +1 -0
- package/lib/module/screens/inbox/Inbox.js +51 -40
- package/lib/module/screens/inbox/Inbox.js.map +1 -1
- package/lib/module/translation/resources/i18n.js +9 -1
- package/lib/module/translation/resources/i18n.js.map +1 -1
- package/lib/typescript/src/components/GroupItem/index.d.ts +8 -0
- package/lib/typescript/src/components/GroupItem/index.d.ts.map +1 -0
- package/lib/typescript/src/core/useChatListener.d.ts.map +1 -1
- package/lib/typescript/src/hooks/groups/useFetchPublicGroup.d.ts +213 -0
- package/lib/typescript/src/hooks/groups/useFetchPublicGroup.d.ts.map +1 -0
- package/lib/typescript/src/hooks/groups/useJoinGroup.d.ts +5 -0
- package/lib/typescript/src/hooks/groups/useJoinGroup.d.ts.map +1 -0
- package/lib/typescript/src/hooks/message/usePinMessage.d.ts.map +1 -1
- package/lib/typescript/src/hooks/message/useSendMessage.d.ts.map +1 -1
- package/lib/typescript/src/hooks/query-keys.d.ts +6 -0
- package/lib/typescript/src/hooks/query-keys.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useGroupPermission.d.ts +6 -0
- package/lib/typescript/src/hooks/useGroupPermission.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatComposer.d.ts +3 -1
- package/lib/typescript/src/screens/chat-detail/ChatComposer.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatDetail.d.ts +1 -1
- package/lib/typescript/src/screens/chat-detail/ChatDetail.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.d.ts +1 -1
- package/lib/typescript/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.d.ts.map +1 -1
- package/lib/typescript/src/screens/chat-detail/types.d.ts +2 -1
- package/lib/typescript/src/screens/chat-detail/types.d.ts.map +1 -1
- package/lib/typescript/src/screens/inbox/CommunityTab.d.ts +6 -0
- package/lib/typescript/src/screens/inbox/CommunityTab.d.ts.map +1 -0
- package/lib/typescript/src/screens/inbox/Inbox.d.ts +2 -1
- package/lib/typescript/src/screens/inbox/Inbox.d.ts.map +1 -1
- package/lib/typescript/src/translation/resources/i18n.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/GroupItem/index.tsx +170 -0
- package/src/core/useChatListener.ts +54 -1
- package/src/hooks/groups/useFetchPublicGroup.ts +43 -0
- package/src/hooks/groups/useJoinGroup.ts +46 -0
- package/src/hooks/message/usePinMessage.ts +8 -2
- package/src/hooks/message/useSendMessage.ts +11 -15
- package/src/hooks/query-keys.ts +8 -0
- package/src/hooks/useGroupPermission.ts +43 -0
- package/src/index.tsx +5 -1
- package/src/screens/SearchConversation/TabResult.tsx +1 -1
- package/src/screens/chat-detail/ChatComposer.tsx +50 -27
- package/src/screens/chat-detail/ChatDetail.tsx +25 -1
- package/src/screens/chat-detail/messageToolbox/MessageToolboxOverlay.tsx +8 -1
- package/src/screens/chat-detail/types.ts +5 -1
- package/src/screens/inbox/CommunityTab.tsx +65 -0
- package/src/screens/inbox/Inbox.tsx +51 -39
- package/src/translation/resources/i18n.ts +8 -0
|
@@ -63,12 +63,9 @@ import { ChatCurrentQuotedMessage } from './ChatCurrentQuotedMessage';
|
|
|
63
63
|
import { useSendMessage } from '../../hooks/message/useSendMessage';
|
|
64
64
|
import { openBotMenuSheet } from './BotMenuSheet';
|
|
65
65
|
import { UIUtils } from '../../utils/UIUtils';
|
|
66
|
-
import {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
SessionType,
|
|
70
|
-
} from '@droppii/openim-rn-client-sdk';
|
|
71
|
-
import { useConversationStore } from '../../store';
|
|
66
|
+
import { GroupPermission, PeerType } from '@droppii/openim-rn-client-sdk';
|
|
67
|
+
import { useGuardedAction } from '../../hooks/useGroupPermission';
|
|
68
|
+
import { useIsJoinedGroup } from '../../hooks/useIsJoinedGroup';
|
|
72
69
|
|
|
73
70
|
interface ChatComposerInternalProps {
|
|
74
71
|
isEmptyMessage?: boolean;
|
|
@@ -76,6 +73,8 @@ interface ChatComposerInternalProps {
|
|
|
76
73
|
isComposeDisabled?: boolean;
|
|
77
74
|
composerRef?: RefObject<View | null>;
|
|
78
75
|
onComposerLayout?: (event: LayoutChangeEvent) => void;
|
|
76
|
+
onPressJoinGroup?: () => void;
|
|
77
|
+
isJoiningGroup?: boolean;
|
|
79
78
|
}
|
|
80
79
|
|
|
81
80
|
export const ChatComposer = memo(
|
|
@@ -85,6 +84,8 @@ export const ChatComposer = memo(
|
|
|
85
84
|
isComposeDisabled = false,
|
|
86
85
|
composerRef,
|
|
87
86
|
onComposerLayout,
|
|
87
|
+
onPressJoinGroup,
|
|
88
|
+
isJoiningGroup = false,
|
|
88
89
|
}: ChatComposerInternalProps) => {
|
|
89
90
|
const insets = useSafeAreaInsets();
|
|
90
91
|
const isDisableCompose = isComposeDisabled;
|
|
@@ -103,7 +104,12 @@ export const ChatComposer = memo(
|
|
|
103
104
|
const { mutateAsync: closeSupportSession } = useCloseSupportSession();
|
|
104
105
|
const { sendMessage } = useSendMessage();
|
|
105
106
|
const compose = useChatCompose();
|
|
106
|
-
|
|
107
|
+
|
|
108
|
+
const { data: isJoinedGroup } = useIsJoinedGroup(conversation?.groupID);
|
|
109
|
+
|
|
110
|
+
const isNotInGroup = useMemo(() => {
|
|
111
|
+
return conversation?.groupID ? !isJoinedGroup : false;
|
|
112
|
+
}, [conversation?.groupID, isJoinedGroup]);
|
|
107
113
|
|
|
108
114
|
const {
|
|
109
115
|
activePanelType,
|
|
@@ -137,27 +143,20 @@ export const ChatComposer = memo(
|
|
|
137
143
|
onAttachmentOpenChange: setIsAttachmentOpen,
|
|
138
144
|
});
|
|
139
145
|
|
|
140
|
-
const handleSend =
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
.
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
if (compose.isUploading || !compose.canSend) return;
|
|
155
|
-
try {
|
|
156
|
-
await compose.send();
|
|
157
|
-
} catch (error) {
|
|
158
|
-
if (__DEV__) console.error('[ChatComposer] Failed to send:', error);
|
|
146
|
+
const handleSend = useGuardedAction(
|
|
147
|
+
GroupPermission.SendMessage,
|
|
148
|
+
useCallback(async () => {
|
|
149
|
+
if (compose.isUploading || !compose.canSend) return;
|
|
150
|
+
try {
|
|
151
|
+
await compose.send();
|
|
152
|
+
} catch (error) {
|
|
153
|
+
if (__DEV__) console.error('[ChatComposer] Failed to send:', error);
|
|
154
|
+
}
|
|
155
|
+
}, [compose]),
|
|
156
|
+
{
|
|
157
|
+
deniedMessage: trans('chat:no_send_permission'),
|
|
159
158
|
}
|
|
160
|
-
|
|
159
|
+
);
|
|
161
160
|
|
|
162
161
|
const handleInputFocus = useCallback(() => {
|
|
163
162
|
setIsInputFocused(true);
|
|
@@ -443,6 +442,30 @@ export const ChatComposer = memo(
|
|
|
443
442
|
/>
|
|
444
443
|
</KContainer.View>
|
|
445
444
|
);
|
|
445
|
+
} else if (isNotInGroup) {
|
|
446
|
+
content = (
|
|
447
|
+
<KContainer.View
|
|
448
|
+
paddingH="0.75rem"
|
|
449
|
+
justifyContent="center"
|
|
450
|
+
brTW={1}
|
|
451
|
+
brTC={KColors.border.light}
|
|
452
|
+
>
|
|
453
|
+
<KLabel.Text
|
|
454
|
+
typo="TextSmNormal"
|
|
455
|
+
textAlign="center"
|
|
456
|
+
paddingV={'0.75rem'}
|
|
457
|
+
>
|
|
458
|
+
{trans('group:not_in_group')}
|
|
459
|
+
</KLabel.Text>
|
|
460
|
+
<KButton.Solid
|
|
461
|
+
size="md"
|
|
462
|
+
label={trans('group:join')}
|
|
463
|
+
stretch
|
|
464
|
+
loading={isJoiningGroup}
|
|
465
|
+
onPress={onPressJoinGroup}
|
|
466
|
+
/>
|
|
467
|
+
</KContainer.View>
|
|
468
|
+
);
|
|
446
469
|
} else {
|
|
447
470
|
content = (
|
|
448
471
|
<KContainer.View background={'#F9F9FA'}>
|
|
@@ -30,10 +30,14 @@ import {
|
|
|
30
30
|
useGetConversationDetail,
|
|
31
31
|
useGetConversationTarget,
|
|
32
32
|
} from '../../hooks/conversation/useGetConversationDetail';
|
|
33
|
-
import
|
|
33
|
+
import {
|
|
34
|
+
GroupJoinSource,
|
|
35
|
+
type MessageItem,
|
|
36
|
+
} from '@droppii/openim-rn-client-sdk';
|
|
34
37
|
import { useMessages } from '../../hooks/message/useMessages';
|
|
35
38
|
import { ChatEvent, type GroupRemovedPayload } from '../../types/events';
|
|
36
39
|
import { useSetIsShowFLashMessage } from '../../context/global';
|
|
40
|
+
import { useJoinGroup } from '../../hooks/groups/useJoinGroup';
|
|
37
41
|
|
|
38
42
|
const ChatDetail = memo(
|
|
39
43
|
({
|
|
@@ -50,6 +54,7 @@ const ChatDetail = memo(
|
|
|
50
54
|
onPressUrl,
|
|
51
55
|
customMessageItemFactory,
|
|
52
56
|
pannelActions,
|
|
57
|
+
groupJoinSource,
|
|
53
58
|
}: ChatDetailProps) => {
|
|
54
59
|
const navigation = useNavigation();
|
|
55
60
|
const mediaViewerRef = useRef<MediaViewerModalHandle>(null);
|
|
@@ -94,6 +99,8 @@ const ChatDetail = memo(
|
|
|
94
99
|
hasMoreNew,
|
|
95
100
|
} = useMessages({ conversationId, startClientMsgId: targetMessageId });
|
|
96
101
|
|
|
102
|
+
const { mutate: joinGroup, isPending: isJoiningGroup } = useJoinGroup();
|
|
103
|
+
|
|
97
104
|
const setShowFLashMessage = useSetIsShowFLashMessage();
|
|
98
105
|
|
|
99
106
|
const { pinnedMessages, pinMessage, unpinMessage } =
|
|
@@ -164,6 +171,21 @@ const ChatDetail = memo(
|
|
|
164
171
|
onPressMenu?.(conversationId);
|
|
165
172
|
}, [conversationId, onPressMenu]);
|
|
166
173
|
|
|
174
|
+
const handlePressJoinGroup = useCallback(() => {
|
|
175
|
+
if (!conversation?.groupID) return;
|
|
176
|
+
joinGroup({
|
|
177
|
+
groupID: conversation?.groupID,
|
|
178
|
+
reqMsg: '',
|
|
179
|
+
joinSource: groupJoinSource || GroupJoinSource.Search,
|
|
180
|
+
groupName: conversation?.showName || '',
|
|
181
|
+
});
|
|
182
|
+
}, [
|
|
183
|
+
groupJoinSource,
|
|
184
|
+
conversation?.groupID,
|
|
185
|
+
joinGroup,
|
|
186
|
+
conversation?.showName,
|
|
187
|
+
]);
|
|
188
|
+
|
|
167
189
|
return (
|
|
168
190
|
<KContainer.Page flex edges={['bottom']}>
|
|
169
191
|
<ChatDetailHeader
|
|
@@ -207,6 +229,8 @@ const ChatDetail = memo(
|
|
|
207
229
|
isEmptyMessage={messages?.length === 0}
|
|
208
230
|
pannelActions={pannelActions}
|
|
209
231
|
isComposeDisabled={isComposeDisabled}
|
|
232
|
+
onPressJoinGroup={handlePressJoinGroup}
|
|
233
|
+
isJoiningGroup={isJoiningGroup}
|
|
210
234
|
/>
|
|
211
235
|
|
|
212
236
|
<MediaViewerModal ref={mediaViewerRef} />
|
|
@@ -20,7 +20,11 @@ import { MessageToolboxWrapper } from './MessageToolboxWrapper';
|
|
|
20
20
|
import type { ReactNode } from 'react';
|
|
21
21
|
import { useSendMessage } from '../../../hooks/message/useSendMessage';
|
|
22
22
|
import { useChatDetailContext } from '../../../context';
|
|
23
|
-
import
|
|
23
|
+
import {
|
|
24
|
+
GroupPermission,
|
|
25
|
+
type MessageItem,
|
|
26
|
+
} from '@droppii/openim-rn-client-sdk';
|
|
27
|
+
import { useHasGroupPermission } from '../../../hooks/useGroupPermission';
|
|
24
28
|
|
|
25
29
|
interface MessageToolboxOverlayProps {
|
|
26
30
|
currentUserId?: string;
|
|
@@ -51,6 +55,7 @@ export const MessageToolboxOverlay = forwardRef<
|
|
|
51
55
|
[message, currentUserId]
|
|
52
56
|
);
|
|
53
57
|
const { retryMessage, revokeMessage } = useSendMessage();
|
|
58
|
+
const isPinAllowed = useHasGroupPermission(GroupPermission.PinMessage);
|
|
54
59
|
|
|
55
60
|
const hide = useCallback(() => {
|
|
56
61
|
setVisible(false);
|
|
@@ -173,6 +178,8 @@ export const MessageToolboxOverlay = forwardRef<
|
|
|
173
178
|
toolbox={
|
|
174
179
|
<MessageToolboxMenu
|
|
175
180
|
{...toolboxItems}
|
|
181
|
+
showPinMessage={toolboxItems.showPinMessage && isPinAllowed}
|
|
182
|
+
showUnpinMessage={toolboxItems.showUnpinMessage && isPinAllowed}
|
|
176
183
|
onCopyMessage={handleCopyMessage}
|
|
177
184
|
onCopyMessageLink={handleCopyMessageLink}
|
|
178
185
|
onPinMessage={handlePinMessage}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import type { MediaItem } from '../../hooks/useMediaViewer';
|
|
3
3
|
import type { MeasuredRect } from './messageToolbox/types';
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
GroupJoinSource,
|
|
6
|
+
MessageItem,
|
|
7
|
+
} from '@droppii/openim-rn-client-sdk';
|
|
5
8
|
|
|
6
9
|
export type DChatActionIconProvider = 'MaterialCommunityIcons' | 'DroppiiNew';
|
|
7
10
|
|
|
@@ -100,4 +103,5 @@ export interface ChatDetailProps extends Omit<
|
|
|
100
103
|
onPressUrl?: (url: string) => void;
|
|
101
104
|
customMessageItemFactory?: (item: MessageItem) => ReactNode;
|
|
102
105
|
pannelActions?: DChatPannelAction[];
|
|
106
|
+
groupJoinSource?: GroupJoinSource;
|
|
103
107
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { KContainer, KSpacingValue } from '@droppii/libs';
|
|
2
|
+
import { memo, useCallback } from 'react';
|
|
3
|
+
import { ActivityIndicator, StyleSheet } from 'react-native';
|
|
4
|
+
import type { SearchPublicGroupInfo } from '@droppii/openim-rn-client-sdk';
|
|
5
|
+
import { useFetchPublicGroup } from '../../hooks/groups/useFetchPublicGroup';
|
|
6
|
+
import { GroupItem } from '../../components/GroupItem';
|
|
7
|
+
|
|
8
|
+
interface CommunityTabProps {
|
|
9
|
+
onPressGroup?: (groupId: string) => void;
|
|
10
|
+
}
|
|
11
|
+
export const CommunityTab = memo(({ onPressGroup }: CommunityTabProps) => {
|
|
12
|
+
const {
|
|
13
|
+
dataFlatten,
|
|
14
|
+
isFetching,
|
|
15
|
+
hasNextPage,
|
|
16
|
+
fetchNextPage,
|
|
17
|
+
isFetchingNextPage,
|
|
18
|
+
isRefetching,
|
|
19
|
+
refetch,
|
|
20
|
+
} = useFetchPublicGroup('');
|
|
21
|
+
|
|
22
|
+
const renderItem = useCallback(
|
|
23
|
+
({ item }: { item: SearchPublicGroupInfo }) => (
|
|
24
|
+
<GroupItem item={item} onPress={onPressGroup} />
|
|
25
|
+
),
|
|
26
|
+
[onPressGroup]
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const keyExtractor = useCallback(
|
|
30
|
+
(item: SearchPublicGroupInfo) => item.groupID,
|
|
31
|
+
[]
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const onEndReached = useCallback(() => {
|
|
35
|
+
if (hasNextPage && !isFetchingNextPage) {
|
|
36
|
+
fetchNextPage();
|
|
37
|
+
}
|
|
38
|
+
}, [hasNextPage, isFetchingNextPage, fetchNextPage]);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<KContainer.Page flex>
|
|
42
|
+
{isFetching && !isFetchingNextPage && !isRefetching ? (
|
|
43
|
+
<KContainer.View flex center>
|
|
44
|
+
<ActivityIndicator />
|
|
45
|
+
</KContainer.View>
|
|
46
|
+
) : (
|
|
47
|
+
<KContainer.FlatList
|
|
48
|
+
data={dataFlatten}
|
|
49
|
+
renderItem={renderItem}
|
|
50
|
+
keyExtractor={keyExtractor}
|
|
51
|
+
onEndReached={onEndReached}
|
|
52
|
+
refreshing={isRefetching}
|
|
53
|
+
onRefresh={refetch}
|
|
54
|
+
contentContainerStyle={styles.contentContainer}
|
|
55
|
+
/>
|
|
56
|
+
)}
|
|
57
|
+
</KContainer.Page>
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const styles = StyleSheet.create({
|
|
62
|
+
contentContainer: {
|
|
63
|
+
paddingHorizontal: KSpacingValue['0.75rem'],
|
|
64
|
+
},
|
|
65
|
+
});
|
|
@@ -1,38 +1,56 @@
|
|
|
1
1
|
import { memo, useCallback, useState } from 'react';
|
|
2
2
|
import { StyleSheet } from 'react-native';
|
|
3
3
|
import { TabView } from 'react-native-tab-view';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
KContainer,
|
|
6
|
+
KImage,
|
|
7
|
+
KLabel,
|
|
8
|
+
KColors,
|
|
9
|
+
KRadiusValue,
|
|
10
|
+
KSpacingValue,
|
|
11
|
+
} from '@droppii/libs';
|
|
5
12
|
import { MessagesTab } from './MessagesTab';
|
|
13
|
+
import { trans } from '../../translation';
|
|
14
|
+
import { CommunityTab } from './CommunityTab';
|
|
6
15
|
|
|
7
16
|
interface InboxProps {
|
|
8
17
|
onPressThread?: (item: string) => void;
|
|
9
18
|
onPressSearch?: () => void;
|
|
10
19
|
onPressEdit?: () => void;
|
|
11
20
|
onPressContact?: () => void;
|
|
21
|
+
onPressGroup?: (groupId: string) => void;
|
|
12
22
|
}
|
|
13
23
|
|
|
14
24
|
type TabRoute = { key: string; title: string };
|
|
15
25
|
|
|
26
|
+
const TabRoutes: TabRoute[] = [
|
|
27
|
+
{ key: 'messages', title: trans('messages') },
|
|
28
|
+
{ key: 'community', title: trans('community') },
|
|
29
|
+
];
|
|
30
|
+
|
|
16
31
|
const Inbox = memo(
|
|
17
32
|
({
|
|
18
33
|
onPressThread,
|
|
19
34
|
onPressSearch,
|
|
20
35
|
onPressEdit,
|
|
21
36
|
onPressContact,
|
|
37
|
+
onPressGroup,
|
|
22
38
|
}: InboxProps) => {
|
|
23
39
|
const [index, setIndex] = useState(0);
|
|
24
|
-
const [routes] = useState<TabRoute[]>(
|
|
25
|
-
{ key: 'messages', title: 'Tin nhắn' },
|
|
26
|
-
]);
|
|
40
|
+
const [routes] = useState<TabRoute[]>(TabRoutes);
|
|
27
41
|
|
|
28
42
|
const renderScene = useCallback(
|
|
29
43
|
({ route }: { route: TabRoute }) => {
|
|
30
|
-
|
|
31
|
-
|
|
44
|
+
switch (route.key) {
|
|
45
|
+
case 'messages':
|
|
46
|
+
return <MessagesTab onPressThread={onPressThread} />;
|
|
47
|
+
case 'community':
|
|
48
|
+
return <CommunityTab onPressGroup={onPressGroup} />;
|
|
49
|
+
default:
|
|
50
|
+
return null;
|
|
32
51
|
}
|
|
33
|
-
return null;
|
|
34
52
|
},
|
|
35
|
-
[onPressThread]
|
|
53
|
+
[onPressThread, onPressGroup]
|
|
36
54
|
);
|
|
37
55
|
|
|
38
56
|
const renderTabBar = useCallback(
|
|
@@ -46,24 +64,18 @@ const Inbox = memo(
|
|
|
46
64
|
<KContainer.Touchable
|
|
47
65
|
key={route.key}
|
|
48
66
|
onPress={() => setIndex(i)}
|
|
49
|
-
paddingV="0.75rem"
|
|
50
|
-
marginR="1rem"
|
|
51
67
|
style={styles.tabItem}
|
|
52
68
|
activeOpacity={0.7}
|
|
53
69
|
>
|
|
54
70
|
<KLabel.Text
|
|
55
71
|
typo="TextNmBold"
|
|
56
72
|
color={
|
|
57
|
-
isActive
|
|
58
|
-
? KColors.palette.primary.w400
|
|
59
|
-
: KColors.palette.gray.w500
|
|
73
|
+
isActive ? KColors.primary.normal : KColors.gray.light
|
|
60
74
|
}
|
|
61
75
|
>
|
|
62
76
|
{route.title}
|
|
63
77
|
</KLabel.Text>
|
|
64
|
-
{isActive &&
|
|
65
|
-
<KContainer.View style={styles.activeIndicator} />
|
|
66
|
-
)}
|
|
78
|
+
{isActive && <KContainer.View style={styles.indicator} />}
|
|
67
79
|
</KContainer.Touchable>
|
|
68
80
|
);
|
|
69
81
|
})}
|
|
@@ -77,10 +89,9 @@ const Inbox = memo(
|
|
|
77
89
|
activeOpacity={0.7}
|
|
78
90
|
>
|
|
79
91
|
<KImage.VectorIcons
|
|
80
|
-
name="
|
|
81
|
-
provider="MaterialCommunityIcons"
|
|
92
|
+
name="search-o"
|
|
82
93
|
size={24}
|
|
83
|
-
color={KColors.
|
|
94
|
+
color={KColors.primary.normal}
|
|
84
95
|
/>
|
|
85
96
|
</KContainer.Touchable>
|
|
86
97
|
<KContainer.Touchable
|
|
@@ -89,10 +100,9 @@ const Inbox = memo(
|
|
|
89
100
|
activeOpacity={0.7}
|
|
90
101
|
>
|
|
91
102
|
<KImage.VectorIcons
|
|
92
|
-
name="
|
|
93
|
-
provider="MaterialCommunityIcons"
|
|
103
|
+
name="plus-circle-o"
|
|
94
104
|
size={24}
|
|
95
|
-
color={KColors.
|
|
105
|
+
color={KColors.primary.normal}
|
|
96
106
|
/>
|
|
97
107
|
</KContainer.Touchable>
|
|
98
108
|
<KContainer.Touchable
|
|
@@ -101,10 +111,9 @@ const Inbox = memo(
|
|
|
101
111
|
activeOpacity={0.7}
|
|
102
112
|
>
|
|
103
113
|
<KImage.VectorIcons
|
|
104
|
-
name="
|
|
105
|
-
provider="MaterialCommunityIcons"
|
|
114
|
+
name="user-three-o"
|
|
106
115
|
size={24}
|
|
107
|
-
color={KColors.
|
|
116
|
+
color={KColors.primary.normal}
|
|
108
117
|
/>
|
|
109
118
|
</KContainer.Touchable>
|
|
110
119
|
</KContainer.View>
|
|
@@ -114,13 +123,13 @@ const Inbox = memo(
|
|
|
114
123
|
);
|
|
115
124
|
|
|
116
125
|
return (
|
|
117
|
-
<KContainer.Page flex edges={['top'
|
|
126
|
+
<KContainer.Page flex edges={['top']}>
|
|
118
127
|
<TabView
|
|
119
128
|
navigationState={{ index, routes }}
|
|
120
129
|
renderScene={renderScene}
|
|
121
130
|
renderTabBar={renderTabBar}
|
|
122
131
|
onIndexChange={setIndex}
|
|
123
|
-
|
|
132
|
+
lazy
|
|
124
133
|
/>
|
|
125
134
|
</KContainer.Page>
|
|
126
135
|
);
|
|
@@ -133,25 +142,28 @@ export default Inbox;
|
|
|
133
142
|
|
|
134
143
|
const styles = StyleSheet.create({
|
|
135
144
|
tabBar: {
|
|
136
|
-
borderBottomWidth:
|
|
137
|
-
borderBottomColor: KColors.
|
|
138
|
-
|
|
145
|
+
borderBottomWidth: 1,
|
|
146
|
+
borderBottomColor: KColors.border.light,
|
|
147
|
+
paddingTop: 2,
|
|
139
148
|
},
|
|
140
149
|
tabItem: {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
150
|
+
height: 40,
|
|
151
|
+
marginHorizontal: KSpacingValue['0.75rem'],
|
|
152
|
+
justifyContent: 'center',
|
|
153
|
+
alignItems: 'center',
|
|
144
154
|
},
|
|
145
|
-
|
|
155
|
+
indicator: {
|
|
156
|
+
height: 3,
|
|
157
|
+
backgroundColor: KColors.primary.normal,
|
|
158
|
+
width: '100%',
|
|
159
|
+
borderRadius: KRadiusValue.x,
|
|
146
160
|
position: 'absolute',
|
|
147
|
-
bottom:
|
|
161
|
+
bottom: -1,
|
|
148
162
|
left: 0,
|
|
149
163
|
right: 0,
|
|
150
|
-
height: 3,
|
|
151
|
-
borderRadius: 4,
|
|
152
|
-
backgroundColor: KColors.palette.primary.w400,
|
|
153
164
|
},
|
|
154
165
|
actionGroup: {
|
|
155
|
-
gap:
|
|
166
|
+
gap: KSpacingValue['0.25rem'],
|
|
167
|
+
paddingRight: KSpacingValue['0.5rem'],
|
|
156
168
|
},
|
|
157
169
|
});
|
|
@@ -163,7 +163,15 @@ const i18nKey: Record<string, string> = {
|
|
|
163
163
|
'search_conversation:empty_hint': 'Bạn có thể tìm kiếm theo liên hệ',
|
|
164
164
|
'view_all': 'Xem tất cả',
|
|
165
165
|
'search_message:revoked_message': 'Tin nhắn đã được thu hồi',
|
|
166
|
+
'chat:no_permission': 'Bạn không có quyền này',
|
|
166
167
|
'chat:no_send_permission': 'Bạn không có quyền gửi tin nhắn',
|
|
168
|
+
'community': 'Cộng đồng',
|
|
169
|
+
'group:member_count': '{{count}} thành viên',
|
|
170
|
+
'group:access': 'Truy cập',
|
|
171
|
+
'group:join': 'Tham gia',
|
|
172
|
+
'group:not_in_group': 'Bạn cần tham gia nhóm để gửi tin nhắn',
|
|
173
|
+
'group:cannot_send_message': 'Bạn không thể gửi tin nhắn vào nhóm này',
|
|
174
|
+
'group:joined_group': 'Đã tham gia nhóm {{groupName}}',
|
|
167
175
|
};
|
|
168
176
|
|
|
169
177
|
export default {
|