movius-chats 1.0.0 → 1.2.0

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 (25) hide show
  1. package/README.md +102 -89
  2. package/lib/commonjs/assets/Icons/ArrowBack2RoundedIcon.js +1 -1
  3. package/lib/commonjs/assets/Icons/ArrowBack2RoundedIcon.js.map +1 -1
  4. package/lib/commonjs/components/ChatBubble/ChatBubble.js +1 -1
  5. package/lib/commonjs/components/ChatBubble/ChatBubble.js.map +1 -1
  6. package/lib/commonjs/components/ChatBubble/MessageContent.js +1 -1
  7. package/lib/commonjs/components/ChatBubble/MessageContent.js.map +1 -1
  8. package/lib/commonjs/components/TypingComponent/TypingIndicator.js +1 -1
  9. package/lib/commonjs/components/TypingComponent/TypingIndicator.js.map +1 -1
  10. package/lib/module/assets/Icons/ArrowBack2RoundedIcon.js +1 -1
  11. package/lib/module/assets/Icons/ArrowBack2RoundedIcon.js.map +1 -1
  12. package/lib/module/components/ChatBubble/ChatBubble.js +1 -1
  13. package/lib/module/components/ChatBubble/ChatBubble.js.map +1 -1
  14. package/lib/module/components/ChatBubble/MessageContent.js +1 -1
  15. package/lib/module/components/ChatBubble/MessageContent.js.map +1 -1
  16. package/lib/module/components/TypingComponent/TypingIndicator.js +1 -1
  17. package/lib/module/components/TypingComponent/TypingIndicator.js.map +1 -1
  18. package/lib/typescript/assets/Icons/ArrowBack2RoundedIcon.d.ts +1 -1
  19. package/lib/typescript/types/index.d.ts +3 -2
  20. package/package.json +1 -1
  21. package/src/assets/Icons/ArrowBack2RoundedIcon.tsx +5 -5
  22. package/src/components/ChatBubble/ChatBubble.tsx +1 -1
  23. package/src/components/ChatBubble/MessageContent.tsx +5 -2
  24. package/src/components/TypingComponent/TypingIndicator.tsx +1 -1
  25. package/src/types/index.ts +3 -2
package/README.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  A highly customizable, feature-rich chats interface component for React Native applications. Built with performance and flexibility in mind, this component provides a complete solution for implementing chats functionality in your mobile applications.
4
4
 
5
+ ## ⚠️ Important Implementation Notes
6
+
7
+ - **Native Rebuild Required**: This package uses native modules that require rebuilding your application after installation.
8
+ - **Expo Go Compatibility**: This package is **not compatible** with Expo Go due to its native dependencies. You must use a development build or eject from Expo Go to use this library.
9
+ - **Development Build**: For Expo users, you'll need to create a [Development Build](https://docs.expo.dev/develop/development-builds/introduction/) to use this package.
10
+
5
11
  ## Features
6
12
 
7
13
  - 🚀 Full TypeScript support
@@ -16,6 +22,9 @@ A highly customizable, feature-rich chats interface component for React Native a
16
22
  - 💬 Message status indicators (sent, delivered, read)
17
23
  - 🎯 Custom component injection
18
24
  - 🔧 Comprehensive styling API
25
+ - 🔄 Lazy loading for media messages
26
+ - 📡 Debounced typing indicators
27
+ - 🖼️ Avatar image caching
19
28
 
20
29
  ## Installation
21
30
 
@@ -47,10 +56,29 @@ module.exports = {
47
56
  };
48
57
  ```
49
58
 
59
+ ### Post-Installation Steps
60
+
61
+ After installing this package and its dependencies:
62
+
63
+ 1. **For React Native CLI Projects**:
64
+ ```bash
65
+ npx pod-install # For iOS
66
+ npx react-native run-android # Rebuild for Android
67
+ npx react-native run-ios # Rebuild for iOS
68
+ ```
69
+
70
+ 2. **For Expo Projects**:
71
+ ```bash
72
+ npx expo prebuild # Generate native code
73
+ npx expo run:android # Build and run on Android
74
+ npx expo run:ios # Build and run on iOS
75
+ ```
76
+
50
77
  ## Basic Usage
51
78
 
52
79
  ```typescript
53
- import { ChatScreen, Message } from 'movius-chats';
80
+ import ChatScreen from 'movius-chats';
81
+ import { Message } from 'movius-chats/lib/typescript/types';
54
82
  import { useState } from 'react';
55
83
 
