@messenger-box/platform-mobile 10.0.3-alpha.5 → 10.0.3-alpha.54

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.
Files changed (98) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/lib/compute.js +2 -3
  3. package/lib/compute.js.map +1 -1
  4. package/lib/index.js.map +1 -1
  5. package/lib/queries/inboxQueries.js +65 -0
  6. package/lib/queries/inboxQueries.js.map +1 -0
  7. package/lib/routes.json +2 -3
  8. package/lib/screens/inbox/DialogMessages.js +1 -1
  9. package/lib/screens/inbox/DialogMessages.js.map +1 -1
  10. package/lib/screens/inbox/DialogThreadMessages.js +4 -8
  11. package/lib/screens/inbox/DialogThreadMessages.js.map +1 -1
  12. package/lib/screens/inbox/DialogThreads.js +57 -12
  13. package/lib/screens/inbox/DialogThreads.js.map +1 -1
  14. package/lib/screens/inbox/Inbox.js +1 -1
  15. package/lib/screens/inbox/Inbox.js.map +1 -1
  16. package/lib/screens/inbox/components/CachedImage/consts.js +1 -1
  17. package/lib/screens/inbox/components/CachedImage/consts.js.map +1 -1
  18. package/lib/screens/inbox/components/CachedImage/index.js +168 -46
  19. package/lib/screens/inbox/components/CachedImage/index.js.map +1 -1
  20. package/lib/screens/inbox/components/DialogItem.js +169 -0
  21. package/lib/screens/inbox/components/DialogItem.js.map +1 -0
  22. package/lib/screens/inbox/components/GiftedChatInboxComponent.js +313 -0
  23. package/lib/screens/inbox/components/GiftedChatInboxComponent.js.map +1 -0
  24. package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js +147 -31
  25. package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js.map +1 -1
  26. package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js +6 -1
  27. package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js.map +1 -1
  28. package/lib/screens/inbox/components/SubscriptionHandler.js +24 -0
  29. package/lib/screens/inbox/components/SubscriptionHandler.js.map +1 -0
  30. package/lib/screens/inbox/components/ThreadsViewItem.js +66 -55
  31. package/lib/screens/inbox/components/ThreadsViewItem.js.map +1 -1
  32. package/lib/screens/inbox/config/config.js +2 -2
  33. package/lib/screens/inbox/config/config.js.map +1 -1
  34. package/lib/screens/inbox/containers/ConversationView.js +1111 -434
  35. package/lib/screens/inbox/containers/ConversationView.js.map +1 -1
  36. package/lib/screens/inbox/containers/Dialogs.js +193 -80
  37. package/lib/screens/inbox/containers/Dialogs.js.map +1 -1
  38. package/lib/screens/inbox/containers/ThreadConversationView.js +725 -216
  39. package/lib/screens/inbox/containers/ThreadConversationView.js.map +1 -1
  40. package/lib/screens/inbox/containers/ThreadsView.js +83 -50
  41. package/lib/screens/inbox/containers/ThreadsView.js.map +1 -1
  42. package/lib/screens/inbox/hooks/useInboxMessages.js +31 -0
  43. package/lib/screens/inbox/hooks/useInboxMessages.js.map +1 -0
  44. package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js +108 -0
  45. package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js.map +1 -0
  46. package/lib/screens/inbox/workflow/dialog-threads-xstate.js +151 -0
  47. package/lib/screens/inbox/workflow/dialog-threads-xstate.js.map +1 -0
  48. package/package.json +4 -4
  49. package/src/compute.ts +5 -6
  50. package/src/index.ts +2 -0
  51. package/src/navigation/InboxNavigation.tsx +3 -3
  52. package/src/queries/inboxQueries.ts +299 -0
  53. package/src/queries/index.d.ts +2 -0
  54. package/src/queries/index.ts +1 -0
  55. package/src/screens/inbox/DialogMessages.tsx +1 -1
  56. package/src/screens/inbox/DialogThreadMessages.tsx +7 -14
  57. package/src/screens/inbox/DialogThreads.tsx +55 -61
  58. package/src/screens/inbox/Inbox.tsx +1 -1
  59. package/src/screens/inbox/components/Actionsheet.tsx +30 -0
  60. package/src/screens/inbox/components/CachedImage/consts.ts +4 -3
  61. package/src/screens/inbox/components/CachedImage/index.tsx +232 -61
  62. package/src/screens/inbox/components/DialogItem.tsx +306 -0
  63. package/src/screens/inbox/components/DialogsHeader.tsx +6 -13
  64. package/src/screens/inbox/components/DialogsListItem.tsx +262 -198
  65. package/src/screens/inbox/components/ExpandableInput.tsx +460 -0
  66. package/src/screens/inbox/components/ExpandableInputActionSheet.tsx +518 -0
  67. package/src/screens/inbox/components/GiftedChatInboxComponent.tsx +411 -0
  68. package/src/screens/inbox/components/ServiceDialogsListItem.tsx +337 -194
  69. package/src/screens/inbox/components/SlackInput.tsx +23 -0
  70. package/src/screens/inbox/components/SlackMessageContainer/SlackBubble.tsx +233 -23
  71. package/src/screens/inbox/components/SlackMessageContainer/SlackMessage.tsx +1 -1
  72. package/src/screens/inbox/components/SmartLoader.tsx +61 -0
  73. package/src/screens/inbox/components/SubscriptionHandler.tsx +41 -0
  74. package/src/screens/inbox/components/SupportServiceDialogsListItem.tsx +53 -55
  75. package/src/screens/inbox/components/ThreadsViewItem.tsx +178 -285
  76. package/src/screens/inbox/components/workflow/dialogs-list-item-xstate.ts +145 -0
  77. package/src/screens/inbox/components/workflow/service-dialogs-list-item-xstate.ts +159 -0
  78. package/src/screens/inbox/config/config.ts +2 -2
  79. package/src/screens/inbox/containers/ConversationView.tsx +1843 -702
  80. package/src/screens/inbox/containers/ConversationView.tsx.bk +1467 -0
  81. package/src/screens/inbox/containers/Dialogs.tsx +402 -204
  82. package/src/screens/inbox/containers/SupportServiceDialogs.tsx +4 -4
  83. package/src/screens/inbox/containers/ThreadConversationView.tsx +1350 -319
  84. package/src/screens/inbox/containers/ThreadsView.tsx +105 -193
  85. package/src/screens/inbox/containers/workflow/apollo/handleResult.ts +20 -0
  86. package/src/screens/inbox/containers/workflow/conversation-xstate.ts +313 -0
  87. package/src/screens/inbox/containers/workflow/dialogs-xstate.ts +196 -0
  88. package/src/screens/inbox/containers/workflow/thread-conversation-xstate.ts +401 -0
  89. package/src/screens/inbox/hooks/useInboxMessages.ts +34 -0
  90. package/src/screens/inbox/hooks/useSafeDialogThreadsMachine.ts +136 -0
  91. package/src/screens/inbox/index.ts +37 -0
  92. package/src/screens/inbox/machines/threadsMachine.ts +147 -0
  93. package/src/screens/inbox/workflow/dialog-threads-xstate.ts +163 -0
  94. package/tsconfig.json +11 -54
  95. package/lib/screens/inbox/components/DialogsListItem.js +0 -171
  96. package/lib/screens/inbox/components/DialogsListItem.js.map +0 -1
  97. package/lib/screens/inbox/components/ServiceDialogsListItem.js +0 -171
  98. package/lib/screens/inbox/components/ServiceDialogsListItem.js.map +0 -1
