movius-chats 1.1.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 +100 -88
  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,6 +56,24 @@ 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
@@ -88,86 +115,62 @@ const App = () => {
88
115
  | messages | Message[] | Yes | Array of message objects to display |
89
116
  | currentUserId | string | Yes | ID of the current user |
90
117
  | onSendMessage | (message: Omit<Message, "id" \| "time" \| "status">) => void | Yes | Callback when a message is sent |
91
-
92
- ### Message Type
93
-
94
- ```typescript
95
- interface Message {
96
- id: string;
97
- text?: string;
98
- image?: string;
99
- video?: string;
100
- audio?: string;
101
- senderId: string;
102
- time: string;
103
- status: "read" | "delivered" | "sent";
104
- senderName?: string;
105
- senderAvatar?: string;
106
- }
107
- ```
108
-
109
- ### Feature Flags
110
-
111
- | Prop | Type | Default | Description |
112
- |------|------|---------|-------------|
113
- | showAvatars | boolean | false | Show user avatars |
114
- | showUserNames | boolean | false | Display usernames above messages |
115
- | showEmojiButton | boolean | true | Show emoji picker button |
116
- | showAttachmentsButton | boolean | true | Show attachments button |
117
- | showCameraButton | boolean | true | Show camera access button |
118
- | showVoiceRecordButton | boolean | true | Show voice recording button |
119
- | showBubbleTail | boolean | true | Show message bubble tails |
120
- | showMessageStatus | boolean | true | Show message status indicators |
121
-
122
- ### Event Handlers
123
-
124
- | Prop | Type | Description |
125
- |------|------|-------------|
126
- | onMessageLongPress | (message: Message) => void | Callback for long-pressing a message |
127
- | onAttachmentPress | () => void | Callback for attachment button press |
128
- | onAudioRecordStart | () => void | Callback when audio recording starts |
129
- | onAudioRecordEnd | () => void | Callback when audio recording ends |
130
- | onCameraPress | () => void | Callback for camera button press |
131
- | onTypingStart | () => void | Callback when user starts typing |
132
- | 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 |
133
127
 
134
128
  ### Theming
135
129
 
136
130
  The component supports extensive theming through the `theme` prop:
137
131
 
138
132
  ```typescript
139
- theme?: {
140
- colors?: {
141
- sentMessageTailColor?: string;
142
- receivedMessageTailColor?: string;
143
- timestamp?: string;
144
- inputsIconsColor?: string;
145
- sendIconsColor?: string;
146
- placeholderTextColor?: string;
147
- audioPlayIconColor?: string;
148
- audioPauseIconColor?: string;
149
- videoPlayIconColor?: string;
150
- };
151
- bubbleStyle?: {
152
- sent?: ViewStyle;
153
- received?: ViewStyle;
154
- // ... other bubble styles
155
- };
156
- messageStyle?: {
157
- textStyle?: TextStyle;
158
- // ... other message styles
159
- };
160
- inputStyles?: {
161
- inputSectionContainerStyle?: ViewStyle;
162
- // ... 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
+ };
163
169
  };
164
- }
165
170
  ```
166
171
 
167
172
  ### Custom Components
168
173
 
169
- You can provide custom components for various elements:
170
-
171
174
  | Prop | Type | Description |
172
175
  |------|------|-------------|
173
176
  | renderCustomInput | () => React.ReactNode | Custom input component |
@@ -210,33 +213,42 @@ You can provide custom components for various elements:
210
213
  />
211
214
  ```
212
215
 
213
- ### Custom Input Component
216
+ ### Expo Usage
214
217
 
215
- ```typescript
216
- <ChatScreen
217
- messages={messages}
218
- currentUserId="user123"
219
- onSendMessage={handleSendMessage}
220
- renderCustomInput={() => (
221
- <YourCustomInputComponent
222
- onSend={(text) => {
223
- handleSendMessage({
224
- text,
225
- senderId: 'user123',
226
- });
227
- }}
228
- />
229
- )}
230
- />
231
- ```
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
+ ```
232
231
 
233
- ## 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
234
238
 
235
239
  - Messages are rendered using `FlatList` for optimal performance
236
240
  - Avatar images are cached automatically
237
241
  - Media messages use lazy loading
238
242
  - Typing indicators are debounced
239
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
+
240
252
  ## Contributing
241
253
 
242
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.1.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;