56
84
  const App = () => {
@@ -87,86 +115,62 @@ const App = () => {
87
115
  | messages | Message[] | Yes | Array of message objects to display |
88
116
  | currentUserId | string | Yes | ID of the current user |
89
117
  | onSendMessage | (message: Omit<Message, "id" \| "time" \| "status">) => void | Yes | Callback when a message is sent |
90
-
91
- ### Message Type
92
-
93
- ```typescript
94
- interface Message {
95
- id: string;
96
- text?: string;
97
- image?: string;
98
- video?: string;
99
- audio?: string;
100
- senderId: string;
101
- time: string;
102
- status: "read" | "delivered" | "sent";
103
- senderName?: string;
104
- senderAvatar?: string;
105
- }
106
- ```
107
-
108
- ### Feature Flags
109
-
110
- | Prop | Type | Default | Description |
111
- |------|------|---------|-------------|
112
- | showAvatars | boolean | false | Show user avatars |
113
- | showUserNames | boolean | false | Display usernames above messages |
114
- | showEmojiButton | boolean | true | Show emoji picker button |
115
- | showAttachmentsButton | boolean | true | Show attachments button |
116
- | showCameraButton | boolean | true | Show camera access button |
117
- | showVoiceRecordButton | boolean | true | Show voice recording button |
118
- | showBubbleTail | boolean | true | Show message bubble tails |
119
- | showMessageStatus | boolean | true | Show message status indicators |
120
-
121
- ### Event Handlers
122
-
123
- | Prop | Type | Description |
124
- |------|------|-------------|
125
- | onMessageLongPress | (message: Message) => void | Callback for long-pressing a message |
126
- | onAttachmentPress | () => void | Callback for attachment button press |
127
- | onAudioRecordStart | () => void | Callback when audio recording starts |
128
- | onAudioRecordEnd | () => void | Callback when audio recording ends |
129
- | onCameraPress | () => void | Callback for camera button press |
130
- | onTypingStart | () => void | Callback when user starts typing |
131
- | onTypingEnd | () => void | Callback when user stops typing |
118
+ | onMessageLongPress | (message: Message) => void | No | Callback for long-pressing a message |
119
+ | onAttachmentPress | () => void | No | Callback for attachment button press |
120
+ | onAudioRecordStart | () => void | No | Callback when audio recording starts |
121
+ | onAudioRecordEnd | () => void | No | Callback when audio recording ends |
122
+ | onCameraPress | () => void | No | Callback for camera button press |
123
+ | onTypingStart | () => void | No | Callback when user starts typing |
124
+ | onTypingEnd | () => void | No | Callback when user stops typing |
125
+ | placeholder | string | No | Input placeholder text |
126
+ | typingUsers | Array<{ id: string; avatar: string; name: string }> | No | List of users who are typing |
132
127
 
133
128
  ### Theming
134
129
 
135
130
  The component supports extensive theming through the `theme` prop:
136
131
 
137
132
  ```typescript
138
- theme?: {
139
- colors?: {
140
- sentMessageTailColor?: string;
141
- receivedMessageTailColor?: string;
142
- timestamp?: string;
143
- inputsIconsColor?: string;
144
- sendIconsColor?: string;
145
- placeholderTextColor?: string;
146
- audioPlayIconColor?: string;
147
- audioPauseIconColor?: string;
148
- videoPlayIconColor?: string;
149
- };
150
- bubbleStyle?: {
151
- sent?: ViewStyle;
152
- received?: ViewStyle;
153
- // ... other bubble styles
154
- };
155
- messageStyle?: {
156
- textStyle?: TextStyle;
157
- // ... other message styles
158
- };
159
- inputStyles?: {
160
- inputSectionContainerStyle?: ViewStyle;
161
- // ... other input styles
133
+ theme?: {
134
+ colors?: {
135
+ sentMessageTailColor?: string;
136
+ receivedMessageTailColor?: string;
137
+ timestamp?: string;
138
+ inputsIconsColor?: string;
139
+ sendIconsColor?: string;
140
+ placeholderTextColor?: string;
141
+ audioPlayIconColor?: string;
142
+ audioPauseIconColor?: string;
143
+ videoPlayIconColor?: string;
144
+ };
145
+ bubbleStyle?: {
146
+ sent?: ViewStyle;
147
+ received?: ViewStyle;
148
+ avatarTextStyle?: TextStyle;
149
+ userNameStyle?: TextStyle;
150
+ avatarImageStyle?: ImageStyle;
151
+ typingContainerStyle?: ViewStyle;
152
+ additionalTypingUsersContainerStyle?: ViewStyle;
153
+ additionalTypingUsersTextStyle?: TextStyle;
154
+ };
155
+ messageStyle?: {
156
+ sentTextStyle?: TextStyle;
157
+ receivedTextStyle?: TextStyle;
158
+ audioPlayButtonStyle?: ViewStyle;
159
+ audioKnobStyle?: ViewStyle;
160
+ progressBarStyle?: ViewStyle;
161
+ activeProgressBarStyle?: ViewStyle;
162
+ audioDurationStyle?: TextStyle;
163
+ };
164
+ inputStyles?: {
165
+ inputSectionContainerStyle?: ViewStyle;
166
+ inputContainerStyle?: ViewStyle;
167
+ sendButtonStyle?: ViewStyle;
168
+ };
162
169
  };
163
- }
164
170
  ```
165
171
 
166
172
  ### Custom Components
167
173
 
168
- You can provide custom components for various elements:
169
-
170
174
  | Prop | Type | Description |
171
175
  |------|------|-------------|
172
176
  | renderCustomInput | () => React.ReactNode | Custom input component |
@@ -209,33 +213,42 @@ You can provide custom components for various elements:
209
213
  />
210
214
  ```
211
215
 
212
- ### Custom Input Component
216
+ ### Expo Usage
213
217
 
214
- ```typescript
215
- <ChatScreen
216
- messages={messages}
217
- currentUserId="user123"
218
- onSendMessage={handleSendMessage}
219
- renderCustomInput={() => (
220
- <YourCustomInputComponent
221
- onSend={(text) => {
222
- handleSendMessage({
223
- text,
224
- senderId: 'user123',
225
- });
226
- }}
227
- />
228
- )}
229
- />
230
- ```
218
+ If you're using Expo, follow these steps:
219
+
220
+ 1. Create a development build of your app:
221
+ ```bash
222
+ npx expo prebuild
223
+ ```
224
+
225
+ 2. Run on your desired platform:
226
+ ```bash
227
+ npx expo run:android
228
+ # or
229
+ npx expo run:ios
230
+ ```
231
231
 
232
- ## Performance Considerations
232
+ 3. For subsequent updates to the native modules, you'll need to rebuild:
233
+ ```bash
234
+ npx expo prebuild --clean
235
+ ```
236
+
237
+ ### Performance Considerations
233
238
 
234
239
  - Messages are rendered using `FlatList` for optimal performance
235
240
  - Avatar images are cached automatically
236
241
  - Media messages use lazy loading
237
242
  - Typing indicators are debounced
238
243
 
244
+ ## Troubleshooting
245
+
246
+ ### Common Issues
247
+
248
+ - **"Native module not found" error**: Ensure you've rebuilt your app after installing the package.
249
+ - **Crashes in Expo Go**: This package uses native modules that are not compatible with Expo Go. Use a development build instead.
250
+ - **Audio/Video not working**: Check that you've installed all required dependencies and rebuilt the app.
251
+
239
252
  ## Contributing
240
253
 
241
254
  We welcome contributions! Please see our contributing guide for details.
@@ -1,2 +1,2 @@
1
- "use strict";var e=require("react-native-svg"),r=require("react/jsx-runtime");exports.ArrowBack2RoundedIcon=({style:o,color:t})=>r.jsx(e,{style:o,fill:t,viewBox:"0 0 48 48",children:r.jsx(e.Path,{fillRule:"evenodd",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"4",d:"M8 9.115c0-1.82 2.235-2.694 3.47-1.356l29.432 31.884c1.182 1.282.273 3.357-1.47 3.357H10a2 2 0 0 1-2-2z",clipRule:"evenodd"})});
1
+ "use strict";var e=require("react-native-svg"),r=require("react/jsx-runtime");exports.ArrowBack2RoundedIcon=({style:o,color:t})=>r.jsx(e,{style:o,viewBox:"0 0 48 48",children:r.jsx(e.Path,{fill:t,fillRule:"evenodd",stroke:t,strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"4",d:"M8 9.115c0-1.82 2.235-2.694 3.47-1.356l29.432 31.884c1.182 1.282.273 3.357-1.47 3.357H10a2 2 0 0 1-2-2z",clipRule:"evenodd"})});
2
2
  //# sourceMappingURL=ArrowBack2RoundedIcon.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ArrowBack2RoundedIcon.js","sources":["../../../../src/assets/Icons/ArrowBack2RoundedIcon.tsx"],"sourcesContent":["\nimport { ViewStyle } from \"react-native\";\nimport Svg, { Path } from \"react-native-svg\";\n\nexport const ArrowBack2RoundedIcon = ({\n style,\n color,\n}: {\n style?: ViewStyle;\n color?: string;\n}) => {\n return (\n <Svg style={style} fill={color} viewBox=\"0 0 48 48\">\n <Path\n fillRule=\"evenodd\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"4\"\n d=\"M8 9.115c0-1.82 2.235-2.694 3.47-1.356l29.432 31.884c1.182 1.282.273 3.357-1.47 3.357H10a2 2 0 0 1-2-2z\"\n clipRule=\"evenodd\"\n ></Path>\n </Svg>\n );\n};\n"],"names":["ArrowBack2RoundedIcon","style","color","_jsx","Svg","fill","viewBox","children","jsx","Path","fillRule","stroke","strokeLinecap","strokeLinejoin","strokeWidth","d","clipRule"],"mappings":"4GAIqCA,EACnCC,QACAC,WAMEC,EAAAA,IAACC,EAAG,CAACH,MAAOA,EAAOI,KAAMH,EAAOI,QAAQ,YAAWC,SACjDJ,EAAAK,IAACC,OAAI,CACHC,SAAS,UACTC,OAAO,eACPC,cAAc,QACdC,eAAe,QACfC,YAAY,IACZC,EAAE,0GACFC,SAAS"}
1
+ {"version":3,"file":"ArrowBack2RoundedIcon.js","sources":["../../../../src/assets/Icons/ArrowBack2RoundedIcon.tsx"],"sourcesContent":["import { ViewStyle } from 'react-native';\nimport Svg, { Path } from 'react-native-svg';\n\nexport const ArrowBack2RoundedIcon = ({\n style,\n color,\n}: {\n style?: ViewStyle;\n color?: string;\n}) => {\n return (\n <Svg style={style} viewBox=\"0 0 48 48\">\n <Path\n fill={color}\n fillRule=\"evenodd\"\n stroke={color}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"4\"\n d=\"M8 9.115c0-1.82 2.235-2.694 3.47-1.356l29.432 31.884c1.182 1.282.273 3.357-1.47 3.357H10a2 2 0 0 1-2-2z\"\n clipRule=\"evenodd\"\n ></Path>\n </Svg>\n );\n};\n"],"names":["ArrowBack2RoundedIcon","style","color","_jsx","Svg","viewBox","children","jsx","Path","fill","fillRule","stroke","strokeLinecap","strokeLinejoin","strokeWidth","d","clipRule"],"mappings":"4GAGqCA,EACnCC,QACAC,WAMEC,EAAAA,IAACC,EAAG,CAACH,MAAOA,EAAOI,QAAQ,YAAWC,SACpCH,EAAAI,IAACC,OAAI,CACHC,KAAMP,EACNQ,SAAS,UACTC,OAAQT,EACRU,cAAc,QACdC,eAAe,QACfC,YAAY,IACZC,EAAE,0GACFC,SAAS"}
@@ -1,2 +1,2 @@
1
- "use strict";var e=require("react"),t=require("react-native"),s=require("twrnc"),r=require("../../assets/Icons/ArrowBack2RoundedIcon.js"),l=require("../../context/ChatContext.js"),a=require("./MessageContent.js"),i=require("./MessageStatus.js"),o=require("react/jsx-runtime");const n=({message:e,isCurrentUser:n,isFirstInSequence:u,onLongPress:d})=>{const{theme:c,showAvatars:b,showUserNames:m,showBubbleTail:x,setMediaUrl:g,setIsVideoPlaying:h,isVideoPlaying:y}=l.useChatContext();return o.jsxs(t.Pressable,{onLongPress:d,style:[s`px-2 my-1 max-w-[75%] relative`,n?s`self-end mr-3`:s`self-start ml-9`,u?n?s`bg-green-500 rounded-tr-none`:s`bg-white rounded-tl-none`:n?s`bg-green-500`:s`bg-white`,{borderRadius:8,...n?c?.bubbleStyle?.sent:c?.bubbleStyle?.received}],children:[!n&&u&&b&&o.jsxs(o.Fragment,{children:[o.jsx(t.View,{style:s`absolute w-6 h-6 rounded-full top-0 -left-9 flex-row items-center`,children:e.senderAvatar?o.jsx(t.Image,{source:{uri:e.senderAvatar},style:[s`w-full h-full rounded-full`,c?.bubbleStyle?.avatarImageStyle],resizeMode:"cover"}):o.jsx(t.Text,{style:[s`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,c?.bubbleStyle?.avatarTextStyle],children:e.senderName?.charAt(0)})}),m&&e.senderName&&o.jsx(t.Text,{style:[s`text-sm text-black font-semibold mt-1 capitalize`,c?.bubbleStyle?.userNameStyle],children:e.senderName})]}),u&&x&&o.jsx(r.ArrowBack2RoundedIcon,{style:s.style("absolute -top-1 w-6 h-6",n?"-right-3.5":"-left-3.5 mt-[1.25px]",{transform:[{rotate:n?"90deg":"180deg"}]}),color:n?`${c?.colors?.sentMessageTailColor||"rgba(34, 197, 94,1)"}`:`${c?.colors?.receivedMessageTailColor||"white"}`}),o.jsx(a,{message:e,isCurrentUser:n,isFirstInSequence:u,onMediaPress:(e,t)=>{g({imageUrl:"image"===e?t:"",videoUrl:"video"===e?t:""}),"video"===e&&h(!0)},isVideoPlaying:y}),o.jsx(i,{time:e.time,status:n?e.status:void 0,isCurrentUser:n,hasText:!!e.text,hasAudio:!!e.audio})]})};var u=e.memo(n);module.exports=u;
1
+ "use strict";var e=require("react"),t=require("react-native"),s=require("twrnc"),r=require("../../assets/Icons/ArrowBack2RoundedIcon.js"),a=require("../../context/ChatContext.js"),l=require("./MessageContent.js"),o=require("./MessageStatus.js"),i=require("react/jsx-runtime");const n=({message:e,isCurrentUser:n,isFirstInSequence:u,onLongPress:d})=>{const{theme:c,showAvatars:b,showUserNames:m,showBubbleTail:x,setMediaUrl:g,setIsVideoPlaying:h,isVideoPlaying:y}=a.useChatContext();return i.jsxs(t.Pressable,{onLongPress:d,style:[s`px-2 my-1 max-w-[75%] relative`,n?s`self-end mr-3`:s`self-start ml-9`,u?n?s`bg-green-500 rounded-tr-none`:s`bg-white rounded-tl-none`:n?s`bg-green-500`:s`bg-white`,{borderRadius:8,...n?c?.bubbleStyle?.sent:c?.bubbleStyle?.received}],children:[!n&&u&&b&&i.jsxs(i.Fragment,{children:[i.jsx(t.View,{style:s`absolute w-6 h-6 rounded-full top-0 -left-9 flex-row items-center`,children:e.senderAvatar?i.jsx(t.Image,{source:{uri:e.senderAvatar},style:[s`w-full h-full rounded-full`,c?.bubbleStyle?.avatarImageStyle],resizeMode:"cover"}):i.jsx(t.Text,{style:[s`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,c?.bubbleStyle?.avatarTextStyle],children:e.senderName?.charAt(0)})}),m&&e.senderName&&i.jsx(t.Text,{style:[s`text-sm text-black font-semibold mt-1 capitalize`,c?.bubbleStyle?.userNameStyle],children:e.senderName})]}),u&&x&&i.jsx(r.ArrowBack2RoundedIcon,{style:s.style("absolute -top-1 w-6 h-6 stroke-transparent",n?"-right-3.5":"-left-3.5 mt-[1.25px]",{transform:[{rotate:n?"90deg":"180deg"}]}),color:n?`${c?.colors?.sentMessageTailColor||"rgba(34, 197, 94,1)"}`:`${c?.colors?.receivedMessageTailColor||"white"}`}),i.jsx(l,{message:e,isCurrentUser:n,isFirstInSequence:u,onMediaPress:(e,t)=>{g({imageUrl:"image"===e?t:"",videoUrl:"video"===e?t:""}),"video"===e&&h(!0)},isVideoPlaying:y}),i.jsx(o,{time:e.time,status:n?e.status:void 0,isCurrentUser:n,hasText:!!e.text,hasAudio:!!e.audio})]})};var u=e.memo(n);module.exports=u;
2
2
  //# sourceMappingURL=ChatBubble.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatBubble.js","sources":["../../../../src/components/ChatBubble/ChatBubble.tsx"],"sourcesContent":["import React from 'react';\nimport { Image, Pressable, Text, View } from 'react-native';\nimport tw from 'twrnc';\nimport { ArrowBack2RoundedIcon } from '../../assets/Icons/ArrowBack2RoundedIcon';\nimport { useChatContext } from '../../context/ChatContext';\nimport MessageContent from './MessageContent';\nimport MessageStatus from './MessageStatus';\nimport { ChatBubbleProps } from './types';\n\nconst ChatBubble: React.FC<ChatBubbleProps> = ({\n message,\n isCurrentUser,\n isFirstInSequence,\n onLongPress,\n}) => {\n const {\n theme,\n showAvatars,\n showUserNames,\n showBubbleTail,\n setMediaUrl,\n setIsVideoPlaying,\n isVideoPlaying,\n } = useChatContext();\n\n const handleMediaPress = (type: 'image' | 'video', url: string) => {\n setMediaUrl({\n imageUrl: type === 'image' ? url : '',\n videoUrl: type === 'video' ? url : '',\n });\n if (type === 'video') {\n setIsVideoPlaying(true);\n }\n };\n\n return (\n <Pressable\n onLongPress={onLongPress}\n style={[\n tw`px-2 my-1 max-w-[75%] relative`,\n isCurrentUser ? tw`self-end mr-3` : tw`self-start ml-9`,\n isFirstInSequence\n ? isCurrentUser\n ? tw`bg-green-500 rounded-tr-none`\n : tw`bg-white rounded-tl-none`\n : isCurrentUser\n ? tw`bg-green-500`\n : tw`bg-white`,\n {\n borderRadius: 8,\n ...(isCurrentUser\n ? theme?.bubbleStyle?.sent\n : theme?.bubbleStyle?.received),\n },\n ]}\n >\n {/* Avatar & Sender Name for Group Chat */}\n {!isCurrentUser && isFirstInSequence && showAvatars && (\n <>\n <View\n style={tw`absolute w-6 h-6 rounded-full top-0 -left-9 flex-row items-center`}\n >\n {message.senderAvatar ? (\n <Image\n source={{ uri: message.senderAvatar }}\n style={[\n tw`w-full h-full rounded-full`,\n theme?.bubbleStyle?.avatarImageStyle,\n ]}\n resizeMode=\"cover\"\n />\n ) : (\n <Text\n style={[\n tw`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,\n theme?.bubbleStyle?.avatarTextStyle,\n ]}\n >\n {message.senderName?.charAt(0)}\n </Text>\n )}\n </View>\n {showUserNames && message.senderName && (\n <Text\n style={[\n tw`text-sm text-black font-semibold mt-1 capitalize`,\n theme?.bubbleStyle?.userNameStyle,\n ]}\n >\n {message.senderName}\n </Text>\n )}\n </>\n )}\n\n {/* Bubble Tail */}\n {isFirstInSequence && showBubbleTail && (\n <ArrowBack2RoundedIcon\n style={tw.style(\n 'absolute -top-1 w-6 h-6',\n isCurrentUser ? '-right-3.5' : '-left-3.5 mt-[1.25px]',\n {\n transform: [{ rotate: isCurrentUser ? '90deg' : '180deg' }],\n }\n )}\n color={\n isCurrentUser\n ? `${\n theme?.colors?.sentMessageTailColor || 'rgba(34, 197, 94,1)'\n }`\n : `${theme?.colors?.receivedMessageTailColor || 'white'}`\n }\n />\n )}\n\n {/* Message Content */}\n <MessageContent\n message={message}\n isCurrentUser={isCurrentUser}\n isFirstInSequence={isFirstInSequence}\n onMediaPress={handleMediaPress}\n isVideoPlaying={isVideoPlaying}\n />\n\n {/* Message Status */}\n <MessageStatus\n time={message.time}\n status={isCurrentUser ? message.status : undefined}\n isCurrentUser={isCurrentUser}\n hasText={!!message.text}\n hasAudio={!!message.audio}\n />\n </Pressable>\n );\n};\n\nexport default React.memo(ChatBubble);\n"],"names":["ChatBubble","message","isCurrentUser","isFirstInSequence","onLongPress","theme","showAvatars","showUserNames","showBubbleTail","setMediaUrl","setIsVideoPlaying","isVideoPlaying","useChatContext","_jsxs","Pressable","style","tw","borderRadius","bubbleStyle","sent","received","children","jsxs","_Fragment","_jsx","jsx","View","senderAvatar","Image","source","uri","avatarImageStyle","resizeMode","Text","avatarTextStyle","senderName","charAt","userNameStyle","ArrowBack2RoundedIcon","transform","rotate","color","colors","sentMessageTailColor","receivedMessageTailColor","MessageContent","onMediaPress","handleMediaPress","type","url","imageUrl","videoUrl","MessageStatus","time","status","undefined","hasText","text","hasAudio","audio","ChatBubble$1","React","memo"],"mappings":"oRASA,MAAMA,EAAwCA,EAC5CC,UACAC,gBACAC,oBACAC,kBAEA,MAAMC,MACJA,EAAKC,YACLA,EAAWC,cACXA,EAAaC,eACbA,EAAcC,YACdA,EAAWC,kBACXA,EAAiBC,eACjBA,GACEC,mBAYJ,OACEC,EAAAA,KAACC,EAAAA,UAAS,CACRV,YAAaA,EACbW,MAAO,CACLC,CAAE,iCACFd,EAAgBc,CAAE,gBAAkBA,CAAE,kBACtCb,EACID,EACEc,CAAE,+BACFA,CAAE,2BACJd,EACEc,CAAE,eACFA,CAAE,WACR,CACEC,aAAc,KACVf,EACAG,GAAOa,aAAaC,KACpBd,GAAOa,aAAaE,WAE1BC,SAAA,EAGAnB,GAAiBC,GAAqBG,GACtCO,EAAAS,KAAAC,WAAA,CAAAF,SAAA,CACEG,EAAAC,IAACC,OAAI,CACHX,MAAOC,CAAE,oEAAoEK,SAE5EpB,EAAQ0B,aACPH,EAAAA,IAACI,EAAAA,MAAK,CACJC,OAAQ,CAAEC,IAAK7B,EAAQ0B,cACvBZ,MAAO,CACLC,CAAE,6BACFX,GAAOa,aAAaa,kBAEtBC,WAAW,UAGbR,EAAAC,IAACQ,OAAI,CACHlB,MAAO,CACLC,CAAE,wGACFX,GAAOa,aAAagB,iBACpBb,SAEDpB,EAAQkC,YAAYC,OAAO,OAIjC7B,GAAiBN,EAAQkC,YACxBX,EAAAA,IAACS,EAAAA,KAAI,CACHlB,MAAO,CACLC,CAAE,mDACFX,GAAOa,aAAamB,eACpBhB,SAEDpB,EAAQkC,gBAOhBhC,GAAqBK,GACpBgB,EAAAA,IAACc,EAAAA,sBAAqB,CACpBvB,MAAOC,EAAGD,MACR,0BACAb,EAAgB,aAAe,wBAC/B,CACEqC,UAAW,CAAC,CAAEC,OAAQtC,EAAgB,QAAU,aAGpDuC,MACEvC,EACI,GACEG,GAAOqC,QAAQC,sBAAwB,wBAEzC,GAAGtC,GAAOqC,QAAQE,0BAA4B,YAMxDpB,EAAAC,IAACoB,EAAc,CACb5C,QAASA,EACTC,cAAeA,EACfC,kBAAmBA,EACnB2C,aA/FmBC,CAACC,EAAyBC,KACjDxC,EAAY,CACVyC,SAAmB,UAATF,EAAmBC,EAAM,GACnCE,SAAmB,UAATH,EAAmBC,EAAM,KAExB,UAATD,GACFtC,GAAkB,EACpB,EAyFIC,eAAgBA,IAIlBa,EAAAC,IAAC2B,EAAa,CACZC,KAAMpD,EAAQoD,KACdC,OAAQpD,EAAgBD,EAAQqD,YAASC,EACzCrD,cAAeA,EACfsD,UAAWvD,EAAQwD,KACnBC,WAAYzD,EAAQ0D,UAEZ,EAIhB,IAAAC,EAAeC,EAAMC,KAAK9D"}
1
+ {"version":3,"file":"ChatBubble.js","sources":["../../../../src/components/ChatBubble/ChatBubble.tsx"],"sourcesContent":["import React from 'react';\nimport { Image, Pressable, Text, View } from 'react-native';\nimport tw from 'twrnc';\nimport { ArrowBack2RoundedIcon } from '../../assets/Icons/ArrowBack2RoundedIcon';\nimport { useChatContext } from '../../context/ChatContext';\nimport MessageContent from './MessageContent';\nimport MessageStatus from './MessageStatus';\nimport { ChatBubbleProps } from './types';\n\nconst ChatBubble: React.FC<ChatBubbleProps> = ({\n message,\n isCurrentUser,\n isFirstInSequence,\n onLongPress,\n}) => {\n const {\n theme,\n showAvatars,\n showUserNames,\n showBubbleTail,\n setMediaUrl,\n setIsVideoPlaying,\n isVideoPlaying,\n } = useChatContext();\n\n const handleMediaPress = (type: 'image' | 'video', url: string) => {\n setMediaUrl({\n imageUrl: type === 'image' ? url : '',\n videoUrl: type === 'video' ? url : '',\n });\n if (type === 'video') {\n setIsVideoPlaying(true);\n }\n };\n\n return (\n <Pressable\n onLongPress={onLongPress}\n style={[\n tw`px-2 my-1 max-w-[75%] relative`,\n isCurrentUser ? tw`self-end mr-3` : tw`self-start ml-9`,\n isFirstInSequence\n ? isCurrentUser\n ? tw`bg-green-500 rounded-tr-none`\n : tw`bg-white rounded-tl-none`\n : isCurrentUser\n ? tw`bg-green-500`\n : tw`bg-white`,\n {\n borderRadius: 8,\n ...(isCurrentUser\n ? theme?.bubbleStyle?.sent\n : theme?.bubbleStyle?.received),\n },\n ]}\n >\n {/* Avatar & Sender Name for Group Chat */}\n {!isCurrentUser && isFirstInSequence && showAvatars && (\n <>\n <View\n style={tw`absolute w-6 h-6 rounded-full top-0 -left-9 flex-row items-center`}\n >\n {message.senderAvatar ? (\n <Image\n source={{ uri: message.senderAvatar }}\n style={[\n tw`w-full h-full rounded-full`,\n theme?.bubbleStyle?.avatarImageStyle,\n ]}\n resizeMode=\"cover\"\n />\n ) : (\n <Text\n style={[\n tw`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,\n theme?.bubbleStyle?.avatarTextStyle,\n ]}\n >\n {message.senderName?.charAt(0)}\n </Text>\n )}\n </View>\n {showUserNames && message.senderName && (\n <Text\n style={[\n tw`text-sm text-black font-semibold mt-1 capitalize`,\n theme?.bubbleStyle?.userNameStyle,\n ]}\n >\n {message.senderName}\n </Text>\n )}\n </>\n )}\n\n {/* Bubble Tail */}\n {isFirstInSequence && showBubbleTail && (\n <ArrowBack2RoundedIcon\n style={tw.style(\n 'absolute -top-1 w-6 h-6 stroke-transparent',\n isCurrentUser ? '-right-3.5' : '-left-3.5 mt-[1.25px]',\n {\n transform: [{ rotate: isCurrentUser ? '90deg' : '180deg' }],\n }\n )}\n color={\n isCurrentUser\n ? `${\n theme?.colors?.sentMessageTailColor || 'rgba(34, 197, 94,1)'\n }`\n : `${theme?.colors?.receivedMessageTailColor || 'white'}`\n }\n />\n )}\n\n {/* Message Content */}\n <MessageContent\n message={message}\n isCurrentUser={isCurrentUser}\n isFirstInSequence={isFirstInSequence}\n onMediaPress={handleMediaPress}\n isVideoPlaying={isVideoPlaying}\n />\n\n {/* Message Status */}\n <MessageStatus\n time={message.time}\n status={isCurrentUser ? message.status : undefined}\n isCurrentUser={isCurrentUser}\n hasText={!!message.text}\n hasAudio={!!message.audio}\n />\n </Pressable>\n );\n};\n\nexport default React.memo(ChatBubble);\n"],"names":["ChatBubble","message","isCurrentUser","isFirstInSequence","onLongPress","theme","showAvatars","showUserNames","showBubbleTail","setMediaUrl","setIsVideoPlaying","isVideoPlaying","useChatContext","_jsxs","Pressable","style","tw","borderRadius","bubbleStyle","sent","received","children","jsxs","_Fragment","_jsx","jsx","View","senderAvatar","Image","source","uri","avatarImageStyle","resizeMode","Text","avatarTextStyle","senderName","charAt","userNameStyle","ArrowBack2RoundedIcon","transform","rotate","color","colors","sentMessageTailColor","receivedMessageTailColor","MessageContent","onMediaPress","handleMediaPress","type","url","imageUrl","videoUrl","MessageStatus","time","status","undefined","hasText","text","hasAudio","audio","ChatBubble$1","React","memo"],"mappings":"oRASA,MAAMA,EAAwCA,EAC5CC,UACAC,gBACAC,oBACAC,kBAEA,MAAMC,MACJA,EAAKC,YACLA,EAAWC,cACXA,EAAaC,eACbA,EAAcC,YACdA,EAAWC,kBACXA,EAAiBC,eACjBA,GACEC,mBAYJ,OACEC,EAAAA,KAACC,EAAAA,UAAS,CACRV,YAAaA,EACbW,MAAO,CACLC,CAAE,iCACFd,EAAgBc,CAAE,gBAAkBA,CAAE,kBACtCb,EACID,EACEc,CAAE,+BACFA,CAAE,2BACJd,EACEc,CAAE,eACFA,CAAE,WACR,CACEC,aAAc,KACVf,EACAG,GAAOa,aAAaC,KACpBd,GAAOa,aAAaE,WAE1BC,SAAA,EAGAnB,GAAiBC,GAAqBG,GACtCO,EAAAS,KAAAC,WAAA,CAAAF,SAAA,CACEG,EAAAC,IAACC,OAAI,CACHX,MAAOC,CAAE,oEAAoEK,SAE5EpB,EAAQ0B,aACPH,EAAAA,IAACI,EAAAA,MAAK,CACJC,OAAQ,CAAEC,IAAK7B,EAAQ0B,cACvBZ,MAAO,CACLC,CAAE,6BACFX,GAAOa,aAAaa,kBAEtBC,WAAW,UAGbR,EAAAC,IAACQ,OAAI,CACHlB,MAAO,CACLC,CAAE,wGACFX,GAAOa,aAAagB,iBACpBb,SAEDpB,EAAQkC,YAAYC,OAAO,OAIjC7B,GAAiBN,EAAQkC,YACxBX,EAAAA,IAACS,EAAAA,KAAI,CACHlB,MAAO,CACLC,CAAE,mDACFX,GAAOa,aAAamB,eACpBhB,SAEDpB,EAAQkC,gBAOhBhC,GAAqBK,GACpBgB,EAAAA,IAACc,EAAAA,sBAAqB,CACpBvB,MAAOC,EAAGD,MACR,6CACAb,EAAgB,aAAe,wBAC/B,CACEqC,UAAW,CAAC,CAAEC,OAAQtC,EAAgB,QAAU,aAGpDuC,MACEvC,EACI,GACEG,GAAOqC,QAAQC,sBAAwB,wBAEzC,GAAGtC,GAAOqC,QAAQE,0BAA4B,YAMxDpB,EAAAC,IAACoB,EAAc,CACb5C,QAASA,EACTC,cAAeA,EACfC,kBAAmBA,EACnB2C,aA/FmBC,CAACC,EAAyBC,KACjDxC,EAAY,CACVyC,SAAmB,UAATF,EAAmBC,EAAM,GACnCE,SAAmB,UAATH,EAAmBC,EAAM,KAExB,UAATD,GACFtC,GAAkB,EACpB,EAyFIC,eAAgBA,IAIlBa,EAAAC,IAAC2B,EAAa,CACZC,KAAMpD,EAAQoD,KACdC,OAAQpD,EAAgBD,EAAQqD,YAASC,EACzCrD,cAAeA,EACfsD,UAAWvD,EAAQwD,KACnBC,WAAYzD,EAAQ0D,UAEZ,EAIhB,IAAAC,EAAeC,EAAMC,KAAK9D"}
@@ -1,2 +1,2 @@
1
- "use strict";var e=require("react"),t=require("react-native"),s=require("react-native-video"),r=require("twrnc"),i=require("../../assets/Icons/LoadingIcon.js"),o=require("../../assets/Icons/PlayIcon.js"),l=require("../../context/ChatContext.js"),a=require("../../utils/datefunc.js"),n=require("../AudioPlayer/AudioPlayer.js"),d=require("react/jsx-runtime");const u=({message:u,onMediaPress:c,isVideoPlaying:x})=>{const{theme:y,showMessageStatus:h,CustomPlayIcon:j,renderCustomVideoBubbleError:m}=l.useChatContext(),b=e.useRef(null),[f,w]=e.useState(0),[g,v]=e.useState(!1),[P,p]=e.useState(!1);return d.jsxs(t.View,{children:[u.image&&d.jsx(t.Pressable,{onPress:()=>c("image",u.image),style:r`w-60 h-80 my-2`,children:d.jsx(t.Image,{source:{uri:u.image},style:r`w-full h-full object-contain rounded-lg`})}),u.video&&d.jsxs(t.Pressable,{onPress:()=>c("video",u.video),style:r`w-60 h-80 my-2 justify-center items-center`,disabled:g,children:[d.jsx(s,{source:{uri:u.video},ref:b,paused:!0,style:{width:"100%",height:"100%",borderRadius:8,position:"relative"},resizeMode:"cover",onLoadStart:()=>{v(!0),p(!1)},onLoad:e=>{w(e.duration),v(!1)},onBuffer:({isBuffering:e})=>v(e),onError:()=>{p(!0),v(!1)}}),g?d.jsx(t.View,{style:r`absolute inset-0 flex items-center justify-center bg-black/40 rounded-full`,children:d.jsx(i.LoadingIcon,{style:r.style("h-12 w-12 fill-white animate-spin")})}):P?m?m():d.jsx(t.View,{style:r`absolute inset-0 flex items-center justify-center bg-red-500/60 p-2`,children:d.jsx(t.Text,{style:r`text-white font-bold`,children:"Failed to load video"})}):d.jsxs(d.Fragment,{children:[d.jsx(t.View,{style:r`absolute bg-black/40 rounded-full`,children:j?d.jsx(j,{}):d.jsx(o.PlayIcon,{style:r.style("h-16 w-16"),color:y?.colors?.audioPlayIconColor||"white"})}),d.jsx(t.View,{style:r`absolute bottom-2 left-2 bg-black/50 px-2 py-1 rounded-md`,children:d.jsx(t.Text,{style:r`text-white text-xs font-semibold`,children:a.formatDuration(f)})})]})]}),u.audio&&d.jsx(t.View,{style:r`my-2`,children:d.jsx(n,{audioUrl:u.audio,audioId:u.id,isVideoPlaying:x})}),u.text&&d.jsx(t.Text,{style:[r`text-gray-800 pt-1`,h?r`pb-0`:r`pb-2`,{wordBreak:"break-word",overflowWrap:"break-word"},y?.messageStyle?.textStyle],children:u.text})]})};var c=e.memo(u);module.exports=c;
1
+ "use strict";var e=require("react"),t=require("react-native"),s=require("react-native-video"),r=require("twrnc"),i=require("../../assets/Icons/LoadingIcon.js"),o=require("../../assets/Icons/PlayIcon.js"),l=require("../../context/ChatContext.js"),a=require("../../utils/datefunc.js"),n=require("../AudioPlayer/AudioPlayer.js"),d=require("react/jsx-runtime");const u=({message:u,onMediaPress:c,isVideoPlaying:x,isCurrentUser:y})=>{const{theme:h,showMessageStatus:j,CustomPlayIcon:m,renderCustomVideoBubbleError:b}=l.useChatContext(),f=e.useRef(null),[w,g]=e.useState(0),[v,P]=e.useState(!1),[p,q]=e.useState(!1);return d.jsxs(t.View,{children:[u.image&&d.jsx(t.Pressable,{onPress:()=>c("image",u.image),style:r`w-60 h-80 my-2`,children:d.jsx(t.Image,{source:{uri:u.image},style:r`w-full h-full object-contain rounded-lg`})}),u.video&&d.jsxs(t.Pressable,{onPress:()=>c("video",u.video),style:r`w-60 h-80 my-2 justify-center items-center`,disabled:v,children:[d.jsx(s,{source:{uri:u.video},ref:f,paused:!0,style:{width:"100%",height:"100%",borderRadius:8,position:"relative"},resizeMode:"cover",onLoadStart:()=>{P(!0),q(!1)},onLoad:e=>{g(e.duration),P(!1)},onBuffer:({isBuffering:e})=>P(e),onError:()=>{q(!0),P(!1)}}),v?d.jsx(t.View,{style:r`absolute inset-0 flex items-center justify-center bg-black/40 rounded-full`,children:d.jsx(i.LoadingIcon,{style:r.style("h-12 w-12 fill-white animate-spin")})}):p?b?b():d.jsx(t.View,{style:r`absolute inset-0 flex items-center justify-center bg-red-500/60 p-2`,children:d.jsx(t.Text,{style:r`text-white font-bold`,children:"Failed to load video"})}):d.jsxs(d.Fragment,{children:[d.jsx(t.View,{style:r`absolute bg-black/40 rounded-full`,children:m?d.jsx(m,{}):d.jsx(o.PlayIcon,{style:r.style("h-16 w-16"),color:h?.colors?.audioPlayIconColor||"white"})}),d.jsx(t.View,{style:r`absolute bottom-2 left-2 bg-black/50 px-2 py-1 rounded-md`,children:d.jsx(t.Text,{style:r`text-white text-xs font-semibold`,children:a.formatDuration(w)})})]})]}),u.audio&&d.jsx(t.View,{style:r`my-2`,children:d.jsx(n,{audioUrl:u.audio,audioId:u.id,isVideoPlaying:x})}),u.text&&d.jsx(t.Text,{style:[r`pt-1`,j?r`pb-0`:r`pb-2`,{wordBreak:"break-word",overflowWrap:"break-word"},y?h?.messageStyle?.sentTextStyle:h?.messageStyle?.receivedTextStyle],children:u.text})]})};var c=e.memo(u);module.exports=c;
2
2
  //# sourceMappingURL=MessageContent.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MessageContent.js","sources":["../../../../src/components/ChatBubble/MessageContent.tsx"],"sourcesContent":["import React from 'react';\nimport { Image, Pressable, Text, View } from 'react-native';\nimport Video, { VideoRef } from 'react-native-video';\nimport tw from 'twrnc';\nimport { LoadingIcon } from '../../assets/Icons/LoadingIcon';\nimport { PlayIcon } from '../../assets/Icons/PlayIcon';\nimport { useChatContext } from '../../context/ChatContext';\nimport { formatDuration } from '../../utils/datefunc';\nimport AudioPlayer from '../AudioPlayer/AudioPlayer';\nimport { MessageContentProps } from './types';\n\nconst MessageContent: React.FC<MessageContentProps> = ({\n message,\n onMediaPress,\n isVideoPlaying,\n}) => {\n const {\n theme,\n showMessageStatus,\n CustomPlayIcon,\n renderCustomVideoBubbleError,\n } = useChatContext();\n const videoRef = React.useRef<VideoRef>(null);\n const [duration, setDuration] = React.useState(0);\n const [videoIsLoading, setVideoIsLoading] = React.useState(false);\n const [videoHasError, setVideoHasError] = React.useState(false);\n\n return (\n <View>\n {message.image && (\n <Pressable\n onPress={() => onMediaPress('image', message.image as string)}\n style={tw`w-60 h-80 my-2`}\n >\n <Image\n source={{ uri: message.image }}\n style={tw`w-full h-full object-contain rounded-lg`}\n />\n </Pressable>\n )}\n\n {message.video && (\n <Pressable\n onPress={() => onMediaPress('video', message.video as string)}\n style={tw`w-60 h-80 my-2 justify-center items-center`}\n disabled={videoIsLoading}\n >\n <Video\n source={{ uri: message.video }}\n ref={videoRef}\n paused={true}\n style={{\n width: '100%',\n height: '100%',\n borderRadius: 8,\n position: 'relative',\n }}\n resizeMode=\"cover\"\n onLoadStart={() => {\n setVideoIsLoading(true);\n setVideoHasError(false);\n }}\n onLoad={(data) => {\n setDuration(data.duration);\n setVideoIsLoading(false);\n }}\n onBuffer={({ isBuffering }) => setVideoIsLoading(isBuffering)}\n onError={() => {\n setVideoHasError(true);\n setVideoIsLoading(false);\n }}\n />\n {videoIsLoading ? (\n <View\n style={tw`absolute inset-0 flex items-center justify-center bg-black/40 rounded-full`}\n >\n <LoadingIcon\n style={tw.style('h-12 w-12 fill-white animate-spin')}\n />\n </View>\n ) : videoHasError ? (\n renderCustomVideoBubbleError ? (\n renderCustomVideoBubbleError()\n ) : (\n <View\n style={tw`absolute inset-0 flex items-center justify-center bg-red-500/60 p-2`}\n >\n <Text style={tw`text-white font-bold`}>\n Failed to load video\n </Text>\n </View>\n )\n ) : (\n <>\n <View style={tw`absolute bg-black/40 rounded-full`}>\n {CustomPlayIcon ? (\n <CustomPlayIcon />\n ) : (\n <PlayIcon\n style={tw.style('h-16 w-16')}\n color={theme?.colors?.audioPlayIconColor || 'white'}\n />\n )}\n </View>\n <View\n style={tw`absolute bottom-2 left-2 bg-black/50 px-2 py-1 rounded-md`}\n >\n <Text style={tw`text-white text-xs font-semibold`}>\n {formatDuration(duration)}\n </Text>\n </View>\n </>\n )}\n </Pressable>\n )}\n\n {message.audio && (\n <View style={tw`my-2`}>\n <AudioPlayer\n audioUrl={message.audio}\n audioId={message.id}\n isVideoPlaying={isVideoPlaying as boolean}\n />\n </View>\n )}\n\n {message.text && (\n <Text\n style={[\n tw`text-gray-800 pt-1`,\n showMessageStatus ? tw`pb-0` : tw`pb-2`,\n { wordBreak: 'break-word', overflowWrap: 'break-word' },\n theme?.messageStyle?.textStyle,\n ]}\n >\n {message.text}\n </Text>\n )}\n </View>\n );\n};\n\nexport default React.memo(MessageContent);\n"],"names":["MessageContent","message","onMediaPress","isVideoPlaying","theme","showMessageStatus","CustomPlayIcon","renderCustomVideoBubbleError","useChatContext","videoRef","React","useRef","duration","setDuration","useState","videoIsLoading","setVideoIsLoading","videoHasError","setVideoHasError","_jsxs","View","children","image","_jsx","Pressable","onPress","style","tw","jsx","Image","source","uri","video","disabled","Video","ref","paused","width","height","borderRadius","position","resizeMode","onLoadStart","onLoad","data","onBuffer","isBuffering","onError","LoadingIcon","Text","jsxs","_Fragment","PlayIcon","color","colors","audioPlayIconColor","formatDuration","audio","AudioPlayer","audioUrl","audioId","id","text","wordBreak","overflowWrap","messageStyle","textStyle","MessageContent$1","memo"],"mappings":"qWAWA,MAAMA,EAAgDA,EACpDC,UACAC,eACAC,qBAEA,MAAMC,MACJA,EAAKC,kBACLA,EAAiBC,eACjBA,EAAcC,6BACdA,GACEC,mBACEC,EAAWC,EAAMC,OAAiB,OACjCC,EAAUC,GAAeH,EAAMI,SAAS,IACxCC,EAAgBC,GAAqBN,EAAMI,UAAS,IACpDG,EAAeC,GAAoBR,EAAMI,UAAS,GAEzD,OACEK,EAAAA,KAACC,EAAAA,KAAI,CAAAC,UACFpB,EAAQqB,OACPC,EAAAA,IAACC,EAAAA,UAAS,CACRC,QAASA,IAAMvB,EAAa,QAASD,EAAQqB,OAC7CI,MAAOC,CAAE,iBAAiBN,SAE1BE,EAAAK,IAACC,QAAK,CACJC,OAAQ,CAAEC,IAAK9B,EAAQqB,OACvBI,MAAOC,CAAE,8CAKd1B,EAAQ+B,OACPb,EAAAA,KAACK,EAAAA,UAAS,CACRC,QAASA,IAAMvB,EAAa,QAASD,EAAQ+B,OAC7CN,MAAOC,CAAE,6CACTM,SAAUlB,EAAeM,SAAA,CAEzBE,EAAAK,IAACM,EAAK,CACJJ,OAAQ,CAAEC,IAAK9B,EAAQ+B,OACvBG,IAAK1B,EACL2B,QAAQ,EACRV,MAAO,CACLW,MAAO,OACPC,OAAQ,OACRC,aAAc,EACdC,SAAU,YAEZC,WAAW,QACXC,YAAaA,KACX1B,GAAkB,GAClBE,GAAiB,EAAM,EAEzByB,OAASC,IACP/B,EAAY+B,EAAKhC,UACjBI,GAAkB,EAAM,EAE1B6B,SAAUA,EAAGC,iBAAkB9B,EAAkB8B,GACjDC,QAASA,KACP7B,GAAiB,GACjBF,GAAkB,EAAM,IAG3BD,EACCQ,EAAAK,IAACR,OAAI,CACHM,MAAOC,CAAE,6EAA6EN,SAEtFE,EAAAK,IAACoB,cAAW,CACVtB,MAAOC,EAAGD,MAAM,yCAGlBT,EACFV,EACEA,IAEAgB,EAAAA,IAACH,EAAAA,KAAI,CACHM,MAAOC,CAAE,sEAAsEN,SAE/EE,EAAAK,IAACqB,OAAI,CAACvB,MAAOC,CAAE,uBAAuBN,SAAC,2BAM3CF,EAAA+B,KAAAC,WAAA,CAAA9B,SAAA,CACEE,EAAAK,IAACR,OAAI,CAACM,MAAOC,CAAE,oCAAoCN,SAChDf,EACCiB,MAACjB,EAAc,CAAA,GAEfiB,EAAAK,IAACwB,WAAQ,CACP1B,MAAOC,EAAGD,MAAM,aAChB2B,MAAOjD,GAAOkD,QAAQC,oBAAsB,YAIlDhC,EAAAK,IAACR,OAAI,CACHM,MAAOC,CAAE,4DAA4DN,SAErEE,EAAAK,IAACqB,OAAI,CAACvB,MAAOC,CAAE,mCAAmCN,SAC/CmC,EAAcA,eAAC5C,aAQ3BX,EAAQwD,OACPlC,EAAAA,IAACH,EAAAA,KAAI,CAACM,MAAOC,CAAE,OAAON,SACpBE,EAAAK,IAAC8B,EAAW,CACVC,SAAU1D,EAAQwD,MAClBG,QAAS3D,EAAQ4D,GACjB1D,eAAgBA,MAKrBF,EAAQ6D,MACPvC,EAAAA,IAAC0B,EAAAA,KAAI,CACHvB,MAAO,CACLC,CAAE,qBACFtB,EAAoBsB,CAAE,OAASA,CAAE,OACjC,CAAEoC,UAAW,aAAcC,aAAc,cACzC5D,GAAO6D,cAAcC,WACrB7C,SAEDpB,EAAQ6D,SAGR,EAIX,IAAAK,EAAezD,EAAM0D,KAAKpE"}
1
+ {"version":3,"file":"MessageContent.js","sources":["../../../../src/components/ChatBubble/MessageContent.tsx"],"sourcesContent":["import React from 'react';\nimport { Image, Pressable, Text, View } from 'react-native';\nimport Video, { VideoRef } from 'react-native-video';\nimport tw from 'twrnc';\nimport { LoadingIcon } from '../../assets/Icons/LoadingIcon';\nimport { PlayIcon } from '../../assets/Icons/PlayIcon';\nimport { useChatContext } from '../../context/ChatContext';\nimport { formatDuration } from '../../utils/datefunc';\nimport AudioPlayer from '../AudioPlayer/AudioPlayer';\nimport { MessageContentProps } from './types';\n\nconst MessageContent: React.FC<MessageContentProps> = ({\n message,\n onMediaPress,\n isVideoPlaying,\n isCurrentUser,\n}) => {\n const {\n theme,\n showMessageStatus,\n CustomPlayIcon,\n renderCustomVideoBubbleError,\n } = useChatContext();\n const videoRef = React.useRef<VideoRef>(null);\n const [duration, setDuration] = React.useState(0);\n const [videoIsLoading, setVideoIsLoading] = React.useState(false);\n const [videoHasError, setVideoHasError] = React.useState(false);\n\n return (\n <View>\n {message.image && (\n <Pressable\n onPress={() => onMediaPress('image', message.image as string)}\n style={tw`w-60 h-80 my-2`}\n >\n <Image\n source={{ uri: message.image }}\n style={tw`w-full h-full object-contain rounded-lg`}\n />\n </Pressable>\n )}\n\n {message.video && (\n <Pressable\n onPress={() => onMediaPress('video', message.video as string)}\n style={tw`w-60 h-80 my-2 justify-center items-center`}\n disabled={videoIsLoading}\n >\n <Video\n source={{ uri: message.video }}\n ref={videoRef}\n paused={true}\n style={{\n width: '100%',\n height: '100%',\n borderRadius: 8,\n position: 'relative',\n }}\n resizeMode=\"cover\"\n onLoadStart={() => {\n setVideoIsLoading(true);\n setVideoHasError(false);\n }}\n onLoad={(data) => {\n setDuration(data.duration);\n setVideoIsLoading(false);\n }}\n onBuffer={({ isBuffering }) => setVideoIsLoading(isBuffering)}\n onError={() => {\n setVideoHasError(true);\n setVideoIsLoading(false);\n }}\n />\n {videoIsLoading ? (\n <View\n style={tw`absolute inset-0 flex items-center justify-center bg-black/40 rounded-full`}\n >\n <LoadingIcon\n style={tw.style('h-12 w-12 fill-white animate-spin')}\n />\n </View>\n ) : videoHasError ? (\n renderCustomVideoBubbleError ? (\n renderCustomVideoBubbleError()\n ) : (\n <View\n style={tw`absolute inset-0 flex items-center justify-center bg-red-500/60 p-2`}\n >\n <Text style={tw`text-white font-bold`}>\n Failed to load video\n </Text>\n </View>\n )\n ) : (\n <>\n <View style={tw`absolute bg-black/40 rounded-full`}>\n {CustomPlayIcon ? (\n <CustomPlayIcon />\n ) : (\n <PlayIcon\n style={tw.style('h-16 w-16')}\n color={theme?.colors?.audioPlayIconColor || 'white'}\n />\n )}\n </View>\n <View\n style={tw`absolute bottom-2 left-2 bg-black/50 px-2 py-1 rounded-md`}\n >\n <Text style={tw`text-white text-xs font-semibold`}>\n {formatDuration(duration)}\n </Text>\n </View>\n </>\n )}\n </Pressable>\n )}\n\n {message.audio && (\n <View style={tw`my-2`}>\n <AudioPlayer\n audioUrl={message.audio}\n audioId={message.id}\n isVideoPlaying={isVideoPlaying as boolean}\n />\n </View>\n )}\n\n {message.text && (\n <Text\n style={[\n tw`pt-1`,\n showMessageStatus ? tw`pb-0` : tw`pb-2`,\n { wordBreak: 'break-word', overflowWrap: 'break-word' },\n isCurrentUser\n ? theme?.messageStyle?.sentTextStyle\n : theme?.messageStyle?.receivedTextStyle,\n ]}\n >\n {message.text}\n </Text>\n )}\n </View>\n );\n};\n\nexport default React.memo(MessageContent);\n"],"names":["MessageContent","message","onMediaPress","isVideoPlaying","isCurrentUser","theme","showMessageStatus","CustomPlayIcon","renderCustomVideoBubbleError","useChatContext","videoRef","React","useRef","duration","setDuration","useState","videoIsLoading","setVideoIsLoading","videoHasError","setVideoHasError","_jsxs","View","children","image","_jsx","Pressable","onPress","style","tw","jsx","Image","source","uri","video","disabled","Video","ref","paused","width","height","borderRadius","position","resizeMode","onLoadStart","onLoad","data","onBuffer","isBuffering","onError","LoadingIcon","Text","jsxs","_Fragment","PlayIcon","color","colors","audioPlayIconColor","formatDuration","audio","AudioPlayer","audioUrl","audioId","id","text","wordBreak","overflowWrap","messageStyle","sentTextStyle","receivedTextStyle","MessageContent$1","memo"],"mappings":"qWAWA,MAAMA,EAAgDA,EACpDC,UACAC,eACAC,iBACAC,oBAEA,MAAMC,MACJA,EAAKC,kBACLA,EAAiBC,eACjBA,EAAcC,6BACdA,GACEC,mBACEC,EAAWC,EAAMC,OAAiB,OACjCC,EAAUC,GAAeH,EAAMI,SAAS,IACxCC,EAAgBC,GAAqBN,EAAMI,UAAS,IACpDG,EAAeC,GAAoBR,EAAMI,UAAS,GAEzD,OACEK,EAAAA,KAACC,EAAAA,KAAI,CAAAC,UACFrB,EAAQsB,OACPC,EAAAA,IAACC,EAAAA,UAAS,CACRC,QAASA,IAAMxB,EAAa,QAASD,EAAQsB,OAC7CI,MAAOC,CAAE,iBAAiBN,SAE1BE,EAAAK,IAACC,QAAK,CACJC,OAAQ,CAAEC,IAAK/B,EAAQsB,OACvBI,MAAOC,CAAE,8CAKd3B,EAAQgC,OACPb,EAAAA,KAACK,EAAAA,UAAS,CACRC,QAASA,IAAMxB,EAAa,QAASD,EAAQgC,OAC7CN,MAAOC,CAAE,6CACTM,SAAUlB,EAAeM,SAAA,CAEzBE,EAAAK,IAACM,EAAK,CACJJ,OAAQ,CAAEC,IAAK/B,EAAQgC,OACvBG,IAAK1B,EACL2B,QAAQ,EACRV,MAAO,CACLW,MAAO,OACPC,OAAQ,OACRC,aAAc,EACdC,SAAU,YAEZC,WAAW,QACXC,YAAaA,KACX1B,GAAkB,GAClBE,GAAiB,EAAM,EAEzByB,OAASC,IACP/B,EAAY+B,EAAKhC,UACjBI,GAAkB,EAAM,EAE1B6B,SAAUA,EAAGC,iBAAkB9B,EAAkB8B,GACjDC,QAASA,KACP7B,GAAiB,GACjBF,GAAkB,EAAM,IAG3BD,EACCQ,EAAAK,IAACR,OAAI,CACHM,MAAOC,CAAE,6EAA6EN,SAEtFE,EAAAK,IAACoB,cAAW,CACVtB,MAAOC,EAAGD,MAAM,yCAGlBT,EACFV,EACEA,IAEAgB,EAAAA,IAACH,EAAAA,KAAI,CACHM,MAAOC,CAAE,sEAAsEN,SAE/EE,EAAAK,IAACqB,OAAI,CAACvB,MAAOC,CAAE,uBAAuBN,SAAC,2BAM3CF,EAAA+B,KAAAC,WAAA,CAAA9B,SAAA,CACEE,EAAAK,IAACR,OAAI,CAACM,MAAOC,CAAE,oCAAoCN,SAChDf,EACCiB,MAACjB,EAAc,CAAA,GAEfiB,EAAAK,IAACwB,WAAQ,CACP1B,MAAOC,EAAGD,MAAM,aAChB2B,MAAOjD,GAAOkD,QAAQC,oBAAsB,YAIlDhC,EAAAK,IAACR,OAAI,CACHM,MAAOC,CAAE,4DAA4DN,SAErEE,EAAAK,IAACqB,OAAI,CAACvB,MAAOC,CAAE,mCAAmCN,SAC/CmC,EAAcA,eAAC5C,aAQ3BZ,EAAQyD,OACPlC,EAAAA,IAACH,EAAAA,KAAI,CAACM,MAAOC,CAAE,OAAON,SACpBE,EAAAK,IAAC8B,EAAW,CACVC,SAAU3D,EAAQyD,MAClBG,QAAS5D,EAAQ6D,GACjB3D,eAAgBA,MAKrBF,EAAQ8D,MACPvC,EAAAA,IAAC0B,EAAAA,KAAI,CACHvB,MAAO,CACLC,CAAE,OACFtB,EAAoBsB,CAAE,OAASA,CAAE,OACjC,CAAEoC,UAAW,aAAcC,aAAc,cACzC7D,EACIC,GAAO6D,cAAcC,cACrB9D,GAAO6D,cAAcE,mBACzB9C,SAEDrB,EAAQ8D,SAGR,EAIX,IAAAM,EAAe1D,EAAM2D,KAAKtE"}
@@ -1,2 +1,2 @@
1
- "use strict";var e=require("react-native"),t=require("twrnc"),r=require("../../assets/Icons/ArrowBack2RoundedIcon.js"),l=require("../../context/ChatContext.js"),n=require("react/jsx-runtime");exports.TypingIndicator=({typingUsers:s,currentUserId:i})=>{const{theme:a,showAvatars:o,renderCustomTyping:c,showBubbleTail:d}=l.useChatContext(),u=s.filter((e=>e.id!==i));if(!u.length)return null;const x=u.slice(0,2),y=u.length-2;return n.jsxs(e.View,{style:t`my-1 max-w-[75%] self-start flex-row`,children:[o&&n.jsxs(e.View,{style:t`flex-row`,children:[x.map(((r,l)=>n.jsx(e.View,{style:[t`bg-gray-400 w-6 h-6 rounded-full items-center`,{marginLeft:l>0?-10:0,zIndex:x.length+l}],children:r.avatar?n.jsx(e.Image,{source:{uri:r.avatar},style:[t`w-full h-full object-cover rounded-full`,a?.bubbleStyle?.avatarImageStyle]}):n.jsx(e.Text,{style:[t`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,a?.bubbleStyle?.avatarTextStyle],children:r.name?.charAt(0)})},r.id))),y>0&&n.jsx(e.View,{style:[t`bg-gray-400 w-6 h-6 rounded-full items-center justify-center`,{marginLeft:-10,zIndex:3},{...a?.bubbleStyle?.additionalTypingUsersContainerStyle}],children:n.jsxs(e.Text,{style:[t`text-white text-xs font-semibold`,a?.bubbleStyle?.additionalTypingUsersTextStyle],children:["+",y]})})]}),d&&n.jsx(r.ArrowBack2RoundedIcon,{style:t.style("w-6 h-6 fill-white mt-[1.25px]",{transform:[{rotate:"180deg"},{translateX:6}]}),color:`${a?.colors?.receivedMessageTailColor||"white"}`}),n.jsx(e.View,{style:[t`px-2 my-1 bg-white rounded-tl-none rounded-lg`,a?.bubbleStyle?.typingContainerStyle],children:c?c():n.jsx(e.View,{style:t`flex-row items-center py-3 px-2 justify-center`,children:n.jsx(e.Text,{style:t`text-gray-600`,children:"Typing..."})})})]})};
1
+ "use strict";var e=require("react-native"),t=require("twrnc"),r=require("../../assets/Icons/ArrowBack2RoundedIcon.js"),l=require("../../context/ChatContext.js"),n=require("react/jsx-runtime");exports.TypingIndicator=({typingUsers:s,currentUserId:i})=>{const{theme:a,showAvatars:o,renderCustomTyping:c,showBubbleTail:d}=l.useChatContext(),u=s.filter((e=>e.id!==i));if(!u.length)return null;const x=u.slice(0,2),y=u.length-2;return n.jsxs(e.View,{style:t`my-1 max-w-[75%] self-start flex-row`,children:[o&&n.jsxs(e.View,{style:t`flex-row`,children:[x.map(((r,l)=>n.jsx(e.View,{style:[t`bg-gray-400 w-6 h-6 rounded-full items-center`,{marginLeft:l>0?-10:0,zIndex:x.length+l}],children:r.avatar?n.jsx(e.Image,{source:{uri:r.avatar},style:[t`w-full h-full object-cover rounded-full`,a?.bubbleStyle?.avatarImageStyle]}):n.jsx(e.Text,{style:[t`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,a?.bubbleStyle?.avatarTextStyle],children:r.name?.charAt(0)})},r.id))),y>0&&n.jsx(e.View,{style:[t`bg-gray-400 w-6 h-6 rounded-full items-center justify-center`,{marginLeft:-10,zIndex:3},{...a?.bubbleStyle?.additionalTypingUsersContainerStyle}],children:n.jsxs(e.Text,{style:[t`text-white text-xs font-semibold`,a?.bubbleStyle?.additionalTypingUsersTextStyle],children:["+",y]})})]}),d&&n.jsx(r.ArrowBack2RoundedIcon,{style:t.style("w-6 h-6 fill-white mt-[1.25px] stroke-transparent",{transform:[{rotate:"180deg"},{translateX:6}]}),color:`${a?.colors?.receivedMessageTailColor||"white"}`}),n.jsx(e.View,{style:[t`px-2 my-1 bg-white rounded-tl-none rounded-lg`,a?.bubbleStyle?.typingContainerStyle],children:c?c():n.jsx(e.View,{style:t`flex-row items-center py-3 px-2 justify-center`,children:n.jsx(e.Text,{style:t`text-gray-600`,children:"Typing..."})})})]})};
2
2
  //# sourceMappingURL=TypingIndicator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TypingIndicator.js","sources":["../../../../src/components/TypingComponent/TypingIndicator.tsx"],"sourcesContent":["import { Image, Text, View } from 'react-native';\nimport tw from 'twrnc';\nimport { ArrowBack2RoundedIcon } from '../../assets/Icons/ArrowBack2RoundedIcon';\nimport { useChatContext } from '../../context/ChatContext';\n\nexport interface TypingUser {\n id: string;\n avatar: string;\n name: string;\n}\n\ninterface TypingIndicatorProps {\n typingUsers: TypingUser[];\n currentUserId: string;\n}\n\nexport const TypingIndicator = ({\n typingUsers,\n currentUserId,\n}: TypingIndicatorProps) => {\n const { theme, showAvatars, renderCustomTyping, showBubbleTail } =\n useChatContext();\n\n const otherTypingUsers = typingUsers.filter(\n (user) => user.id !== currentUserId\n );\n\n if (!otherTypingUsers.length) return null;\n\n const displayedUsers = otherTypingUsers.slice(0, 2);\n const additionalUsers = otherTypingUsers.length - 2;\n\n return (\n <View style={tw`my-1 max-w-[75%] self-start flex-row`}>\n {showAvatars && (\n <View style={tw`flex-row`}>\n {displayedUsers.map((user, index) => (\n <View\n key={user.id}\n style={[\n tw`bg-gray-400 w-6 h-6 rounded-full items-center`,\n {\n marginLeft: index > 0 ? -10 : 0,\n zIndex: displayedUsers.length + index,\n },\n ]}\n >\n {user.avatar ? (\n <Image\n source={{ uri: user.avatar }}\n style={[\n tw`w-full h-full object-cover rounded-full`,\n theme?.bubbleStyle?.avatarImageStyle,\n ]}\n />\n ) : (\n <Text\n style={[\n tw`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,\n theme?.bubbleStyle?.avatarTextStyle,\n ]}\n >\n {user.name?.charAt(0)}\n </Text>\n )}\n </View>\n ))}\n {additionalUsers > 0 && (\n <View\n style={[\n tw`bg-gray-400 w-6 h-6 rounded-full items-center justify-center`,\n {\n marginLeft: -10,\n zIndex: 3,\n },\n { ...theme?.bubbleStyle?.additionalTypingUsersContainerStyle },\n ]}\n >\n <Text\n style={[\n tw`text-white text-xs font-semibold`,\n theme?.bubbleStyle?.additionalTypingUsersTextStyle,\n ]}\n >\n +{additionalUsers}\n </Text>\n </View>\n )}\n </View>\n )}\n {showBubbleTail && (\n <ArrowBack2RoundedIcon\n style={tw.style(\n 'w-6 h-6 fill-white mt-[1.25px]', \n {\n transform: [{ rotate: '180deg' }, { translateX: 6 }],\n }\n )}\n color={`${theme?.colors?.receivedMessageTailColor || 'white'}`}\n />\n )}\n\n <View\n style={[\n tw`px-2 my-1 bg-white rounded-tl-none rounded-lg`,\n theme?.bubbleStyle?.typingContainerStyle,\n ]}\n >\n {renderCustomTyping ? (\n renderCustomTyping()\n ) : (\n <View style={tw`flex-row items-center py-3 px-2 justify-center`}>\n <Text style={tw`text-gray-600`}>Typing...</Text>\n </View>\n )}\n </View>\n </View>\n );\n};\n"],"names":["TypingIndicator","typingUsers","currentUserId","theme","showAvatars","renderCustomTyping","showBubbleTail","useChatContext","otherTypingUsers","filter","user","id","length","displayedUsers","slice","additionalUsers","_jsxs","View","style","tw","children","jsxs","map","index","_jsx","jsx","marginLeft","zIndex","avatar","Image","source","uri","bubbleStyle","avatarImageStyle","Text","avatarTextStyle","name","charAt","additionalTypingUsersContainerStyle","additionalTypingUsersTextStyle","ArrowBack2RoundedIcon","transform","rotate","translateX","color","colors","receivedMessageTailColor","typingContainerStyle"],"mappings":"wNAgB+BA,EAC7BC,cACAC,oBAEA,MAAMC,MAAEA,EAAKC,YAAEA,EAAWC,mBAAEA,EAAkBC,eAAEA,GAC9CC,mBAEIC,EAAmBP,EAAYQ,QAClCC,GAASA,EAAKC,KAAOT,IAGxB,IAAKM,EAAiBI,OAAQ,OAAO,KAErC,MAAMC,EAAiBL,EAAiBM,MAAM,EAAG,GAC3CC,EAAkBP,EAAiBI,OAAS,EAElD,OACEI,EAAAA,KAACC,EAAAA,KAAI,CAACC,MAAOC,CAAE,uCAAuCC,SACnDhB,CAAAA,GACCY,EAAAK,KAACJ,OAAI,CAACC,MAAOC,CAAE,WAAWC,SACvBP,CAAAA,EAAeS,KAAI,CAACZ,EAAMa,IACzBC,EAAAC,IAACR,OAAI,CAEHC,MAAO,CACLC,CAAE,gDACF,CACEO,WAAYH,EAAQ,GAAI,GAAM,EAC9BI,OAAQd,EAAeD,OAASW,IAElCH,SAEDV,EAAKkB,OACJJ,EAAAA,IAACK,EAAAA,MAAK,CACJC,OAAQ,CAAEC,IAAKrB,EAAKkB,QACpBV,MAAO,CACLC,CAAE,0CACFhB,GAAO6B,aAAaC,oBAIxBT,EAAAC,IAACS,OAAI,CACHhB,MAAO,CACLC,CAAE,wGACFhB,GAAO6B,aAAaG,iBACpBf,SAEDV,EAAK0B,MAAMC,OAAO,MAxBlB3B,EAAKC,MA6BbI,EAAkB,GACjBS,EAAAC,IAACR,OAAI,CACHC,MAAO,CACLC,CAAE,+DACF,CACEO,YAAe,GACfC,OAAQ,GAEV,IAAKxB,GAAO6B,aAAaM,sCACzBlB,SAEFJ,EAAAK,KAACa,OAAI,CACHhB,MAAO,CACLC,CAAE,mCACFhB,GAAO6B,aAAaO,gCACpBnB,SAAA,CACH,IACGL,UAMXT,GACCkB,EAAAC,IAACe,wBAAqB,CACpBtB,MAAOC,EAAGD,MACR,iCACA,CACEuB,UAAW,CAAC,CAAEC,OAAQ,UAAY,CAAEC,WAAY,MAGpDC,MAAO,GAAGzC,GAAO0C,QAAQC,0BAA4B,YAIzDtB,EAAAC,IAACR,OAAI,CACHC,MAAO,CACLC,CAAE,gDACFhB,GAAO6B,aAAae,sBACpB3B,SAEDf,EACCA,IAEAmB,EAAAA,IAACP,EAAAA,KAAI,CAACC,MAAOC,CAAE,iDAAiDC,SAC9DI,EAAAC,IAACS,OAAI,CAAChB,MAAOC,CAAE,gBAAgBC,SAAC,oBAIjC"}
1
+ {"version":3,"file":"TypingIndicator.js","sources":["../../../../src/components/TypingComponent/TypingIndicator.tsx"],"sourcesContent":["import { Image, Text, View } from 'react-native';\nimport tw from 'twrnc';\nimport { ArrowBack2RoundedIcon } from '../../assets/Icons/ArrowBack2RoundedIcon';\nimport { useChatContext } from '../../context/ChatContext';\n\nexport interface TypingUser {\n id: string;\n avatar: string;\n name: string;\n}\n\ninterface TypingIndicatorProps {\n typingUsers: TypingUser[];\n currentUserId: string;\n}\n\nexport const TypingIndicator = ({\n typingUsers,\n currentUserId,\n}: TypingIndicatorProps) => {\n const { theme, showAvatars, renderCustomTyping, showBubbleTail } =\n useChatContext();\n\n const otherTypingUsers = typingUsers.filter(\n (user) => user.id !== currentUserId\n );\n\n if (!otherTypingUsers.length) return null;\n\n const displayedUsers = otherTypingUsers.slice(0, 2);\n const additionalUsers = otherTypingUsers.length - 2;\n\n return (\n <View style={tw`my-1 max-w-[75%] self-start flex-row`}>\n {showAvatars && (\n <View style={tw`flex-row`}>\n {displayedUsers.map((user, index) => (\n <View\n key={user.id}\n style={[\n tw`bg-gray-400 w-6 h-6 rounded-full items-center`,\n {\n marginLeft: index > 0 ? -10 : 0,\n zIndex: displayedUsers.length + index,\n },\n ]}\n >\n {user.avatar ? (\n <Image\n source={{ uri: user.avatar }}\n style={[\n tw`w-full h-full object-cover rounded-full`,\n theme?.bubbleStyle?.avatarImageStyle,\n ]}\n />\n ) : (\n <Text\n style={[\n tw`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,\n theme?.bubbleStyle?.avatarTextStyle,\n ]}\n >\n {user.name?.charAt(0)}\n </Text>\n )}\n </View>\n ))}\n {additionalUsers > 0 && (\n <View\n style={[\n tw`bg-gray-400 w-6 h-6 rounded-full items-center justify-center`,\n {\n marginLeft: -10,\n zIndex: 3,\n },\n { ...theme?.bubbleStyle?.additionalTypingUsersContainerStyle },\n ]}\n >\n <Text\n style={[\n tw`text-white text-xs font-semibold`,\n theme?.bubbleStyle?.additionalTypingUsersTextStyle,\n ]}\n >\n +{additionalUsers}\n </Text>\n </View>\n )}\n </View>\n )}\n {showBubbleTail && (\n <ArrowBack2RoundedIcon\n style={tw.style(\n 'w-6 h-6 fill-white mt-[1.25px] stroke-transparent', \n {\n transform: [{ rotate: '180deg' }, { translateX: 6 }],\n }\n )}\n color={`${theme?.colors?.receivedMessageTailColor || 'white'}`}\n />\n )}\n\n <View\n style={[\n tw`px-2 my-1 bg-white rounded-tl-none rounded-lg`,\n theme?.bubbleStyle?.typingContainerStyle,\n ]}\n >\n {renderCustomTyping ? (\n renderCustomTyping()\n ) : (\n <View style={tw`flex-row items-center py-3 px-2 justify-center`}>\n <Text style={tw`text-gray-600`}>Typing...</Text>\n </View>\n )}\n </View>\n </View>\n );\n};\n"],"names":["TypingIndicator","typingUsers","currentUserId","theme","showAvatars","renderCustomTyping","showBubbleTail","useChatContext","otherTypingUsers","filter","user","id","length","displayedUsers","slice","additionalUsers","_jsxs","View","style","tw","children","jsxs","map","index","_jsx","jsx","marginLeft","zIndex","avatar","Image","source","uri","bubbleStyle","avatarImageStyle","Text","avatarTextStyle","name","charAt","additionalTypingUsersContainerStyle","additionalTypingUsersTextStyle","ArrowBack2RoundedIcon","transform","rotate","translateX","color","colors","receivedMessageTailColor","typingContainerStyle"],"mappings":"wNAgB+BA,EAC7BC,cACAC,oBAEA,MAAMC,MAAEA,EAAKC,YAAEA,EAAWC,mBAAEA,EAAkBC,eAAEA,GAC9CC,mBAEIC,EAAmBP,EAAYQ,QAClCC,GAASA,EAAKC,KAAOT,IAGxB,IAAKM,EAAiBI,OAAQ,OAAO,KAErC,MAAMC,EAAiBL,EAAiBM,MAAM,EAAG,GAC3CC,EAAkBP,EAAiBI,OAAS,EAElD,OACEI,EAAAA,KAACC,EAAAA,KAAI,CAACC,MAAOC,CAAE,uCAAuCC,SACnDhB,CAAAA,GACCY,EAAAK,KAACJ,OAAI,CAACC,MAAOC,CAAE,WAAWC,SACvBP,CAAAA,EAAeS,KAAI,CAACZ,EAAMa,IACzBC,EAAAC,IAACR,OAAI,CAEHC,MAAO,CACLC,CAAE,gDACF,CACEO,WAAYH,EAAQ,GAAI,GAAM,EAC9BI,OAAQd,EAAeD,OAASW,IAElCH,SAEDV,EAAKkB,OACJJ,EAAAA,IAACK,EAAAA,MAAK,CACJC,OAAQ,CAAEC,IAAKrB,EAAKkB,QACpBV,MAAO,CACLC,CAAE,0CACFhB,GAAO6B,aAAaC,oBAIxBT,EAAAC,IAACS,OAAI,CACHhB,MAAO,CACLC,CAAE,wGACFhB,GAAO6B,aAAaG,iBACpBf,SAEDV,EAAK0B,MAAMC,OAAO,MAxBlB3B,EAAKC,MA6BbI,EAAkB,GACjBS,EAAAC,IAACR,OAAI,CACHC,MAAO,CACLC,CAAE,+DACF,CACEO,YAAe,GACfC,OAAQ,GAEV,IAAKxB,GAAO6B,aAAaM,sCACzBlB,SAEFJ,EAAAK,KAACa,OAAI,CACHhB,MAAO,CACLC,CAAE,mCACFhB,GAAO6B,aAAaO,gCACpBnB,SAAA,CACH,IACGL,UAMXT,GACCkB,EAAAC,IAACe,wBAAqB,CACpBtB,MAAOC,EAAGD,MACR,oDACA,CACEuB,UAAW,CAAC,CAAEC,OAAQ,UAAY,CAAEC,WAAY,MAGpDC,MAAO,GAAGzC,GAAO0C,QAAQC,0BAA4B,YAIzDtB,EAAAC,IAACR,OAAI,CACHC,MAAO,CACLC,CAAE,gDACFhB,GAAO6B,aAAae,sBACpB3B,SAEDf,EACCA,IAEAmB,EAAAA,IAACP,EAAAA,KAAI,CAACC,MAAOC,CAAE,iDAAiDC,SAC9DI,EAAAC,IAACS,OAAI,CAAChB,MAAOC,CAAE,gBAAgBC,SAAC,oBAIjC"}
@@ -1,2 +1,2 @@
1
- import e,{Path as o}from"react-native-svg";import{jsx as r}from"react/jsx-runtime";const t=({style:t,color:i})=>r(e,{style:t,fill:i,viewBox:"0 0 48 48",children:r(o,{fillRule:"evenodd",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"4",d:"M8 9.115c0-1.82 2.235-2.694 3.47-1.356l29.432 31.884c1.182 1.282.273 3.357-1.47 3.357H10a2 2 0 0 1-2-2z",clipRule:"evenodd"})});export{t as ArrowBack2RoundedIcon};
1
+ import e,{Path as o}from"react-native-svg";import{jsx as r}from"react/jsx-runtime";const t=({style:t,color:i})=>r(e,{style:t,viewBox:"0 0 48 48",children:r(o,{fill:i,fillRule:"evenodd",stroke:i,strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"4",d:"M8 9.115c0-1.82 2.235-2.694 3.47-1.356l29.432 31.884c1.182 1.282.273 3.357-1.47 3.357H10a2 2 0 0 1-2-2z",clipRule:"evenodd"})});export{t as ArrowBack2RoundedIcon};
2
2
  //# sourceMappingURL=ArrowBack2RoundedIcon.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ArrowBack2RoundedIcon.js","sources":["../../../../src/assets/Icons/ArrowBack2RoundedIcon.tsx"],"sourcesContent":["\nimport { ViewStyle } from \"react-native\";\nimport Svg, { Path } from \"react-native-svg\";\n\nexport const ArrowBack2RoundedIcon = ({\n style,\n color,\n}: {\n style?: ViewStyle;\n color?: string;\n}) => {\n return (\n <Svg style={style} fill={color} viewBox=\"0 0 48 48\">\n <Path\n fillRule=\"evenodd\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"4\"\n d=\"M8 9.115c0-1.82 2.235-2.694 3.47-1.356l29.432 31.884c1.182 1.282.273 3.357-1.47 3.357H10a2 2 0 0 1-2-2z\"\n clipRule=\"evenodd\"\n ></Path>\n </Svg>\n );\n};\n"],"names":["ArrowBack2RoundedIcon","style","color","_jsx","Svg","fill","viewBox","children","Path","fillRule","stroke","strokeLinecap","strokeLinejoin","strokeWidth","d","clipRule"],"mappings":"mFAIO,MAAMA,EAAwBA,EACnCC,QACAC,WAMEC,EAACC,EAAG,CAACH,MAAOA,EAAOI,KAAMH,EAAOI,QAAQ,YAAWC,SACjDJ,EAACK,EAAI,CACHC,SAAS,UACTC,OAAO,eACPC,cAAc,QACdC,eAAe,QACfC,YAAY,IACZC,EAAE,0GACFC,SAAS"}
1
+ {"version":3,"file":"ArrowBack2RoundedIcon.js","sources":["../../../../src/assets/Icons/ArrowBack2RoundedIcon.tsx"],"sourcesContent":["import { ViewStyle } from 'react-native';\nimport Svg, { Path } from 'react-native-svg';\n\nexport const ArrowBack2RoundedIcon = ({\n style,\n color,\n}: {\n style?: ViewStyle;\n color?: string;\n}) => {\n return (\n <Svg style={style} viewBox=\"0 0 48 48\">\n <Path\n fill={color}\n fillRule=\"evenodd\"\n stroke={color}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"4\"\n d=\"M8 9.115c0-1.82 2.235-2.694 3.47-1.356l29.432 31.884c1.182 1.282.273 3.357-1.47 3.357H10a2 2 0 0 1-2-2z\"\n clipRule=\"evenodd\"\n ></Path>\n </Svg>\n );\n};\n"],"names":["ArrowBack2RoundedIcon","style","color","_jsx","Svg","viewBox","children","Path","fill","fillRule","stroke","strokeLinecap","strokeLinejoin","strokeWidth","d","clipRule"],"mappings":"mFAGO,MAAMA,EAAwBA,EACnCC,QACAC,WAMEC,EAACC,EAAG,CAACH,MAAOA,EAAOI,QAAQ,YAAWC,SACpCH,EAACI,EAAI,CACHC,KAAMN,EACNO,SAAS,UACTC,OAAQR,EACRS,cAAc,QACdC,eAAe,QACfC,YAAY,IACZC,EAAE,0GACFC,SAAS"}
@@ -1,2 +1,2 @@
1
- import e from"react";import{Pressable as t,View as r,Image as s,Text as o}from"react-native";import l from"twrnc";import{ArrowBack2RoundedIcon as a}from"../../assets/Icons/ArrowBack2RoundedIcon.js";import{useChatContext as i}from"../../context/ChatContext.js";import n from"./MessageContent.js";import d from"./MessageStatus.js";import{jsxs as m,jsx as u,Fragment as c}from"react/jsx-runtime";const b=({message:e,isCurrentUser:b,isFirstInSequence:g,onLongPress:f})=>{const{theme:h,showAvatars:y,showUserNames:p,showBubbleTail:x,setMediaUrl:v,setIsVideoPlaying:w,isVideoPlaying:S}=i();return m(t,{onLongPress:f,style:[l`px-2 my-1 max-w-[75%] relative`,b?l`self-end mr-3`:l`self-start ml-9`,g?b?l`bg-green-500 rounded-tr-none`:l`bg-white rounded-tl-none`:b?l`bg-green-500`:l`bg-white`,{borderRadius:8,...b?h?.bubbleStyle?.sent:h?.bubbleStyle?.received}],children:[!b&&g&&y&&m(c,{children:[u(r,{style:l`absolute w-6 h-6 rounded-full top-0 -left-9 flex-row items-center`,children:e.senderAvatar?u(s,{source:{uri:e.senderAvatar},style:[l`w-full h-full rounded-full`,h?.bubbleStyle?.avatarImageStyle],resizeMode:"cover"}):u(o,{style:[l`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,h?.bubbleStyle?.avatarTextStyle],children:e.senderName?.charAt(0)})}),p&&e.senderName&&u(o,{style:[l`text-sm text-black font-semibold mt-1 capitalize`,h?.bubbleStyle?.userNameStyle],children:e.senderName})]}),g&&x&&u(a,{style:l.style("absolute -top-1 w-6 h-6",b?"-right-3.5":"-left-3.5 mt-[1.25px]",{transform:[{rotate:b?"90deg":"180deg"}]}),color:b?`${h?.colors?.sentMessageTailColor||"rgba(34, 197, 94,1)"}`:`${h?.colors?.receivedMessageTailColor||"white"}`}),u(n,{message:e,isCurrentUser:b,isFirstInSequence:g,onMediaPress:(e,t)=>{v({imageUrl:"image"===e?t:"",videoUrl:"video"===e?t:""}),"video"===e&&w(!0)},isVideoPlaying:S}),u(d,{time:e.time,status:b?e.status:void 0,isCurrentUser:b,hasText:!!e.text,hasAudio:!!e.audio})]})};var g=e.memo(b);export{g as default};
1
+ import e from"react";import{Pressable as t,View as r,Image as s,Text as o}from"react-native";import l from"twrnc";import{ArrowBack2RoundedIcon as a}from"../../assets/Icons/ArrowBack2RoundedIcon.js";import{useChatContext as i}from"../../context/ChatContext.js";import n from"./MessageContent.js";import d from"./MessageStatus.js";import{jsxs as m,jsx as u,Fragment as c}from"react/jsx-runtime";const b=({message:e,isCurrentUser:b,isFirstInSequence:g,onLongPress:f})=>{const{theme:h,showAvatars:y,showUserNames:p,showBubbleTail:x,setMediaUrl:v,setIsVideoPlaying:w,isVideoPlaying:S}=i();return m(t,{onLongPress:f,style:[l`px-2 my-1 max-w-[75%] relative`,b?l`self-end mr-3`:l`self-start ml-9`,g?b?l`bg-green-500 rounded-tr-none`:l`bg-white rounded-tl-none`:b?l`bg-green-500`:l`bg-white`,{borderRadius:8,...b?h?.bubbleStyle?.sent:h?.bubbleStyle?.received}],children:[!b&&g&&y&&m(c,{children:[u(r,{style:l`absolute w-6 h-6 rounded-full top-0 -left-9 flex-row items-center`,children:e.senderAvatar?u(s,{source:{uri:e.senderAvatar},style:[l`w-full h-full rounded-full`,h?.bubbleStyle?.avatarImageStyle],resizeMode:"cover"}):u(o,{style:[l`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,h?.bubbleStyle?.avatarTextStyle],children:e.senderName?.charAt(0)})}),p&&e.senderName&&u(o,{style:[l`text-sm text-black font-semibold mt-1 capitalize`,h?.bubbleStyle?.userNameStyle],children:e.senderName})]}),g&&x&&u(a,{style:l.style("absolute -top-1 w-6 h-6 stroke-transparent",b?"-right-3.5":"-left-3.5 mt-[1.25px]",{transform:[{rotate:b?"90deg":"180deg"}]}),color:b?`${h?.colors?.sentMessageTailColor||"rgba(34, 197, 94,1)"}`:`${h?.colors?.receivedMessageTailColor||"white"}`}),u(n,{message:e,isCurrentUser:b,isFirstInSequence:g,onMediaPress:(e,t)=>{v({imageUrl:"image"===e?t:"",videoUrl:"video"===e?t:""}),"video"===e&&w(!0)},isVideoPlaying:S}),u(d,{time:e.time,status:b?e.status:void 0,isCurrentUser:b,hasText:!!e.text,hasAudio:!!e.audio})]})};var g=e.memo(b);export{g as default};
2
2
  //# sourceMappingURL=ChatBubble.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatBubble.js","sources":["../../../../src/components/ChatBubble/ChatBubble.tsx"],"sourcesContent":["import React from 'react';\nimport { Image, Pressable, Text, View } from 'react-native';\nimport tw from 'twrnc';\nimport { ArrowBack2RoundedIcon } from '../../assets/Icons/ArrowBack2RoundedIcon';\nimport { useChatContext } from '../../context/ChatContext';\nimport MessageContent from './MessageContent';\nimport MessageStatus from './MessageStatus';\nimport { ChatBubbleProps } from './types';\n\nconst ChatBubble: React.FC<ChatBubbleProps> = ({\n message,\n isCurrentUser,\n isFirstInSequence,\n onLongPress,\n}) => {\n const {\n theme,\n showAvatars,\n showUserNames,\n showBubbleTail,\n setMediaUrl,\n setIsVideoPlaying,\n isVideoPlaying,\n } = useChatContext();\n\n const handleMediaPress = (type: 'image' | 'video', url: string) => {\n setMediaUrl({\n imageUrl: type === 'image' ? url : '',\n videoUrl: type === 'video' ? url : '',\n });\n if (type === 'video') {\n setIsVideoPlaying(true);\n }\n };\n\n return (\n <Pressable\n onLongPress={onLongPress}\n style={[\n tw`px-2 my-1 max-w-[75%] relative`,\n isCurrentUser ? tw`self-end mr-3` : tw`self-start ml-9`,\n isFirstInSequence\n ? isCurrentUser\n ? tw`bg-green-500 rounded-tr-none`\n : tw`bg-white rounded-tl-none`\n : isCurrentUser\n ? tw`bg-green-500`\n : tw`bg-white`,\n {\n borderRadius: 8,\n ...(isCurrentUser\n ? theme?.bubbleStyle?.sent\n : theme?.bubbleStyle?.received),\n },\n ]}\n >\n {/* Avatar & Sender Name for Group Chat */}\n {!isCurrentUser && isFirstInSequence && showAvatars && (\n <>\n <View\n style={tw`absolute w-6 h-6 rounded-full top-0 -left-9 flex-row items-center`}\n >\n {message.senderAvatar ? (\n <Image\n source={{ uri: message.senderAvatar }}\n style={[\n tw`w-full h-full rounded-full`,\n theme?.bubbleStyle?.avatarImageStyle,\n ]}\n resizeMode=\"cover\"\n />\n ) : (\n <Text\n style={[\n tw`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,\n theme?.bubbleStyle?.avatarTextStyle,\n ]}\n >\n {message.senderName?.charAt(0)}\n </Text>\n )}\n </View>\n {showUserNames && message.senderName && (\n <Text\n style={[\n tw`text-sm text-black font-semibold mt-1 capitalize`,\n theme?.bubbleStyle?.userNameStyle,\n ]}\n >\n {message.senderName}\n </Text>\n )}\n </>\n )}\n\n {/* Bubble Tail */}\n {isFirstInSequence && showBubbleTail && (\n <ArrowBack2RoundedIcon\n style={tw.style(\n 'absolute -top-1 w-6 h-6',\n isCurrentUser ? '-right-3.5' : '-left-3.5 mt-[1.25px]',\n {\n transform: [{ rotate: isCurrentUser ? '90deg' : '180deg' }],\n }\n )}\n color={\n isCurrentUser\n ? `${\n theme?.colors?.sentMessageTailColor || 'rgba(34, 197, 94,1)'\n }`\n : `${theme?.colors?.receivedMessageTailColor || 'white'}`\n }\n />\n )}\n\n {/* Message Content */}\n <MessageContent\n message={message}\n isCurrentUser={isCurrentUser}\n isFirstInSequence={isFirstInSequence}\n onMediaPress={handleMediaPress}\n isVideoPlaying={isVideoPlaying}\n />\n\n {/* Message Status */}\n <MessageStatus\n time={message.time}\n status={isCurrentUser ? message.status : undefined}\n isCurrentUser={isCurrentUser}\n hasText={!!message.text}\n hasAudio={!!message.audio}\n />\n </Pressable>\n );\n};\n\nexport default React.memo(ChatBubble);\n"],"names":["ChatBubble","message","isCurrentUser","isFirstInSequence","onLongPress","theme","showAvatars","showUserNames","showBubbleTail","setMediaUrl","setIsVideoPlaying","isVideoPlaying","useChatContext","_jsxs","Pressable","style","tw","borderRadius","bubbleStyle","sent","received","children","_Fragment","_jsx","View","senderAvatar","Image","source","uri","avatarImageStyle","resizeMode","Text","avatarTextStyle","senderName","charAt","userNameStyle","ArrowBack2RoundedIcon","transform","rotate","color","colors","sentMessageTailColor","receivedMessageTailColor","MessageContent","onMediaPress","handleMediaPress","type","url","imageUrl","videoUrl","MessageStatus","time","status","undefined","hasText","text","hasAudio","audio","ChatBubble$1","React","memo"],"mappings":"yYASA,MAAMA,EAAwCA,EAC5CC,UACAC,gBACAC,oBACAC,kBAEA,MAAMC,MACJA,EAAKC,YACLA,EAAWC,cACXA,EAAaC,eACbA,EAAcC,YACdA,EAAWC,kBACXA,EAAiBC,eACjBA,GACEC,IAYJ,OACEC,EAACC,EAAS,CACRV,YAAaA,EACbW,MAAO,CACLC,CAAE,iCACFd,EAAgBc,CAAE,gBAAkBA,CAAE,kBACtCb,EACID,EACEc,CAAE,+BACFA,CAAE,2BACJd,EACEc,CAAE,eACFA,CAAE,WACR,CACEC,aAAc,KACVf,EACAG,GAAOa,aAAaC,KACpBd,GAAOa,aAAaE,WAE1BC,SAAA,EAGAnB,GAAiBC,GAAqBG,GACtCO,EAAAS,EAAA,CAAAD,SAAA,CACEE,EAACC,EAAI,CACHT,MAAOC,CAAE,oEAAoEK,SAE5EpB,EAAQwB,aACPF,EAACG,EAAK,CACJC,OAAQ,CAAEC,IAAK3B,EAAQwB,cACvBV,MAAO,CACLC,CAAE,6BACFX,GAAOa,aAAaW,kBAEtBC,WAAW,UAGbP,EAACQ,EAAI,CACHhB,MAAO,CACLC,CAAE,wGACFX,GAAOa,aAAac,iBACpBX,SAEDpB,EAAQgC,YAAYC,OAAO,OAIjC3B,GAAiBN,EAAQgC,YACxBV,EAACQ,EAAI,CACHhB,MAAO,CACLC,CAAE,mDACFX,GAAOa,aAAaiB,eACpBd,SAEDpB,EAAQgC,gBAOhB9B,GAAqBK,GACpBe,EAACa,EAAqB,CACpBrB,MAAOC,EAAGD,MACR,0BACAb,EAAgB,aAAe,wBAC/B,CACEmC,UAAW,CAAC,CAAEC,OAAQpC,EAAgB,QAAU,aAGpDqC,MACErC,EACI,GACEG,GAAOmC,QAAQC,sBAAwB,wBAEzC,GAAGpC,GAAOmC,QAAQE,0BAA4B,YAMxDnB,EAACoB,EAAc,CACb1C,QAASA,EACTC,cAAeA,EACfC,kBAAmBA,EACnByC,aA/FmBC,CAACC,EAAyBC,KACjDtC,EAAY,CACVuC,SAAmB,UAATF,EAAmBC,EAAM,GACnCE,SAAmB,UAATH,EAAmBC,EAAM,KAExB,UAATD,GACFpC,GAAkB,EACpB,EAyFIC,eAAgBA,IAIlBY,EAAC2B,EAAa,CACZC,KAAMlD,EAAQkD,KACdC,OAAQlD,EAAgBD,EAAQmD,YAASC,EACzCnD,cAAeA,EACfoD,UAAWrD,EAAQsD,KACnBC,WAAYvD,EAAQwD,UAEZ,EAIhB,IAAAC,EAAeC,EAAMC,KAAK5D"}
1
+ {"version":3,"file":"ChatBubble.js","sources":["../../../../src/components/ChatBubble/ChatBubble.tsx"],"sourcesContent":["import React from 'react';\nimport { Image, Pressable, Text, View } from 'react-native';\nimport tw from 'twrnc';\nimport { ArrowBack2RoundedIcon } from '../../assets/Icons/ArrowBack2RoundedIcon';\nimport { useChatContext } from '../../context/ChatContext';\nimport MessageContent from './MessageContent';\nimport MessageStatus from './MessageStatus';\nimport { ChatBubbleProps } from './types';\n\nconst ChatBubble: React.FC<ChatBubbleProps> = ({\n message,\n isCurrentUser,\n isFirstInSequence,\n onLongPress,\n}) => {\n const {\n theme,\n showAvatars,\n showUserNames,\n showBubbleTail,\n setMediaUrl,\n setIsVideoPlaying,\n isVideoPlaying,\n } = useChatContext();\n\n const handleMediaPress = (type: 'image' | 'video', url: string) => {\n setMediaUrl({\n imageUrl: type === 'image' ? url : '',\n videoUrl: type === 'video' ? url : '',\n });\n if (type === 'video') {\n setIsVideoPlaying(true);\n }\n };\n\n return (\n <Pressable\n onLongPress={onLongPress}\n style={[\n tw`px-2 my-1 max-w-[75%] relative`,\n isCurrentUser ? tw`self-end mr-3` : tw`self-start ml-9`,\n isFirstInSequence\n ? isCurrentUser\n ? tw`bg-green-500 rounded-tr-none`\n : tw`bg-white rounded-tl-none`\n : isCurrentUser\n ? tw`bg-green-500`\n : tw`bg-white`,\n {\n borderRadius: 8,\n ...(isCurrentUser\n ? theme?.bubbleStyle?.sent\n : theme?.bubbleStyle?.received),\n },\n ]}\n >\n {/* Avatar & Sender Name for Group Chat */}\n {!isCurrentUser && isFirstInSequence && showAvatars && (\n <>\n <View\n style={tw`absolute w-6 h-6 rounded-full top-0 -left-9 flex-row items-center`}\n >\n {message.senderAvatar ? (\n <Image\n source={{ uri: message.senderAvatar }}\n style={[\n tw`w-full h-full rounded-full`,\n theme?.bubbleStyle?.avatarImageStyle,\n ]}\n resizeMode=\"cover\"\n />\n ) : (\n <Text\n style={[\n tw`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,\n theme?.bubbleStyle?.avatarTextStyle,\n ]}\n >\n {message.senderName?.charAt(0)}\n </Text>\n )}\n </View>\n {showUserNames && message.senderName && (\n <Text\n style={[\n tw`text-sm text-black font-semibold mt-1 capitalize`,\n theme?.bubbleStyle?.userNameStyle,\n ]}\n >\n {message.senderName}\n </Text>\n )}\n </>\n )}\n\n {/* Bubble Tail */}\n {isFirstInSequence && showBubbleTail && (\n <ArrowBack2RoundedIcon\n style={tw.style(\n 'absolute -top-1 w-6 h-6 stroke-transparent',\n isCurrentUser ? '-right-3.5' : '-left-3.5 mt-[1.25px]',\n {\n transform: [{ rotate: isCurrentUser ? '90deg' : '180deg' }],\n }\n )}\n color={\n isCurrentUser\n ? `${\n theme?.colors?.sentMessageTailColor || 'rgba(34, 197, 94,1)'\n }`\n : `${theme?.colors?.receivedMessageTailColor || 'white'}`\n }\n />\n )}\n\n {/* Message Content */}\n <MessageContent\n message={message}\n isCurrentUser={isCurrentUser}\n isFirstInSequence={isFirstInSequence}\n onMediaPress={handleMediaPress}\n isVideoPlaying={isVideoPlaying}\n />\n\n {/* Message Status */}\n <MessageStatus\n time={message.time}\n status={isCurrentUser ? message.status : undefined}\n isCurrentUser={isCurrentUser}\n hasText={!!message.text}\n hasAudio={!!message.audio}\n />\n </Pressable>\n );\n};\n\nexport default React.memo(ChatBubble);\n"],"names":["ChatBubble","message","isCurrentUser","isFirstInSequence","onLongPress","theme","showAvatars","showUserNames","showBubbleTail","setMediaUrl","setIsVideoPlaying","isVideoPlaying","useChatContext","_jsxs","Pressable","style","tw","borderRadius","bubbleStyle","sent","received","children","_Fragment","_jsx","View","senderAvatar","Image","source","uri","avatarImageStyle","resizeMode","Text","avatarTextStyle","senderName","charAt","userNameStyle","ArrowBack2RoundedIcon","transform","rotate","color","colors","sentMessageTailColor","receivedMessageTailColor","MessageContent","onMediaPress","handleMediaPress","type","url","imageUrl","videoUrl","MessageStatus","time","status","undefined","hasText","text","hasAudio","audio","ChatBubble$1","React","memo"],"mappings":"yYASA,MAAMA,EAAwCA,EAC5CC,UACAC,gBACAC,oBACAC,kBAEA,MAAMC,MACJA,EAAKC,YACLA,EAAWC,cACXA,EAAaC,eACbA,EAAcC,YACdA,EAAWC,kBACXA,EAAiBC,eACjBA,GACEC,IAYJ,OACEC,EAACC,EAAS,CACRV,YAAaA,EACbW,MAAO,CACLC,CAAE,iCACFd,EAAgBc,CAAE,gBAAkBA,CAAE,kBACtCb,EACID,EACEc,CAAE,+BACFA,CAAE,2BACJd,EACEc,CAAE,eACFA,CAAE,WACR,CACEC,aAAc,KACVf,EACAG,GAAOa,aAAaC,KACpBd,GAAOa,aAAaE,WAE1BC,SAAA,EAGAnB,GAAiBC,GAAqBG,GACtCO,EAAAS,EAAA,CAAAD,SAAA,CACEE,EAACC,EAAI,CACHT,MAAOC,CAAE,oEAAoEK,SAE5EpB,EAAQwB,aACPF,EAACG,EAAK,CACJC,OAAQ,CAAEC,IAAK3B,EAAQwB,cACvBV,MAAO,CACLC,CAAE,6BACFX,GAAOa,aAAaW,kBAEtBC,WAAW,UAGbP,EAACQ,EAAI,CACHhB,MAAO,CACLC,CAAE,wGACFX,GAAOa,aAAac,iBACpBX,SAEDpB,EAAQgC,YAAYC,OAAO,OAIjC3B,GAAiBN,EAAQgC,YACxBV,EAACQ,EAAI,CACHhB,MAAO,CACLC,CAAE,mDACFX,GAAOa,aAAaiB,eACpBd,SAEDpB,EAAQgC,gBAOhB9B,GAAqBK,GACpBe,EAACa,EAAqB,CACpBrB,MAAOC,EAAGD,MACR,6CACAb,EAAgB,aAAe,wBAC/B,CACEmC,UAAW,CAAC,CAAEC,OAAQpC,EAAgB,QAAU,aAGpDqC,MACErC,EACI,GACEG,GAAOmC,QAAQC,sBAAwB,wBAEzC,GAAGpC,GAAOmC,QAAQE,0BAA4B,YAMxDnB,EAACoB,EAAc,CACb1C,QAASA,EACTC,cAAeA,EACfC,kBAAmBA,EACnByC,aA/FmBC,CAACC,EAAyBC,KACjDtC,EAAY,CACVuC,SAAmB,UAATF,EAAmBC,EAAM,GACnCE,SAAmB,UAATH,EAAmBC,EAAM,KAExB,UAATD,GACFpC,GAAkB,EACpB,EAyFIC,eAAgBA,IAIlBY,EAAC2B,EAAa,CACZC,KAAMlD,EAAQkD,KACdC,OAAQlD,EAAgBD,EAAQmD,YAASC,EACzCnD,cAAeA,EACfoD,UAAWrD,EAAQsD,KACnBC,WAAYvD,EAAQwD,UAEZ,EAIhB,IAAAC,EAAeC,EAAMC,KAAK5D"}
@@ -1,2 +1,2 @@
1
- import e from"react";import{View as t,Pressable as o,Image as r,Text as i}from"react-native";import s from"react-native-video";import l from"twrnc";import{LoadingIcon as a}from"../../assets/Icons/LoadingIcon.js";import{PlayIcon as d}from"../../assets/Icons/PlayIcon.js";import{useChatContext as n}from"../../context/ChatContext.js";import{formatDuration as u}from"../../utils/datefunc.js";import c from"../AudioPlayer/AudioPlayer.js";import{jsxs as m,jsx as y,Fragment as f}from"react/jsx-runtime";const h=({message:h,onMediaPress:b,isVideoPlaying:p})=>{const{theme:g,showMessageStatus:w,CustomPlayIcon:x,renderCustomVideoBubbleError:v}=n(),j=e.useRef(null),[P,I]=e.useState(0),[S,k]=e.useState(!1),[C,B]=e.useState(!1);return m(t,{children:[h.image&&y(o,{onPress:()=>b("image",h.image),style:l`w-60 h-80 my-2`,children:y(r,{source:{uri:h.image},style:l`w-full h-full object-contain rounded-lg`})}),h.video&&m(o,{onPress:()=>b("video",h.video),style:l`w-60 h-80 my-2 justify-center items-center`,disabled:S,children:[y(s,{source:{uri:h.video},ref:j,paused:!0,style:{width:"100%",height:"100%",borderRadius:8,position:"relative"},resizeMode:"cover",onLoadStart:()=>{k(!0),B(!1)},onLoad:e=>{I(e.duration),k(!1)},onBuffer:({isBuffering:e})=>k(e),onError:()=>{B(!0),k(!1)}}),S?y(t,{style:l`absolute inset-0 flex items-center justify-center bg-black/40 rounded-full`,children:y(a,{style:l.style("h-12 w-12 fill-white animate-spin")})}):C?v?v():y(t,{style:l`absolute inset-0 flex items-center justify-center bg-red-500/60 p-2`,children:y(i,{style:l`text-white font-bold`,children:"Failed to load video"})}):m(f,{children:[y(t,{style:l`absolute bg-black/40 rounded-full`,children:x?y(x,{}):y(d,{style:l.style("h-16 w-16"),color:g?.colors?.audioPlayIconColor||"white"})}),y(t,{style:l`absolute bottom-2 left-2 bg-black/50 px-2 py-1 rounded-md`,children:y(i,{style:l`text-white text-xs font-semibold`,children:u(P)})})]})]}),h.audio&&y(t,{style:l`my-2`,children:y(c,{audioUrl:h.audio,audioId:h.id,isVideoPlaying:p})}),h.text&&y(i,{style:[l`text-gray-800 pt-1`,w?l`pb-0`:l`pb-2`,{wordBreak:"break-word",overflowWrap:"break-word"},g?.messageStyle?.textStyle],children:h.text})]})};var b=e.memo(h);export{b as default};
1
+ import e from"react";import{View as t,Pressable as o,Image as r,Text as i}from"react-native";import s from"react-native-video";import l from"twrnc";import{LoadingIcon as a}from"../../assets/Icons/LoadingIcon.js";import{PlayIcon as d}from"../../assets/Icons/PlayIcon.js";import{useChatContext as n}from"../../context/ChatContext.js";import{formatDuration as u}from"../../utils/datefunc.js";import c from"../AudioPlayer/AudioPlayer.js";import{jsxs as m,jsx as y,Fragment as f}from"react/jsx-runtime";const h=({message:h,onMediaPress:b,isVideoPlaying:p,isCurrentUser:g})=>{const{theme:w,showMessageStatus:x,CustomPlayIcon:v,renderCustomVideoBubbleError:j}=n(),P=e.useRef(null),[S,I]=e.useState(0),[k,C]=e.useState(!1),[B,L]=e.useState(!1);return m(t,{children:[h.image&&y(o,{onPress:()=>b("image",h.image),style:l`w-60 h-80 my-2`,children:y(r,{source:{uri:h.image},style:l`w-full h-full object-contain rounded-lg`})}),h.video&&m(o,{onPress:()=>b("video",h.video),style:l`w-60 h-80 my-2 justify-center items-center`,disabled:k,children:[y(s,{source:{uri:h.video},ref:P,paused:!0,style:{width:"100%",height:"100%",borderRadius:8,position:"relative"},resizeMode:"cover",onLoadStart:()=>{C(!0),L(!1)},onLoad:e=>{I(e.duration),C(!1)},onBuffer:({isBuffering:e})=>C(e),onError:()=>{L(!0),C(!1)}}),k?y(t,{style:l`absolute inset-0 flex items-center justify-center bg-black/40 rounded-full`,children:y(a,{style:l.style("h-12 w-12 fill-white animate-spin")})}):B?j?j():y(t,{style:l`absolute inset-0 flex items-center justify-center bg-red-500/60 p-2`,children:y(i,{style:l`text-white font-bold`,children:"Failed to load video"})}):m(f,{children:[y(t,{style:l`absolute bg-black/40 rounded-full`,children:v?y(v,{}):y(d,{style:l.style("h-16 w-16"),color:w?.colors?.audioPlayIconColor||"white"})}),y(t,{style:l`absolute bottom-2 left-2 bg-black/50 px-2 py-1 rounded-md`,children:y(i,{style:l`text-white text-xs font-semibold`,children:u(S)})})]})]}),h.audio&&y(t,{style:l`my-2`,children:y(c,{audioUrl:h.audio,audioId:h.id,isVideoPlaying:p})}),h.text&&y(i,{style:[l`pt-1`,x?l`pb-0`:l`pb-2`,{wordBreak:"break-word",overflowWrap:"break-word"},g?w?.messageStyle?.sentTextStyle:w?.messageStyle?.receivedTextStyle],children:h.text})]})};var b=e.memo(h);export{b as default};
2
2
  //# sourceMappingURL=MessageContent.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MessageContent.js","sources":["../../../../src/components/ChatBubble/MessageContent.tsx"],"sourcesContent":["import React from 'react';\nimport { Image, Pressable, Text, View } from 'react-native';\nimport Video, { VideoRef } from 'react-native-video';\nimport tw from 'twrnc';\nimport { LoadingIcon } from '../../assets/Icons/LoadingIcon';\nimport { PlayIcon } from '../../assets/Icons/PlayIcon';\nimport { useChatContext } from '../../context/ChatContext';\nimport { formatDuration } from '../../utils/datefunc';\nimport AudioPlayer from '../AudioPlayer/AudioPlayer';\nimport { MessageContentProps } from './types';\n\nconst MessageContent: React.FC<MessageContentProps> = ({\n message,\n onMediaPress,\n isVideoPlaying,\n}) => {\n const {\n theme,\n showMessageStatus,\n CustomPlayIcon,\n renderCustomVideoBubbleError,\n } = useChatContext();\n const videoRef = React.useRef<VideoRef>(null);\n const [duration, setDuration] = React.useState(0);\n const [videoIsLoading, setVideoIsLoading] = React.useState(false);\n const [videoHasError, setVideoHasError] = React.useState(false);\n\n return (\n <View>\n {message.image && (\n <Pressable\n onPress={() => onMediaPress('image', message.image as string)}\n style={tw`w-60 h-80 my-2`}\n >\n <Image\n source={{ uri: message.image }}\n style={tw`w-full h-full object-contain rounded-lg`}\n />\n </Pressable>\n )}\n\n {message.video && (\n <Pressable\n onPress={() => onMediaPress('video', message.video as string)}\n style={tw`w-60 h-80 my-2 justify-center items-center`}\n disabled={videoIsLoading}\n >\n <Video\n source={{ uri: message.video }}\n ref={videoRef}\n paused={true}\n style={{\n width: '100%',\n height: '100%',\n borderRadius: 8,\n position: 'relative',\n }}\n resizeMode=\"cover\"\n onLoadStart={() => {\n setVideoIsLoading(true);\n setVideoHasError(false);\n }}\n onLoad={(data) => {\n setDuration(data.duration);\n setVideoIsLoading(false);\n }}\n onBuffer={({ isBuffering }) => setVideoIsLoading(isBuffering)}\n onError={() => {\n setVideoHasError(true);\n setVideoIsLoading(false);\n }}\n />\n {videoIsLoading ? (\n <View\n style={tw`absolute inset-0 flex items-center justify-center bg-black/40 rounded-full`}\n >\n <LoadingIcon\n style={tw.style('h-12 w-12 fill-white animate-spin')}\n />\n </View>\n ) : videoHasError ? (\n renderCustomVideoBubbleError ? (\n renderCustomVideoBubbleError()\n ) : (\n <View\n style={tw`absolute inset-0 flex items-center justify-center bg-red-500/60 p-2`}\n >\n <Text style={tw`text-white font-bold`}>\n Failed to load video\n </Text>\n </View>\n )\n ) : (\n <>\n <View style={tw`absolute bg-black/40 rounded-full`}>\n {CustomPlayIcon ? (\n <CustomPlayIcon />\n ) : (\n <PlayIcon\n style={tw.style('h-16 w-16')}\n color={theme?.colors?.audioPlayIconColor || 'white'}\n />\n )}\n </View>\n <View\n style={tw`absolute bottom-2 left-2 bg-black/50 px-2 py-1 rounded-md`}\n >\n <Text style={tw`text-white text-xs font-semibold`}>\n {formatDuration(duration)}\n </Text>\n </View>\n </>\n )}\n </Pressable>\n )}\n\n {message.audio && (\n <View style={tw`my-2`}>\n <AudioPlayer\n audioUrl={message.audio}\n audioId={message.id}\n isVideoPlaying={isVideoPlaying as boolean}\n />\n </View>\n )}\n\n {message.text && (\n <Text\n style={[\n tw`text-gray-800 pt-1`,\n showMessageStatus ? tw`pb-0` : tw`pb-2`,\n { wordBreak: 'break-word', overflowWrap: 'break-word' },\n theme?.messageStyle?.textStyle,\n ]}\n >\n {message.text}\n </Text>\n )}\n </View>\n );\n};\n\nexport default React.memo(MessageContent);\n"],"names":["MessageContent","message","onMediaPress","isVideoPlaying","theme","showMessageStatus","CustomPlayIcon","renderCustomVideoBubbleError","useChatContext","videoRef","React","useRef","duration","setDuration","useState","videoIsLoading","setVideoIsLoading","videoHasError","setVideoHasError","_jsxs","View","children","image","_jsx","Pressable","onPress","style","tw","Image","source","uri","video","disabled","Video","ref","paused","width","height","borderRadius","position","resizeMode","onLoadStart","onLoad","data","onBuffer","isBuffering","onError","LoadingIcon","Text","_Fragment","PlayIcon","color","colors","audioPlayIconColor","formatDuration","audio","AudioPlayer","audioUrl","audioId","id","text","wordBreak","overflowWrap","messageStyle","textStyle","MessageContent$1","memo"],"mappings":"kfAWA,MAAMA,EAAgDA,EACpDC,UACAC,eACAC,qBAEA,MAAMC,MACJA,EAAKC,kBACLA,EAAiBC,eACjBA,EAAcC,6BACdA,GACEC,IACEC,EAAWC,EAAMC,OAAiB,OACjCC,EAAUC,GAAeH,EAAMI,SAAS,IACxCC,EAAgBC,GAAqBN,EAAMI,UAAS,IACpDG,EAAeC,GAAoBR,EAAMI,UAAS,GAEzD,OACEK,EAACC,EAAI,CAAAC,UACFpB,EAAQqB,OACPC,EAACC,EAAS,CACRC,QAASA,IAAMvB,EAAa,QAASD,EAAQqB,OAC7CI,MAAOC,CAAE,iBAAiBN,SAE1BE,EAACK,EAAK,CACJC,OAAQ,CAAEC,IAAK7B,EAAQqB,OACvBI,MAAOC,CAAE,8CAKd1B,EAAQ8B,OACPZ,EAACK,EAAS,CACRC,QAASA,IAAMvB,EAAa,QAASD,EAAQ8B,OAC7CL,MAAOC,CAAE,6CACTK,SAAUjB,EAAeM,SAAA,CAEzBE,EAACU,EAAK,CACJJ,OAAQ,CAAEC,IAAK7B,EAAQ8B,OACvBG,IAAKzB,EACL0B,QAAQ,EACRT,MAAO,CACLU,MAAO,OACPC,OAAQ,OACRC,aAAc,EACdC,SAAU,YAEZC,WAAW,QACXC,YAAaA,KACXzB,GAAkB,GAClBE,GAAiB,EAAM,EAEzBwB,OAASC,IACP9B,EAAY8B,EAAK/B,UACjBI,GAAkB,EAAM,EAE1B4B,SAAUA,EAAGC,iBAAkB7B,EAAkB6B,GACjDC,QAASA,KACP5B,GAAiB,GACjBF,GAAkB,EAAM,IAG3BD,EACCQ,EAACH,EAAI,CACHM,MAAOC,CAAE,6EAA6EN,SAEtFE,EAACwB,EAAW,CACVrB,MAAOC,EAAGD,MAAM,yCAGlBT,EACFV,EACEA,IAEAgB,EAACH,EAAI,CACHM,MAAOC,CAAE,sEAAsEN,SAE/EE,EAACyB,EAAI,CAACtB,MAAOC,CAAE,uBAAuBN,SAAC,2BAM3CF,EAAA8B,EAAA,CAAA5B,SAAA,CACEE,EAACH,EAAI,CAACM,MAAOC,CAAE,oCAAoCN,SAChDf,EACCiB,EAACjB,EAAc,CAAA,GAEfiB,EAAC2B,EAAQ,CACPxB,MAAOC,EAAGD,MAAM,aAChByB,MAAO/C,GAAOgD,QAAQC,oBAAsB,YAIlD9B,EAACH,EAAI,CACHM,MAAOC,CAAE,4DAA4DN,SAErEE,EAACyB,EAAI,CAACtB,MAAOC,CAAE,mCAAmCN,SAC/CiC,EAAe1C,aAQ3BX,EAAQsD,OACPhC,EAACH,EAAI,CAACM,MAAOC,CAAE,OAAON,SACpBE,EAACiC,EAAW,CACVC,SAAUxD,EAAQsD,MAClBG,QAASzD,EAAQ0D,GACjBxD,eAAgBA,MAKrBF,EAAQ2D,MACPrC,EAACyB,EAAI,CACHtB,MAAO,CACLC,CAAE,qBACFtB,EAAoBsB,CAAE,OAASA,CAAE,OACjC,CAAEkC,UAAW,aAAcC,aAAc,cACzC1D,GAAO2D,cAAcC,WACrB3C,SAEDpB,EAAQ2D,SAGR,EAIX,IAAAK,EAAevD,EAAMwD,KAAKlE"}
1
+ {"version":3,"file":"MessageContent.js","sources":["../../../../src/components/ChatBubble/MessageContent.tsx"],"sourcesContent":["import React from 'react';\nimport { Image, Pressable, Text, View } from 'react-native';\nimport Video, { VideoRef } from 'react-native-video';\nimport tw from 'twrnc';\nimport { LoadingIcon } from '../../assets/Icons/LoadingIcon';\nimport { PlayIcon } from '../../assets/Icons/PlayIcon';\nimport { useChatContext } from '../../context/ChatContext';\nimport { formatDuration } from '../../utils/datefunc';\nimport AudioPlayer from '../AudioPlayer/AudioPlayer';\nimport { MessageContentProps } from './types';\n\nconst MessageContent: React.FC<MessageContentProps> = ({\n message,\n onMediaPress,\n isVideoPlaying,\n isCurrentUser,\n}) => {\n const {\n theme,\n showMessageStatus,\n CustomPlayIcon,\n renderCustomVideoBubbleError,\n } = useChatContext();\n const videoRef = React.useRef<VideoRef>(null);\n const [duration, setDuration] = React.useState(0);\n const [videoIsLoading, setVideoIsLoading] = React.useState(false);\n const [videoHasError, setVideoHasError] = React.useState(false);\n\n return (\n <View>\n {message.image && (\n <Pressable\n onPress={() => onMediaPress('image', message.image as string)}\n style={tw`w-60 h-80 my-2`}\n >\n <Image\n source={{ uri: message.image }}\n style={tw`w-full h-full object-contain rounded-lg`}\n />\n </Pressable>\n )}\n\n {message.video && (\n <Pressable\n onPress={() => onMediaPress('video', message.video as string)}\n style={tw`w-60 h-80 my-2 justify-center items-center`}\n disabled={videoIsLoading}\n >\n <Video\n source={{ uri: message.video }}\n ref={videoRef}\n paused={true}\n style={{\n width: '100%',\n height: '100%',\n borderRadius: 8,\n position: 'relative',\n }}\n resizeMode=\"cover\"\n onLoadStart={() => {\n setVideoIsLoading(true);\n setVideoHasError(false);\n }}\n onLoad={(data) => {\n setDuration(data.duration);\n setVideoIsLoading(false);\n }}\n onBuffer={({ isBuffering }) => setVideoIsLoading(isBuffering)}\n onError={() => {\n setVideoHasError(true);\n setVideoIsLoading(false);\n }}\n />\n {videoIsLoading ? (\n <View\n style={tw`absolute inset-0 flex items-center justify-center bg-black/40 rounded-full`}\n >\n <LoadingIcon\n style={tw.style('h-12 w-12 fill-white animate-spin')}\n />\n </View>\n ) : videoHasError ? (\n renderCustomVideoBubbleError ? (\n renderCustomVideoBubbleError()\n ) : (\n <View\n style={tw`absolute inset-0 flex items-center justify-center bg-red-500/60 p-2`}\n >\n <Text style={tw`text-white font-bold`}>\n Failed to load video\n </Text>\n </View>\n )\n ) : (\n <>\n <View style={tw`absolute bg-black/40 rounded-full`}>\n {CustomPlayIcon ? (\n <CustomPlayIcon />\n ) : (\n <PlayIcon\n style={tw.style('h-16 w-16')}\n color={theme?.colors?.audioPlayIconColor || 'white'}\n />\n )}\n </View>\n <View\n style={tw`absolute bottom-2 left-2 bg-black/50 px-2 py-1 rounded-md`}\n >\n <Text style={tw`text-white text-xs font-semibold`}>\n {formatDuration(duration)}\n </Text>\n </View>\n </>\n )}\n </Pressable>\n )}\n\n {message.audio && (\n <View style={tw`my-2`}>\n <AudioPlayer\n audioUrl={message.audio}\n audioId={message.id}\n isVideoPlaying={isVideoPlaying as boolean}\n />\n </View>\n )}\n\n {message.text && (\n <Text\n style={[\n tw`pt-1`,\n showMessageStatus ? tw`pb-0` : tw`pb-2`,\n { wordBreak: 'break-word', overflowWrap: 'break-word' },\n isCurrentUser\n ? theme?.messageStyle?.sentTextStyle\n : theme?.messageStyle?.receivedTextStyle,\n ]}\n >\n {message.text}\n </Text>\n )}\n </View>\n );\n};\n\nexport default React.memo(MessageContent);\n"],"names":["MessageContent","message","onMediaPress","isVideoPlaying","isCurrentUser","theme","showMessageStatus","CustomPlayIcon","renderCustomVideoBubbleError","useChatContext","videoRef","React","useRef","duration","setDuration","useState","videoIsLoading","setVideoIsLoading","videoHasError","setVideoHasError","_jsxs","View","children","image","_jsx","Pressable","onPress","style","tw","Image","source","uri","video","disabled","Video","ref","paused","width","height","borderRadius","position","resizeMode","onLoadStart","onLoad","data","onBuffer","isBuffering","onError","LoadingIcon","Text","_Fragment","PlayIcon","color","colors","audioPlayIconColor","formatDuration","audio","AudioPlayer","audioUrl","audioId","id","text","wordBreak","overflowWrap","messageStyle","sentTextStyle","receivedTextStyle","MessageContent$1","memo"],"mappings":"kfAWA,MAAMA,EAAgDA,EACpDC,UACAC,eACAC,iBACAC,oBAEA,MAAMC,MACJA,EAAKC,kBACLA,EAAiBC,eACjBA,EAAcC,6BACdA,GACEC,IACEC,EAAWC,EAAMC,OAAiB,OACjCC,EAAUC,GAAeH,EAAMI,SAAS,IACxCC,EAAgBC,GAAqBN,EAAMI,UAAS,IACpDG,EAAeC,GAAoBR,EAAMI,UAAS,GAEzD,OACEK,EAACC,EAAI,CAAAC,UACFrB,EAAQsB,OACPC,EAACC,EAAS,CACRC,QAASA,IAAMxB,EAAa,QAASD,EAAQsB,OAC7CI,MAAOC,CAAE,iBAAiBN,SAE1BE,EAACK,EAAK,CACJC,OAAQ,CAAEC,IAAK9B,EAAQsB,OACvBI,MAAOC,CAAE,8CAKd3B,EAAQ+B,OACPZ,EAACK,EAAS,CACRC,QAASA,IAAMxB,EAAa,QAASD,EAAQ+B,OAC7CL,MAAOC,CAAE,6CACTK,SAAUjB,EAAeM,SAAA,CAEzBE,EAACU,EAAK,CACJJ,OAAQ,CAAEC,IAAK9B,EAAQ+B,OACvBG,IAAKzB,EACL0B,QAAQ,EACRT,MAAO,CACLU,MAAO,OACPC,OAAQ,OACRC,aAAc,EACdC,SAAU,YAEZC,WAAW,QACXC,YAAaA,KACXzB,GAAkB,GAClBE,GAAiB,EAAM,EAEzBwB,OAASC,IACP9B,EAAY8B,EAAK/B,UACjBI,GAAkB,EAAM,EAE1B4B,SAAUA,EAAGC,iBAAkB7B,EAAkB6B,GACjDC,QAASA,KACP5B,GAAiB,GACjBF,GAAkB,EAAM,IAG3BD,EACCQ,EAACH,EAAI,CACHM,MAAOC,CAAE,6EAA6EN,SAEtFE,EAACwB,EAAW,CACVrB,MAAOC,EAAGD,MAAM,yCAGlBT,EACFV,EACEA,IAEAgB,EAACH,EAAI,CACHM,MAAOC,CAAE,sEAAsEN,SAE/EE,EAACyB,EAAI,CAACtB,MAAOC,CAAE,uBAAuBN,SAAC,2BAM3CF,EAAA8B,EAAA,CAAA5B,SAAA,CACEE,EAACH,EAAI,CAACM,MAAOC,CAAE,oCAAoCN,SAChDf,EACCiB,EAACjB,EAAc,CAAA,GAEfiB,EAAC2B,EAAQ,CACPxB,MAAOC,EAAGD,MAAM,aAChByB,MAAO/C,GAAOgD,QAAQC,oBAAsB,YAIlD9B,EAACH,EAAI,CACHM,MAAOC,CAAE,4DAA4DN,SAErEE,EAACyB,EAAI,CAACtB,MAAOC,CAAE,mCAAmCN,SAC/CiC,EAAe1C,aAQ3BZ,EAAQuD,OACPhC,EAACH,EAAI,CAACM,MAAOC,CAAE,OAAON,SACpBE,EAACiC,EAAW,CACVC,SAAUzD,EAAQuD,MAClBG,QAAS1D,EAAQ2D,GACjBzD,eAAgBA,MAKrBF,EAAQ4D,MACPrC,EAACyB,EAAI,CACHtB,MAAO,CACLC,CAAE,OACFtB,EAAoBsB,CAAE,OAASA,CAAE,OACjC,CAAEkC,UAAW,aAAcC,aAAc,cACzC3D,EACIC,GAAO2D,cAAcC,cACrB5D,GAAO2D,cAAcE,mBACzB5C,SAEDrB,EAAQ4D,SAGR,EAIX,IAAAM,EAAexD,EAAMyD,KAAKpE"}
@@ -1,2 +1,2 @@
1
- import{View as e,Image as t,Text as l}from"react-native";import r from"twrnc";import{ArrowBack2RoundedIcon as n}from"../../assets/Icons/ArrowBack2RoundedIcon.js";import{useChatContext as i}from"../../context/ChatContext.js";import{jsxs as o,jsx as s}from"react/jsx-runtime";const a=({typingUsers:a,currentUserId:c})=>{const{theme:d,showAvatars:y,renderCustomTyping:u,showBubbleTail:m}=i(),f=a.filter((e=>e.id!==c));if(!f.length)return null;const h=f.slice(0,2),b=f.length-2;return o(e,{style:r`my-1 max-w-[75%] self-start flex-row`,children:[y&&o(e,{style:r`flex-row`,children:[h.map(((n,i)=>s(e,{style:[r`bg-gray-400 w-6 h-6 rounded-full items-center`,{marginLeft:i>0?-10:0,zIndex:h.length+i}],children:n.avatar?s(t,{source:{uri:n.avatar},style:[r`w-full h-full object-cover rounded-full`,d?.bubbleStyle?.avatarImageStyle]}):s(l,{style:[r`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,d?.bubbleStyle?.avatarTextStyle],children:n.name?.charAt(0)})},n.id))),b>0&&s(e,{style:[r`bg-gray-400 w-6 h-6 rounded-full items-center justify-center`,{marginLeft:-10,zIndex:3},{...d?.bubbleStyle?.additionalTypingUsersContainerStyle}],children:o(l,{style:[r`text-white text-xs font-semibold`,d?.bubbleStyle?.additionalTypingUsersTextStyle],children:["+",b]})})]}),m&&s(n,{style:r.style("w-6 h-6 fill-white mt-[1.25px]",{transform:[{rotate:"180deg"},{translateX:6}]}),color:`${d?.colors?.receivedMessageTailColor||"white"}`}),s(e,{style:[r`px-2 my-1 bg-white rounded-tl-none rounded-lg`,d?.bubbleStyle?.typingContainerStyle],children:u?u():s(e,{style:r`flex-row items-center py-3 px-2 justify-center`,children:s(l,{style:r`text-gray-600`,children:"Typing..."})})})]})};export{a as TypingIndicator};
1
+ import{View as e,Image as t,Text as r}from"react-native";import l from"twrnc";import{ArrowBack2RoundedIcon as n}from"../../assets/Icons/ArrowBack2RoundedIcon.js";import{useChatContext as i}from"../../context/ChatContext.js";import{jsxs as o,jsx as s}from"react/jsx-runtime";const a=({typingUsers:a,currentUserId:c})=>{const{theme:d,showAvatars:y,renderCustomTyping:u,showBubbleTail:m}=i(),f=a.filter((e=>e.id!==c));if(!f.length)return null;const h=f.slice(0,2),b=f.length-2;return o(e,{style:l`my-1 max-w-[75%] self-start flex-row`,children:[y&&o(e,{style:l`flex-row`,children:[h.map(((n,i)=>s(e,{style:[l`bg-gray-400 w-6 h-6 rounded-full items-center`,{marginLeft:i>0?-10:0,zIndex:h.length+i}],children:n.avatar?s(t,{source:{uri:n.avatar},style:[l`w-full h-full object-cover rounded-full`,d?.bubbleStyle?.avatarImageStyle]}):s(r,{style:[l`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,d?.bubbleStyle?.avatarTextStyle],children:n.name?.charAt(0)})},n.id))),b>0&&s(e,{style:[l`bg-gray-400 w-6 h-6 rounded-full items-center justify-center`,{marginLeft:-10,zIndex:3},{...d?.bubbleStyle?.additionalTypingUsersContainerStyle}],children:o(r,{style:[l`text-white text-xs font-semibold`,d?.bubbleStyle?.additionalTypingUsersTextStyle],children:["+",b]})})]}),m&&s(n,{style:l.style("w-6 h-6 fill-white mt-[1.25px] stroke-transparent",{transform:[{rotate:"180deg"},{translateX:6}]}),color:`${d?.colors?.receivedMessageTailColor||"white"}`}),s(e,{style:[l`px-2 my-1 bg-white rounded-tl-none rounded-lg`,d?.bubbleStyle?.typingContainerStyle],children:u?u():s(e,{style:l`flex-row items-center py-3 px-2 justify-center`,children:s(r,{style:l`text-gray-600`,children:"Typing..."})})})]})};export{a as TypingIndicator};
2
2
  //# sourceMappingURL=TypingIndicator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TypingIndicator.js","sources":["../../../../src/components/TypingComponent/TypingIndicator.tsx"],"sourcesContent":["import { Image, Text, View } from 'react-native';\nimport tw from 'twrnc';\nimport { ArrowBack2RoundedIcon } from '../../assets/Icons/ArrowBack2RoundedIcon';\nimport { useChatContext } from '../../context/ChatContext';\n\nexport interface TypingUser {\n id: string;\n avatar: string;\n name: string;\n}\n\ninterface TypingIndicatorProps {\n typingUsers: TypingUser[];\n currentUserId: string;\n}\n\nexport const TypingIndicator = ({\n typingUsers,\n currentUserId,\n}: TypingIndicatorProps) => {\n const { theme, showAvatars, renderCustomTyping, showBubbleTail } =\n useChatContext();\n\n const otherTypingUsers = typingUsers.filter(\n (user) => user.id !== currentUserId\n );\n\n if (!otherTypingUsers.length) return null;\n\n const displayedUsers = otherTypingUsers.slice(0, 2);\n const additionalUsers = otherTypingUsers.length - 2;\n\n return (\n <View style={tw`my-1 max-w-[75%] self-start flex-row`}>\n {showAvatars && (\n <View style={tw`flex-row`}>\n {displayedUsers.map((user, index) => (\n <View\n key={user.id}\n style={[\n tw`bg-gray-400 w-6 h-6 rounded-full items-center`,\n {\n marginLeft: index > 0 ? -10 : 0,\n zIndex: displayedUsers.length + index,\n },\n ]}\n >\n {user.avatar ? (\n <Image\n source={{ uri: user.avatar }}\n style={[\n tw`w-full h-full object-cover rounded-full`,\n theme?.bubbleStyle?.avatarImageStyle,\n ]}\n />\n ) : (\n <Text\n style={[\n tw`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,\n theme?.bubbleStyle?.avatarTextStyle,\n ]}\n >\n {user.name?.charAt(0)}\n </Text>\n )}\n </View>\n ))}\n {additionalUsers > 0 && (\n <View\n style={[\n tw`bg-gray-400 w-6 h-6 rounded-full items-center justify-center`,\n {\n marginLeft: -10,\n zIndex: 3,\n },\n { ...theme?.bubbleStyle?.additionalTypingUsersContainerStyle },\n ]}\n >\n <Text\n style={[\n tw`text-white text-xs font-semibold`,\n theme?.bubbleStyle?.additionalTypingUsersTextStyle,\n ]}\n >\n +{additionalUsers}\n </Text>\n </View>\n )}\n </View>\n )}\n {showBubbleTail && (\n <ArrowBack2RoundedIcon\n style={tw.style(\n 'w-6 h-6 fill-white mt-[1.25px]', \n {\n transform: [{ rotate: '180deg' }, { translateX: 6 }],\n }\n )}\n color={`${theme?.colors?.receivedMessageTailColor || 'white'}`}\n />\n )}\n\n <View\n style={[\n tw`px-2 my-1 bg-white rounded-tl-none rounded-lg`,\n theme?.bubbleStyle?.typingContainerStyle,\n ]}\n >\n {renderCustomTyping ? (\n renderCustomTyping()\n ) : (\n <View style={tw`flex-row items-center py-3 px-2 justify-center`}>\n <Text style={tw`text-gray-600`}>Typing...</Text>\n </View>\n )}\n </View>\n </View>\n );\n};\n"],"names":["TypingIndicator","typingUsers","currentUserId","theme","showAvatars","renderCustomTyping","showBubbleTail","useChatContext","otherTypingUsers","filter","user","id","length","displayedUsers","slice","additionalUsers","_jsxs","View","style","tw","children","map","index","_jsx","marginLeft","zIndex","avatar","Image","source","uri","bubbleStyle","avatarImageStyle","Text","avatarTextStyle","name","charAt","additionalTypingUsersContainerStyle","additionalTypingUsersTextStyle","ArrowBack2RoundedIcon","transform","rotate","translateX","color","colors","receivedMessageTailColor","typingContainerStyle"],"mappings":"kRAgBO,MAAMA,EAAkBA,EAC7BC,cACAC,oBAEA,MAAMC,MAAEA,EAAKC,YAAEA,EAAWC,mBAAEA,EAAkBC,eAAEA,GAC9CC,IAEIC,EAAmBP,EAAYQ,QAClCC,GAASA,EAAKC,KAAOT,IAGxB,IAAKM,EAAiBI,OAAQ,OAAO,KAErC,MAAMC,EAAiBL,EAAiBM,MAAM,EAAG,GAC3CC,EAAkBP,EAAiBI,OAAS,EAElD,OACEI,EAACC,EAAI,CAACC,MAAOC,CAAE,uCAAuCC,SACnDhB,CAAAA,GACCY,EAACC,EAAI,CAACC,MAAOC,CAAE,WAAWC,SACvBP,CAAAA,EAAeQ,KAAI,CAACX,EAAMY,IACzBC,EAACN,EAAI,CAEHC,MAAO,CACLC,CAAE,gDACF,CACEK,WAAYF,EAAQ,GAAI,GAAM,EAC9BG,OAAQZ,EAAeD,OAASU,IAElCF,SAEDV,EAAKgB,OACJH,EAACI,EAAK,CACJC,OAAQ,CAAEC,IAAKnB,EAAKgB,QACpBR,MAAO,CACLC,CAAE,0CACFhB,GAAO2B,aAAaC,oBAIxBR,EAACS,EAAI,CACHd,MAAO,CACLC,CAAE,wGACFhB,GAAO2B,aAAaG,iBACpBb,SAEDV,EAAKwB,MAAMC,OAAO,MAxBlBzB,EAAKC,MA6BbI,EAAkB,GACjBQ,EAACN,EAAI,CACHC,MAAO,CACLC,CAAE,+DACF,CACEK,YAAe,GACfC,OAAQ,GAEV,IAAKtB,GAAO2B,aAAaM,sCACzBhB,SAEFJ,EAACgB,EAAI,CACHd,MAAO,CACLC,CAAE,mCACFhB,GAAO2B,aAAaO,gCACpBjB,SAAA,CACH,IACGL,UAMXT,GACCiB,EAACe,EAAqB,CACpBpB,MAAOC,EAAGD,MACR,iCACA,CACEqB,UAAW,CAAC,CAAEC,OAAQ,UAAY,CAAEC,WAAY,MAGpDC,MAAO,GAAGvC,GAAOwC,QAAQC,0BAA4B,YAIzDrB,EAACN,EAAI,CACHC,MAAO,CACLC,CAAE,gDACFhB,GAAO2B,aAAae,sBACpBzB,SAEDf,EACCA,IAEAkB,EAACN,EAAI,CAACC,MAAOC,CAAE,iDAAiDC,SAC9DG,EAACS,EAAI,CAACd,MAAOC,CAAE,gBAAgBC,SAAC,oBAIjC"}
1
+ {"version":3,"file":"TypingIndicator.js","sources":["../../../../src/components/TypingComponent/TypingIndicator.tsx"],"sourcesContent":["import { Image, Text, View } from 'react-native';\nimport tw from 'twrnc';\nimport { ArrowBack2RoundedIcon } from '../../assets/Icons/ArrowBack2RoundedIcon';\nimport { useChatContext } from '../../context/ChatContext';\n\nexport interface TypingUser {\n id: string;\n avatar: string;\n name: string;\n}\n\ninterface TypingIndicatorProps {\n typingUsers: TypingUser[];\n currentUserId: string;\n}\n\nexport const TypingIndicator = ({\n typingUsers,\n currentUserId,\n}: TypingIndicatorProps) => {\n const { theme, showAvatars, renderCustomTyping, showBubbleTail } =\n useChatContext();\n\n const otherTypingUsers = typingUsers.filter(\n (user) => user.id !== currentUserId\n );\n\n if (!otherTypingUsers.length) return null;\n\n const displayedUsers = otherTypingUsers.slice(0, 2);\n const additionalUsers = otherTypingUsers.length - 2;\n\n return (\n <View style={tw`my-1 max-w-[75%] self-start flex-row`}>\n {showAvatars && (\n <View style={tw`flex-row`}>\n {displayedUsers.map((user, index) => (\n <View\n key={user.id}\n style={[\n tw`bg-gray-400 w-6 h-6 rounded-full items-center`,\n {\n marginLeft: index > 0 ? -10 : 0,\n zIndex: displayedUsers.length + index,\n },\n ]}\n >\n {user.avatar ? (\n <Image\n source={{ uri: user.avatar }}\n style={[\n tw`w-full h-full object-cover rounded-full`,\n theme?.bubbleStyle?.avatarImageStyle,\n ]}\n />\n ) : (\n <Text\n style={[\n tw`text-sm text-black font-semibold capitalize rounded-full bg-zinc-300 w-full h-full text-center pt-0.5`,\n theme?.bubbleStyle?.avatarTextStyle,\n ]}\n >\n {user.name?.charAt(0)}\n </Text>\n )}\n </View>\n ))}\n {additionalUsers > 0 && (\n <View\n style={[\n tw`bg-gray-400 w-6 h-6 rounded-full items-center justify-center`,\n {\n marginLeft: -10,\n zIndex: 3,\n },\n { ...theme?.bubbleStyle?.additionalTypingUsersContainerStyle },\n ]}\n >\n <Text\n style={[\n tw`text-white text-xs font-semibold`,\n theme?.bubbleStyle?.additionalTypingUsersTextStyle,\n ]}\n >\n +{additionalUsers}\n </Text>\n </View>\n )}\n </View>\n )}\n {showBubbleTail && (\n <ArrowBack2RoundedIcon\n style={tw.style(\n 'w-6 h-6 fill-white mt-[1.25px] stroke-transparent', \n {\n transform: [{ rotate: '180deg' }, { translateX: 6 }],\n }\n )}\n color={`${theme?.colors?.receivedMessageTailColor || 'white'}`}\n />\n )}\n\n <View\n style={[\n tw`px-2 my-1 bg-white rounded-tl-none rounded-lg`,\n theme?.bubbleStyle?.typingContainerStyle,\n ]}\n >\n {renderCustomTyping ? (\n renderCustomTyping()\n ) : (\n <View style={tw`flex-row items-center py-3 px-2 justify-center`}>\n <Text style={tw`text-gray-600`}>Typing...</Text>\n </View>\n )}\n </View>\n </View>\n );\n};\n"],"names":["TypingIndicator","typingUsers","currentUserId","theme","showAvatars","renderCustomTyping","showBubbleTail","useChatContext","otherTypingUsers","filter","user","id","length","displayedUsers","slice","additionalUsers","_jsxs","View","style","tw","children","map","index","_jsx","marginLeft","zIndex","avatar","Image","source","uri","bubbleStyle","avatarImageStyle","Text","avatarTextStyle","name","charAt","additionalTypingUsersContainerStyle","additionalTypingUsersTextStyle","ArrowBack2RoundedIcon","transform","rotate","translateX","color","colors","receivedMessageTailColor","typingContainerStyle"],"mappings":"kRAgBO,MAAMA,EAAkBA,EAC7BC,cACAC,oBAEA,MAAMC,MAAEA,EAAKC,YAAEA,EAAWC,mBAAEA,EAAkBC,eAAEA,GAC9CC,IAEIC,EAAmBP,EAAYQ,QAClCC,GAASA,EAAKC,KAAOT,IAGxB,IAAKM,EAAiBI,OAAQ,OAAO,KAErC,MAAMC,EAAiBL,EAAiBM,MAAM,EAAG,GAC3CC,EAAkBP,EAAiBI,OAAS,EAElD,OACEI,EAACC,EAAI,CAACC,MAAOC,CAAE,uCAAuCC,SACnDhB,CAAAA,GACCY,EAACC,EAAI,CAACC,MAAOC,CAAE,WAAWC,SACvBP,CAAAA,EAAeQ,KAAI,CAACX,EAAMY,IACzBC,EAACN,EAAI,CAEHC,MAAO,CACLC,CAAE,gDACF,CACEK,WAAYF,EAAQ,GAAI,GAAM,EAC9BG,OAAQZ,EAAeD,OAASU,IAElCF,SAEDV,EAAKgB,OACJH,EAACI,EAAK,CACJC,OAAQ,CAAEC,IAAKnB,EAAKgB,QACpBR,MAAO,CACLC,CAAE,0CACFhB,GAAO2B,aAAaC,oBAIxBR,EAACS,EAAI,CACHd,MAAO,CACLC,CAAE,wGACFhB,GAAO2B,aAAaG,iBACpBb,SAEDV,EAAKwB,MAAMC,OAAO,MAxBlBzB,EAAKC,MA6BbI,EAAkB,GACjBQ,EAACN,EAAI,CACHC,MAAO,CACLC,CAAE,+DACF,CACEK,YAAe,GACfC,OAAQ,GAEV,IAAKtB,GAAO2B,aAAaM,sCACzBhB,SAEFJ,EAACgB,EAAI,CACHd,MAAO,CACLC,CAAE,mCACFhB,GAAO2B,aAAaO,gCACpBjB,SAAA,CACH,IACGL,UAMXT,GACCiB,EAACe,EAAqB,CACpBpB,MAAOC,EAAGD,MACR,oDACA,CACEqB,UAAW,CAAC,CAAEC,OAAQ,UAAY,CAAEC,WAAY,MAGpDC,MAAO,GAAGvC,GAAOwC,QAAQC,0BAA4B,YAIzDrB,EAACN,EAAI,CACHC,MAAO,CACLC,CAAE,gDACFhB,GAAO2B,aAAae,sBACpBzB,SAEDf,EACCA,IAEAkB,EAACN,EAAI,CAACC,MAAOC,CAAE,iDAAiDC,SAC9DG,EAACS,EAAI,CAACd,MAAOC,CAAE,gBAAgBC,SAAC,oBAIjC"}
@@ -1,4 +1,4 @@
1
- import { ViewStyle } from "react-native";
1
+ import { ViewStyle } from 'react-native';
2
2
  export declare const ArrowBack2RoundedIcon: ({ style, color, }: {
3
3
  style?: ViewStyle;
4
4
  color?: string;
@@ -14,7 +14,7 @@ export interface Message {
14
14
  export interface ChatScreenProps {
15
15
  messages: Message[];
16
16
  currentUserId: string;
17
- onSendMessage: (message: Omit<Message, "id" | "time" | "status">) => void;
17
+ onSendMessage: (message: Omit<Message, 'id' | 'time' | 'status'>) => void;
18
18
  onMessageLongPress?: (message: Message) => void;
19
19
  onAttachmentPress?: () => void;
20
20
  onAudioRecordEnd?: () => void;
@@ -51,7 +51,8 @@ export interface ChatScreenProps {
51
51
  additionalTypingUsersTextStyle?: TextStyle;
52
52
  };
53
53
  messageStyle?: {
54
- textStyle?: TextStyle;
54
+ sentTextStyle?: TextStyle;
55
+ receivedTextStyle?: TextStyle;
55
56
  audioPlayButtonStyle?: ViewStyle;
56
57
  audioKnobStyle?: ViewStyle;
57
58
  progressBarStyle?: ViewStyle;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "movius-chats",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "A highly customizable, feature-rich chat interface component for React Native applications",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -1,6 +1,5 @@
1
-
2
- import { ViewStyle } from "react-native";
3
- import Svg, { Path } from "react-native-svg";
1
+ import { ViewStyle } from 'react-native';
2
+ import Svg, { Path } from 'react-native-svg';
4
3
 
5
4
  export const ArrowBack2RoundedIcon = ({
6
5
  style,
@@ -10,10 +9,11 @@ export const ArrowBack2RoundedIcon = ({
10
9
  color?: string;
11
10
  }) => {
12
11
  return (
13
- <Svg style={style} fill={color} viewBox="0 0 48 48">
12
+ <Svg style={style} viewBox="0 0 48 48">
14
13
  <Path
14
+ fill={color}
15
15
  fillRule="evenodd"
16
- stroke="currentColor"
16
+ stroke={color}
17
17
  strokeLinecap="round"
18
18
  strokeLinejoin="round"
19
19
  strokeWidth="4"
@@ -97,7 +97,7 @@ const ChatBubble: React.FC<ChatBubbleProps> = ({
97
97
  {isFirstInSequence && showBubbleTail && (
98
98
  <ArrowBack2RoundedIcon
99
99
  style={tw.style(
100
- 'absolute -top-1 w-6 h-6',
100
+ 'absolute -top-1 w-6 h-6 stroke-transparent',
101
101
  isCurrentUser ? '-right-3.5' : '-left-3.5 mt-[1.25px]',
102
102
  {
103
103
  transform: [{ rotate: isCurrentUser ? '90deg' : '180deg' }],
@@ -13,6 +13,7 @@ const MessageContent: React.FC<MessageContentProps> = ({
13
13
  message,
14
14
  onMediaPress,
15
15
  isVideoPlaying,
16
+ isCurrentUser,
16
17
  }) => {
17
18
  const {
18
19
  theme,
@@ -127,10 +128,12 @@ const MessageContent: React.FC<MessageContentProps> = ({
127
128
  {message.text && (
128
129
  <Text
129
130
  style={[
130
- tw`text-gray-800 pt-1`,
131
+ tw`pt-1`,
131
132
  showMessageStatus ? tw`pb-0` : tw`pb-2`,
132
133
  { wordBreak: 'break-word', overflowWrap: 'break-word' },
133
- theme?.messageStyle?.textStyle,
134
+ isCurrentUser
135
+ ? theme?.messageStyle?.sentTextStyle
136
+ : theme?.messageStyle?.receivedTextStyle,
134
137
  ]}
135
138
  >
136
139
  {message.text}
@@ -91,7 +91,7 @@ export const TypingIndicator = ({
91
91
  {showBubbleTail && (
92
92
  <ArrowBack2RoundedIcon
93
93
  style={tw.style(
94
- 'w-6 h-6 fill-white mt-[1.25px]',
94
+ 'w-6 h-6 fill-white mt-[1.25px] stroke-transparent',
95
95
  {
96
96
  transform: [{ rotate: '180deg' }, { translateX: 6 }],
97
97
  }
@@ -17,7 +17,7 @@ export interface ChatScreenProps {
17
17
  // Message handling
18
18
  messages: Message[];
19
19
  currentUserId: string;
20
- onSendMessage: (message: Omit<Message, "id" | "time" | "status">) => void;
20
+ onSendMessage: (message: Omit<Message, 'id' | 'time' | 'status'>) => void;
21
21
  onMessageLongPress?: (message: Message) => void;
22
22
  onAttachmentPress?: () => void;
23
23
  onAudioRecordEnd?: () => void;
@@ -54,7 +54,8 @@ export interface ChatScreenProps {
54
54
  additionalTypingUsersTextStyle?: TextStyle;
55
55
  };
56
56
  messageStyle?: {
57
- textStyle?: TextStyle;
57
+ sentTextStyle?: TextStyle;
58
+ receivedTextStyle?: TextStyle;
58
59
  audioPlayButtonStyle?: ViewStyle;
59
60
  audioKnobStyle?: ViewStyle;
60
61
  progressBarStyle?: ViewStyle;