@@ -2,50 +2,47 @@ import React, { useMemo } from 'react';
2
2
  import {
3
3
  VStack,
4
4
  Text,
5
- Image,
6
5
  Pressable,
7
6
  HStack,
8
7
  Box,
9
- AvatarGroup,
10
8
  Avatar,
11
9
  AvatarFallbackText,
12
10
  AvatarImage,
13
- AvatarBadge,
14
- View,
15
11
  Button,
16
12
  ButtonText,
13
+ Icon,
14
+ Badge,
15
+ BadgeText,
16
+ Link,
17
+ LinkText,
17
18
  } from '@admin-layout/gluestack-ui-mobile';
18
19
  import { format, isToday, isYesterday } from 'date-fns';
19
20
  import { useFocusEffect } from '@react-navigation/native';
20
21
  import { IChannel, IUserAccount } from 'common';
21
- import {
22
- useThreadMessagesQuery,
23
- useMessagesQuery,
24
- useUserAccountQuery,
25
- useOnThreadChatMessageAddedSubscription,
26
- useOnThreadCreatedUpdatedSubscription,
27
- } from 'common/lib/generated/generated.js';
28
22
  import { startCase } from 'lodash-es';
23
+ import colors from 'tailwindcss/colors';
24
+ import { useSelector } from 'react-redux';
25
+ import { userSelector } from '@adminide-stack/user-auth0-client';
29
26
 
30
- const createdAtText = (value: string) => {
27
+ const timeFormat = (value: string) => {
31
28
  if (!value) return '';
32
29
  let date = new Date(value);
33
- if (isToday(date)) return 'Today';
34
- if (isYesterday(date)) return 'Yesterday';
35
- return format(new Date(value), 'MMM dd, yyyy');
30
+ if (isToday(date)) return format(date, 'h:mm a').toUpperCase();
31
+ return format(date, 'MMM do').toUpperCase();
36
32
  };
37
33
 
38
34
  export interface IDialogListChannel extends IChannel {
39
35
  users: IUserAccount[];
40
36
  }
41
37
 
42
- export interface IDialogListItemProps {
43
- currentUser?: any;
44
- users?: any;
45
- thread?: any;
46
- onOpen: (id: any, title: any, postParentId?: any) => void;
47
- role?: any;
48
- setData?: any;
38
+ export interface ThreadViewItemProps {
39
+ id: string;
40
+ post: any;
41
+ channel: any;
42
+ replies: any[];
43
+ onPress: (id: any, title: any, postParentId?: any) => void;
44
+ channelId?: string;
45
+ channelsDetail?: any;
49
46
  }
50
47
 
51
48
  /**
@@ -53,287 +50,183 @@ export interface IDialogListItemProps {
53
50
  * - Get Reservation info: reservation date, status
54
51
  * - Add ability to get property information: name, logo
55
52
  */
56
- export const ThreadViewItemComponent: React.FC<IDialogListItemProps> = function DialogsListItem({
57
- currentUser,
58
- // users,
59
- thread,
60
- onOpen,
61
- role,
62
- setData,
53
+ export const ThreadViewItemComponent: React.FC<ThreadViewItemProps> = function ThreadViewItem({
54
+ id,
55
+ post,
56
+ channel,
57
+ replies,
58
+ onPress,
59
+ channelId,
60
+ channelsDetail,
63
61
  }) {
64
- // const { data: threadCreatedUpdated } = useOnThreadCreatedUpdatedSubscription({
65
- // variables: {
66
- // channelId: thread?.channel?.id?.toString(),
67
- // postParentId: thread?.post?.id?.toString(),
68
- // },
69
- // });
70
-
71
- useFocusEffect(
72
- React.useCallback(() => {
73
- // Do something when the screen is focused
74
- return () => {
75
- // Do something when the screen is unfocused
76
- // Useful for cleanup functions
77
- };
78
- }, []),
79
- );
80
-
81
- const threadPostReply = React.useMemo(() => {
82
- if (!thread?.replies) return null;
83
- return thread?.replies;
84
- }, [thread]);
62
+ const currentUser = useSelector(userSelector);
85
63
 
86
- // React.useEffect(() => {
87
- // if (threadCreatedUpdated?.threadCreatedUpdated?.data) setData(threadCreatedUpdated?.threadCreatedUpdated?.data);
88
- // }, [threadCreatedUpdated?.threadCreatedUpdated]);
64
+ // Prepare thread replies for display
65
+ const threadReplies = useMemo(() => {
66
+ return replies || [];
67
+ }, [replies]);
89
68
 
90
- // const threadPostReply = React.useMemo(() => {
91
- // if (!thread?.replies) return null;
92
- // if (threadCreatedUpdated?.threadCreatedUpdated?.data?.replies?.length) {
93
- // return threadCreatedUpdated?.threadCreatedUpdated?.data?.replies;
94
- // } else return thread?.replies;
95
- // }, [thread, threadCreatedUpdated]);
96
-
97
- // const lastMessage = useMemo(() => {
98
- // if (!threadPost) {
99
- // return null;
100
- // }
101
- // const replies = threadPost?.replies?.filter((p: any) => p?.message !== '') ?? [];
102
- // if (replies?.length) {
103
- // return replies[0];
104
- // // return replies[replies.length - 1];
105
- // } else {
106
- // const post = threadPost?.post ?? null;
107
- // return post ? post?.post : null;
108
- // }
109
- // }, [threadPost]);
69
+ if (!threadReplies || threadReplies.length === 0) {
70
+ return null;
71
+ }
110
72
 
111
- // const participants: any = React.useMemo(() => {
112
- // if (!thread?.participants?.length) return null;
113
- // return thread?.participants?.filter((u: any) => u?.user?.id !== currentUser?.id) ?? [];
114
- // }, [thread]);
73
+ // Get the last reply for the thread preview
74
+ const lastReply = threadReplies[0]; // Most recent reply should be first in the array
75
+ // Get total number of replies
76
+ const totalReplies = threadReplies.length;
115
77
 
116
- // const allParticipantsNames: any = React.useMemo(() => {
117
- // if (!participants?.length) return null;
118
- // return (
119
- // participants
120
- // ?.map((p: any) => {
121
- // return p?.user?.givenName + ' ' + p?.user?.familyName ?? '';
122
- // })
123
- // ?.join(', ') ?? ''
124
- // );
125
- // }, [participants]);
78
+ // Get the first user in the thread as the primary user
79
+ const primaryUser = channel?.users?.[0] || lastReply?.author;
80
+ const channelName = channel?.title || `${primaryUser?.givenName || ''} ${primaryUser?.familyName || ''}`;
126
81
 
127
- if (!threadPostReply || threadPostReply?.length == 0) {
128
- return <></>;
129
- }
82
+ // Determine if the current user is in the thread
83
+ const userIsInThread = channel?.users?.some((user: any) => user.id === currentUser?.id);
130
84
 
131
85
  return (
132
- <VStack
133
- space={'sm'}
134
- py={'$2'}
135
- px={'$2'}
136
- borderWidth={'$1'}
137
- borderRadius={'$md'}
138
- borderColor={'$trueGray200'}
139
- flex={1}
140
- $dark-borderColor="$white"
141
- $dark-backgroundColor="$white"
142
- $light-backgroundColor="$white"
86
+ <Pressable
87
+ onPress={() => onPress(channel?.id, 'Thread', post?.id)}
88
+ style={{
89
+ marginVertical: 5,
90
+ backgroundColor: 'white',
91
+ borderRadius: 10,
92
+ paddingVertical: 5,
93
+ elevation: 1,
94
+ shadowColor: '#000',
95
+ shadowOffset: { width: 0, height: 1 },
96
+ shadowOpacity: 0.1,
97
+ shadowRadius: 2,
98
+ }}
143
99
  >
144
- <HStack
145
- // px={2}
146
- // pl={3}
147
- py={'$2'}
148
- space={'sm'}
149
- w={'100%'}
150
- flex={1}
151
- justifyContent={'space-between'}
152
- alignItems={'center'}
153
- >
154
- <Box flex={1}>
155
- {/* <HStack flex={1} space={5} py={2} alignItems={'baseline'}>
156
- <Box>
157
- <Avatar.Badge size={4} left={0} zIndex={1} bg="green.800" />
158
- </Box>
159
- <Box>
160
- <Text color="gray.600" fontSize="lg" flexWrap={'wrap'} fontWeight="semibold">
161
- {allParticipantsNames || ''}
162
- </Text>
163
- </Box>
100
+ <Box className="mb-3">
101
+ <VStack space="md">
102
+ {/* Thread header with green dot and users */}
103
+ {/* <HStack space="sm" className="px-4 items-center">
104
+ <Box
105
+ className="bg-green-500 rounded-full"
106
+ style={{ width: 8, height: 8 }}
107
+ />
108
+ <Text className="text-base text-gray-900">{channelName}</Text>
164
109
  </HStack> */}
165
- <HStack space={'sm'} flex={1} justifyContent={'center'} alignItems={'center'}>
166
- <Box flex={1}>
167
- {/* <HStack space={2} py={2}>
168
- <Box>
110
+
111
+ {/* Thread members */}
112
+ <Text className="text-sm font-medium text-gray-600 px-4 pt-2">
113
+ {channel?.users?.map((user: any) => user?.givenName || user?.username)?.join(', ')}
114
+ </Text>
115
+
116
+ {/* Thread messages preview - show up to 3 most recent messages */}
117
+ {threadReplies.slice(0, 3).map((reply: any, index: number) => {
118
+ // Group consecutive messages from the same user
119
+ const previousReply = index > 0 ? threadReplies.slice(0, 3)[index - 1] : null;
120
+ const isConsecutiveReply = previousReply && previousReply.author?.id === reply.author?.id;
121
+
122
+ return (
123
+ <HStack key={reply.id || index} space="md" className="px-4 py-1">
124
+ {!isConsecutiveReply ? (
169
125
  <Avatar
170
- bg={'transparent'}
171
- size={8}
172
- _image={{ borderRadius: 6, borderWidth: 2, borderColor: '#fff' }}
173
- source={{
174
- uri: thread?.post?.author?.picture,
126
+ size="md"
127
+ style={{
128
+ width: 40,
129
+ height: 40,
130
+ backgroundColor:
131
+ reply?.author?.id === currentUser?.id ? '#2EB67D' : '#E8A54A',
175
132
  }}
176
133
  >
177
- {startCase(thread?.post?.author?.username?.charAt(0))}
134
+ <AvatarFallbackText>
135
+ {startCase(reply?.author?.username?.charAt(0) || 'U')}
136
+ </AvatarFallbackText>
137
+ {reply?.author?.picture && (
138
+ <AvatarImage
139
+ alt={reply?.author?.username || 'User'}
140
+ source={{
141
+ uri: reply?.author?.picture,
142
+ }}
143
+ />
144
+ )}
178
145
  </Avatar>
179
- </Box>
180
- <Box>
181
- <HStack space={4}>
182
- <Text>
183
- {thread?.post?.author?.givenName + ' ' + thread?.post?.author?.familyName ??
184
- ''}
185
- </Text>
186
- <Text color="gray.500">
187
- {thread?.post ? createdAtText(thread?.post?.createdAt) : ''}
188
- </Text>
189
- </HStack>
190
- <Text color="gray.600" noOfLines={2}>
191
- {thread?.post?.message ?? ''}
192
- </Text>
193
- {!thread?.replies?.length && (
194
- <Button
195
- size={'xs'}
196
- w={150}
197
- variant={'outline'}
198
- _text={{ fontSize: 12, color: '#000' }}
199
- onPress={() =>
200
- onOpen(thread?.channel?.id, thread?.channel?.title, thread?.post?.id)
201
- }
202
- >
203
- Reply
204
- </Button>
146
+ ) : (
147
+ <Box style={{ width: 40 }} />
148
+ )}
149
+
150
+ <VStack space="xs" className="flex-1">
151
+ {!isConsecutiveReply && (
152
+ <HStack space="sm" className="items-center">
153
+ <Text className="font-bold text-gray-900">
154
+ {reply?.author?.givenName || reply?.author?.username || 'User'}
155
+ </Text>
156
+ <Text className="text-xs text-gray-500">
157
+ {timeFormat(reply?.createdAt)}
158
+ </Text>
159
+ </HStack>
205
160
  )}
206
- </Box>
207
- </HStack> */}
208
- {threadPostReply?.length > 0 && (
209
- <>
210
- {threadPostReply
211
- ?.slice(0, 2)
212
- ?.reverse()
213
- ?.map((reply: any, index: any) => (
214
- <HStack key={index} space={'sm'} pb={'$2'} pt={'$1'}>
215
- <Box>
216
- <Avatar
217
- key={'thread-view-key-' + index}
218
- bg={'transparent'}
219
- size={'md'}
220
- top={'$0'}
221
- right={'$0'}
222
- zIndex={1}
223
- >
224
- <AvatarFallbackText>
225
- {' '}
226
- {startCase(reply?.author?.username?.charAt(0))}
227
- </AvatarFallbackText>
228
- <AvatarImage
229
- alt="image"
230
- style={{
231
- borderRadius: 6,
232
- borderWidth: 2,
233
- borderColor: '#fff',
234
- }}
235
- source={{
236
- uri: reply?.author?.picture,
237
- }}
238
- />
239
- </Avatar>
240
- </Box>
241
- <Box>
242
- <HStack space={'md'}>
243
- <Text>
244
- {reply?.author?.givenName ?? '' ?? ''}{' '}
245
- {reply?.author?.familyName ?? '' ?? ''}
246
- {/* {lastMessage?.author?.givenName +
247
- ' ' +
248
- lastMessage?.author?.familyName ?? ''} */}
249
- </Text>
250
- <Text color="$trueGray500">
251
- {reply?.createdAt ? createdAtText(reply?.createdAt) : ''}
252
- {/* {lastMessage ? createdAtText(lastMessage?.createdAt) : ''} */}
253
- </Text>
254
- </HStack>
255
- <VStack space={'sm'}>
256
- {reply?.message && (
257
- <Text color="$trueGray600" numberOfLines={2}>
258
- {reply?.message.length < 70
259
- ? `${reply?.message}`
260
- : `${reply?.message.substring(0, 68)}....`}
261
- </Text>
262
- )}
263
- {/* <Text color="gray.600" noOfLines={2}>
264
- {reply?.message
265
- ? reply?.message.length < 70
266
- ? `${reply?.message}`
267
- : `${reply?.message.substring(0, 68)}....`
268
- : ''}
269
- </Text> */}
270
161
 
271
- <>
272
- {reply?.files?.data?.length > 0 &&
273
- reply?.files?.data?.map((f: any, index: any) => (
274
- <Box>
275
- <Avatar
276
- key={'thread-view-other-key-' + index}
277
- bg={'transparent'}
278
- size={'md'}
279
- >
280
- <AvatarFallbackText> I</AvatarFallbackText>
281
- <AvatarImage
282
- alt="image"
283
- style={{
284
- borderRadius: 6,
285
- borderWidth: 2,
286
- borderColor: '#fff',
287
- }}
288
- source={{
289
- uri: f?.url,
290
- }}
291
- />
292
- </Avatar>
293
- </Box>
294
- ))}
295
- </>
296
- </VStack>
162
+ {reply?.message && (
163
+ <Text color={colors.gray[700]} numberOfLines={2} className="text-base">
164
+ {reply?.message}
165
+ {reply?.edited && <Text className="text-xs text-gray-500"> (edited)</Text>}
166
+ </Text>
167
+ )}
297
168
 
298
- {(threadPostReply?.length == 1 || index !== 0) && (
299
- <Button
300
- size={'xs'}
301
- w={150}
302
- variant={'outline'}
303
- onPress={() =>
304
- onOpen(
305
- thread?.channel?.id,
306
- thread?.channel?.title,
307
- thread?.post?.id,
308
- )
309
- }
310
- >
311
- <ButtonText style={{ fontSize: 12, color: '#000' }}>
312
- Reply
313
- </ButtonText>
314
- </Button>
315
- )}
169
+ {reply.email && <Text className="text-blue-500">{reply.email}</Text>}
170
+
171
+ {reply?.files?.data?.length > 0 && (
172
+ <HStack space="sm" className="my-1">
173
+ {reply?.files?.data?.map((file: any, fileIndex: number) => (
174
+ <Box
175
+ key={fileIndex}
176
+ className="overflow-hidden"
177
+ style={{ width: 80, height: 80 }}
178
+ >
179
+ <AvatarImage
180
+ alt="attachment"
181
+ className="rounded-none border-none"
182
+ style={{
183
+ width: '100%',
184
+ height: '100%',
185
+ }}
186
+ source={{
187
+ uri: file?.url,
188
+ }}
189
+ />
316
190
  </Box>
317
- </HStack>
318
- ))}
319
- </>
320
- )}
321
- </Box>
322
- </HStack>
323
- </Box>
324
- </HStack>
325
- {/* <HStack>
326
- <Box flex={0.06} alignItems={'flex-start'}></Box>
327
- <Button
328
- size={'xs'}
329
- variant={'outline'}
330
- _text={{ fontSize: 12, color: '#000' }}
331
- onPress={() => onOpen(thread?.channel?.id, thread?.channel?.title, postParentId)}
332
- >
333
- Reply
334
- </Button>
335
- </HStack> */}
336
- </VStack>
191
+ ))}
192
+ </HStack>
193
+ )}
194
+ </VStack>
195
+ </HStack>
196
+ );
197
+ })}
198
+
199
+ {/* Show more replies indicator */}
200
+ {totalReplies > 3 && (
201
+ <HStack className="px-4 items-center" space="sm">
202
+ <Box style={{ width: 40 }} />
203
+ <Link onPress={() => onPress(channel?.id, 'Thread', post?.id)}>
204
+ <LinkText className="text-blue-600 mt-1">
205
+ {totalReplies - 3} more {totalReplies - 3 === 1 ? 'reply' : 'replies'}
206
+ </LinkText>
207
+ </Link>
208
+ </HStack>
209
+ )}
210
+
211
+ {/* Reply button */}
212
+ <Box className="px-4 pb-2">
213
+ <Button
214
+ size="sm"
215
+ className="self-start rounded-full"
216
+ variant="outline"
217
+ style={{
218
+ borderColor: '#E2E8F0',
219
+ paddingHorizontal: 16,
220
+ paddingVertical: 6,
221
+ }}
222
+ onPress={() => onPress(channel?.id, 'Thread', post?.id)}
223
+ >
224
+ <ButtonText style={{ fontSize: 14, color: colors.gray[800] }}>Reply</ButtonText>
225
+ </Button>
226
+ </Box>
227
+ </VStack>
228
+ </Box>
229
+ </Pressable>
337
230
  );
338
231
  };
339
232