@messenger-box/platform-mobile 10.0.3-alpha.7 → 10.0.3-alpha.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +116 -0
- package/lib/compute.js +2 -3
- package/lib/compute.js.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/queries/inboxQueries.js +65 -0
- package/lib/queries/inboxQueries.js.map +1 -0
- package/lib/routes.json +2 -3
- package/lib/screens/inbox/DialogMessages.js +1 -1
- package/lib/screens/inbox/DialogMessages.js.map +1 -1
- package/lib/screens/inbox/DialogThreadMessages.js +4 -8
- package/lib/screens/inbox/DialogThreadMessages.js.map +1 -1
- package/lib/screens/inbox/DialogThreads.js +57 -12
- package/lib/screens/inbox/DialogThreads.js.map +1 -1
- package/lib/screens/inbox/Inbox.js +1 -1
- package/lib/screens/inbox/Inbox.js.map +1 -1
- package/lib/screens/inbox/components/CachedImage/consts.js +1 -1
- package/lib/screens/inbox/components/CachedImage/consts.js.map +1 -1
- package/lib/screens/inbox/components/CachedImage/index.js +168 -46
- package/lib/screens/inbox/components/CachedImage/index.js.map +1 -1
- package/lib/screens/inbox/components/DialogItem.js +169 -0
- package/lib/screens/inbox/components/DialogItem.js.map +1 -0
- package/lib/screens/inbox/components/GiftedChatInboxComponent.js +313 -0
- package/lib/screens/inbox/components/GiftedChatInboxComponent.js.map +1 -0
- package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js +147 -31
- package/lib/screens/inbox/components/SlackMessageContainer/SlackBubble.js.map +1 -1
- package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js +6 -1
- package/lib/screens/inbox/components/SlackMessageContainer/SlackMessage.js.map +1 -1
- package/lib/screens/inbox/components/SubscriptionHandler.js +24 -0
- package/lib/screens/inbox/components/SubscriptionHandler.js.map +1 -0
- package/lib/screens/inbox/components/ThreadsViewItem.js +66 -55
- package/lib/screens/inbox/components/ThreadsViewItem.js.map +1 -1
- package/lib/screens/inbox/config/config.js +2 -2
- package/lib/screens/inbox/config/config.js.map +1 -1
- package/lib/screens/inbox/containers/ConversationView.js +1111 -434
- package/lib/screens/inbox/containers/ConversationView.js.map +1 -1
- package/lib/screens/inbox/containers/Dialogs.js +193 -80
- package/lib/screens/inbox/containers/Dialogs.js.map +1 -1
- package/lib/screens/inbox/containers/ThreadConversationView.js +725 -216
- package/lib/screens/inbox/containers/ThreadConversationView.js.map +1 -1
- package/lib/screens/inbox/containers/ThreadsView.js +83 -50
- package/lib/screens/inbox/containers/ThreadsView.js.map +1 -1
- package/lib/screens/inbox/hooks/useInboxMessages.js +31 -0
- package/lib/screens/inbox/hooks/useInboxMessages.js.map +1 -0
- package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js +108 -0
- package/lib/screens/inbox/hooks/useSafeDialogThreadsMachine.js.map +1 -0
- package/lib/screens/inbox/workflow/dialog-threads-xstate.js +151 -0
- package/lib/screens/inbox/workflow/dialog-threads-xstate.js.map +1 -0
- package/package.json +4 -4
- package/src/compute.ts +5 -6
- package/src/index.ts +2 -0
- package/src/navigation/InboxNavigation.tsx +3 -3
- package/src/queries/inboxQueries.ts +299 -0
- package/src/queries/index.d.ts +2 -0
- package/src/queries/index.ts +1 -0
- package/src/screens/inbox/DialogMessages.tsx +1 -1
- package/src/screens/inbox/DialogThreadMessages.tsx +7 -14
- package/src/screens/inbox/DialogThreads.tsx +55 -61
- package/src/screens/inbox/Inbox.tsx +1 -1
- package/src/screens/inbox/components/Actionsheet.tsx +30 -0
- package/src/screens/inbox/components/CachedImage/consts.ts +4 -3
- package/src/screens/inbox/components/CachedImage/index.tsx +232 -61
- package/src/screens/inbox/components/DialogItem.tsx +306 -0
- package/src/screens/inbox/components/DialogsHeader.tsx +6 -13
- package/src/screens/inbox/components/DialogsListItem.tsx +262 -198
- package/src/screens/inbox/components/ExpandableInput.tsx +460 -0
- package/src/screens/inbox/components/ExpandableInputActionSheet.tsx +518 -0
- package/src/screens/inbox/components/GiftedChatInboxComponent.tsx +411 -0
- package/src/screens/inbox/components/ServiceDialogsListItem.tsx +337 -194
- package/src/screens/inbox/components/SlackInput.tsx +23 -0
- package/src/screens/inbox/components/SlackMessageContainer/SlackBubble.tsx +233 -23
- package/src/screens/inbox/components/SlackMessageContainer/SlackMessage.tsx +1 -1
- package/src/screens/inbox/components/SmartLoader.tsx +61 -0
- package/src/screens/inbox/components/SubscriptionHandler.tsx +41 -0
- package/src/screens/inbox/components/SupportServiceDialogsListItem.tsx +53 -55
- package/src/screens/inbox/components/ThreadsViewItem.tsx +178 -285
- package/src/screens/inbox/components/workflow/dialogs-list-item-xstate.ts +145 -0
- package/src/screens/inbox/components/workflow/service-dialogs-list-item-xstate.ts +159 -0
- package/src/screens/inbox/config/config.ts +2 -2
- package/src/screens/inbox/containers/ConversationView.tsx +1843 -702
- package/src/screens/inbox/containers/ConversationView.tsx.bk +1467 -0
- package/src/screens/inbox/containers/Dialogs.tsx +402 -204
- package/src/screens/inbox/containers/SupportServiceDialogs.tsx +4 -4
- package/src/screens/inbox/containers/ThreadConversationView.tsx +1350 -319
- package/src/screens/inbox/containers/ThreadsView.tsx +105 -193
- package/src/screens/inbox/containers/workflow/apollo/handleResult.ts +20 -0
- package/src/screens/inbox/containers/workflow/conversation-xstate.ts +313 -0
- package/src/screens/inbox/containers/workflow/dialogs-xstate.ts +196 -0
- package/src/screens/inbox/containers/workflow/thread-conversation-xstate.ts +401 -0
- package/src/screens/inbox/hooks/useInboxMessages.ts +34 -0
- package/src/screens/inbox/hooks/useSafeDialogThreadsMachine.ts +136 -0
- package/src/screens/inbox/index.ts +37 -0
- package/src/screens/inbox/machines/threadsMachine.ts +147 -0
- package/src/screens/inbox/workflow/dialog-threads-xstate.ts +163 -0
- package/tsconfig.json +11 -54
- package/lib/screens/inbox/components/DialogsListItem.js +0 -171
- package/lib/screens/inbox/components/DialogsListItem.js.map +0 -1
- package/lib/screens/inbox/components/ServiceDialogsListItem.js +0 -171
- package/lib/screens/inbox/components/ServiceDialogsListItem.js.map +0 -1
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
TouchableOpacity,
|
|
5
|
+
Animated,
|
|
6
|
+
Keyboard,
|
|
7
|
+
Dimensions,
|
|
8
|
+
StyleSheet,
|
|
9
|
+
PanResponder,
|
|
10
|
+
Text,
|
|
11
|
+
TouchableWithoutFeedback,
|
|
12
|
+
Modal,
|
|
13
|
+
Image,
|
|
14
|
+
TextInput,
|
|
15
|
+
KeyboardAvoidingView,
|
|
16
|
+
Platform,
|
|
17
|
+
ScrollView,
|
|
18
|
+
ActivityIndicator,
|
|
19
|
+
} from 'react-native';
|
|
20
|
+
import { HStack } from '@admin-layout/gluestack-ui-mobile';
|
|
21
|
+
import { MaterialIcons, Ionicons, MaterialCommunityIcons } from '@expo/vector-icons';
|
|
22
|
+
import colors from 'tailwindcss/colors';
|
|
23
|
+
|
|
24
|
+
const { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = Dimensions.get('window');
|
|
25
|
+
const MAX_HEIGHT = SCREEN_HEIGHT * 0.5; // Half screen height instead of 80%
|
|
26
|
+
const BASE_MIN_HEIGHT = 150; // Default compact height without images
|
|
27
|
+
const IMAGE_PREVIEW_HEIGHT = 90; // Height needed for image preview section including margins
|
|
28
|
+
const HANDLE_HEIGHT = 30;
|
|
29
|
+
|
|
30
|
+
interface ExpandableInputActionSheetProps {
|
|
31
|
+
isVisible: boolean;
|
|
32
|
+
onClose: () => void;
|
|
33
|
+
onSend: () => void;
|
|
34
|
+
onSelectImages: () => void;
|
|
35
|
+
text: string;
|
|
36
|
+
onChangeText: (text: string) => void;
|
|
37
|
+
textInputRef: React.RefObject<any>;
|
|
38
|
+
isSendDisabled: boolean;
|
|
39
|
+
selectedImages: Array<any>;
|
|
40
|
+
onRemoveImage: (index: number) => void;
|
|
41
|
+
loading?: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const ExpandableInputActionSheet = ({
|
|
45
|
+
isVisible,
|
|
46
|
+
onClose,
|
|
47
|
+
onSend,
|
|
48
|
+
onSelectImages,
|
|
49
|
+
text,
|
|
50
|
+
onChangeText,
|
|
51
|
+
textInputRef,
|
|
52
|
+
isSendDisabled,
|
|
53
|
+
selectedImages,
|
|
54
|
+
onRemoveImage,
|
|
55
|
+
loading = false,
|
|
56
|
+
}: ExpandableInputActionSheetProps) => {
|
|
57
|
+
const translateY = useRef(new Animated.Value(MAX_HEIGHT)).current;
|
|
58
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
59
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
60
|
+
const inputRef = useRef<TextInput>(null);
|
|
61
|
+
|
|
62
|
+
// Calculate height based on whether we have images
|
|
63
|
+
const getMinHeight = () => {
|
|
64
|
+
return selectedImages.length > 0 ? BASE_MIN_HEIGHT + IMAGE_PREVIEW_HEIGHT : BASE_MIN_HEIGHT;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const [sheetHeight, setSheetHeight] = useState(getMinHeight());
|
|
68
|
+
|
|
69
|
+
// Update height when images array changes
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
if (!isExpanded) {
|
|
72
|
+
setSheetHeight(getMinHeight());
|
|
73
|
+
}
|
|
74
|
+
}, [selectedImages.length, isExpanded]);
|
|
75
|
+
|
|
76
|
+
// Add a function to handle text input changes
|
|
77
|
+
const handleTextChange = (newText) => {
|
|
78
|
+
// Update the parent component's state
|
|
79
|
+
onChangeText(newText);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Close animation
|
|
83
|
+
const closeSheet = () => {
|
|
84
|
+
// Ensure any text changes are properly passed to the parent component
|
|
85
|
+
// This ensures the parent component has the latest text state
|
|
86
|
+
if (inputRef.current) {
|
|
87
|
+
inputRef.current.blur();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
Keyboard.dismiss();
|
|
91
|
+
Animated.timing(translateY, {
|
|
92
|
+
toValue: MAX_HEIGHT,
|
|
93
|
+
duration: 300,
|
|
94
|
+
useNativeDriver: true,
|
|
95
|
+
}).start(() => {
|
|
96
|
+
// Ensure onClose is called after animation completes
|
|
97
|
+
onClose();
|
|
98
|
+
setIsExpanded(false);
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// Expand the sheet to max height
|
|
103
|
+
const expandSheet = () => {
|
|
104
|
+
setIsExpanded(true);
|
|
105
|
+
setSheetHeight(MAX_HEIGHT);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// Collapse the sheet to min height
|
|
109
|
+
const collapseSheet = () => {
|
|
110
|
+
setIsExpanded(false);
|
|
111
|
+
setSheetHeight(getMinHeight());
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Toggle expansion when handle is clicked
|
|
115
|
+
const toggleExpansion = () => {
|
|
116
|
+
if (isExpanded) {
|
|
117
|
+
collapseSheet();
|
|
118
|
+
} else {
|
|
119
|
+
expandSheet();
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// Open animation
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
if (isVisible) {
|
|
126
|
+
// Set initial height based on images
|
|
127
|
+
setSheetHeight(getMinHeight());
|
|
128
|
+
setIsExpanded(false);
|
|
129
|
+
|
|
130
|
+
Animated.timing(translateY, {
|
|
131
|
+
toValue: 0,
|
|
132
|
+
duration: 300,
|
|
133
|
+
useNativeDriver: true,
|
|
134
|
+
}).start(() => {
|
|
135
|
+
// Focus the text input after a small delay to ensure the sheet is visible
|
|
136
|
+
setTimeout(() => {
|
|
137
|
+
if (inputRef.current) {
|
|
138
|
+
inputRef.current.focus();
|
|
139
|
+
}
|
|
140
|
+
}, 100);
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}, [isVisible, translateY, selectedImages.length]);
|
|
144
|
+
|
|
145
|
+
// Handle keyboard showing/hiding
|
|
146
|
+
useEffect(() => {
|
|
147
|
+
const keyboardWillShowListener = Keyboard.addListener('keyboardWillShow', (e) => {
|
|
148
|
+
// Keep height as is when keyboard shows
|
|
149
|
+
if (!isExpanded) {
|
|
150
|
+
setSheetHeight(getMinHeight());
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const keyboardWillHideListener = Keyboard.addListener('keyboardWillHide', () => {
|
|
155
|
+
if (!isDragging && !isExpanded) {
|
|
156
|
+
setSheetHeight(getMinHeight());
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
return () => {
|
|
161
|
+
keyboardWillShowListener.remove();
|
|
162
|
+
keyboardWillHideListener.remove();
|
|
163
|
+
};
|
|
164
|
+
}, [isDragging, isExpanded, selectedImages.length]);
|
|
165
|
+
|
|
166
|
+
// Create pan responder for drag gestures
|
|
167
|
+
const panResponder = useRef(
|
|
168
|
+
PanResponder.create({
|
|
169
|
+
onStartShouldSetPanResponder: () => true,
|
|
170
|
+
onMoveShouldSetPanResponder: (_, gestureState) => {
|
|
171
|
+
return Math.abs(gestureState.dy) > 5;
|
|
172
|
+
},
|
|
173
|
+
onPanResponderGrant: () => {
|
|
174
|
+
setIsDragging(true);
|
|
175
|
+
translateY.setOffset(-1 * translateY['_value']);
|
|
176
|
+
},
|
|
177
|
+
onPanResponderMove: (_, gestureState) => {
|
|
178
|
+
// Allow dragging down to close or up to expand
|
|
179
|
+
if (gestureState.dy > 0) {
|
|
180
|
+
// Dragging down
|
|
181
|
+
translateY.setValue(gestureState.dy);
|
|
182
|
+
} else if (gestureState.dy < 0 && !isExpanded) {
|
|
183
|
+
// Dragging up (only if not already expanded)
|
|
184
|
+
// Calculate what percentage of full expansion this drag represents
|
|
185
|
+
const expansionPercentage = Math.min(1, Math.abs(gestureState.dy) / 200);
|
|
186
|
+
// Calculate new height based on drag distance
|
|
187
|
+
const additionalHeight = (MAX_HEIGHT - getMinHeight()) * expansionPercentage;
|
|
188
|
+
const newHeight = getMinHeight() + additionalHeight;
|
|
189
|
+
setSheetHeight(newHeight);
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
onPanResponderRelease: (_, gestureState) => {
|
|
193
|
+
translateY.flattenOffset();
|
|
194
|
+
setIsDragging(false);
|
|
195
|
+
|
|
196
|
+
// If dragged down significantly, close the sheet
|
|
197
|
+
if (gestureState.dy > 50) {
|
|
198
|
+
closeSheet();
|
|
199
|
+
} else if (gestureState.dy < -50 && !isExpanded) {
|
|
200
|
+
// If dragged up significantly, expand to full height
|
|
201
|
+
expandSheet();
|
|
202
|
+
} else {
|
|
203
|
+
// Otherwise, snap back to current position
|
|
204
|
+
Animated.spring(translateY, {
|
|
205
|
+
toValue: 0,
|
|
206
|
+
useNativeDriver: true,
|
|
207
|
+
tension: 50,
|
|
208
|
+
friction: 7,
|
|
209
|
+
}).start();
|
|
210
|
+
|
|
211
|
+
// If not expanding or closing, restore height to previous state
|
|
212
|
+
if (gestureState.dy > 0 && gestureState.dy <= 50) {
|
|
213
|
+
// Small downward drag, keep current state
|
|
214
|
+
if (isExpanded) {
|
|
215
|
+
setSheetHeight(MAX_HEIGHT);
|
|
216
|
+
} else {
|
|
217
|
+
setSheetHeight(getMinHeight());
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
}),
|
|
223
|
+
).current;
|
|
224
|
+
|
|
225
|
+
return (
|
|
226
|
+
<Modal
|
|
227
|
+
visible={isVisible}
|
|
228
|
+
transparent={true}
|
|
229
|
+
animationType="none"
|
|
230
|
+
onRequestClose={closeSheet}
|
|
231
|
+
statusBarTranslucent={true}
|
|
232
|
+
>
|
|
233
|
+
<KeyboardAvoidingView
|
|
234
|
+
style={styles.container}
|
|
235
|
+
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
|
|
236
|
+
keyboardVerticalOffset={Platform.OS === 'ios' ? 10 : 0}
|
|
237
|
+
>
|
|
238
|
+
<TouchableWithoutFeedback onPress={closeSheet}>
|
|
239
|
+
<View style={styles.backdrop} />
|
|
240
|
+
</TouchableWithoutFeedback>
|
|
241
|
+
|
|
242
|
+
<Animated.View
|
|
243
|
+
style={[
|
|
244
|
+
styles.sheetContainer,
|
|
245
|
+
{
|
|
246
|
+
transform: [{ translateY }],
|
|
247
|
+
height: sheetHeight,
|
|
248
|
+
},
|
|
249
|
+
]}
|
|
250
|
+
>
|
|
251
|
+
{/* Drag handle with click to expand */}
|
|
252
|
+
<TouchableOpacity style={styles.handleContainer} onPress={toggleExpansion} activeOpacity={0.7}>
|
|
253
|
+
<View style={styles.handle} {...panResponder.panHandlers} />
|
|
254
|
+
</TouchableOpacity>
|
|
255
|
+
|
|
256
|
+
{/* Main content */}
|
|
257
|
+
<View style={styles.sheetContent}>
|
|
258
|
+
{/* Input area at top - always visible */}
|
|
259
|
+
<View style={styles.inputContainer}>
|
|
260
|
+
<TextInput
|
|
261
|
+
ref={inputRef}
|
|
262
|
+
value={text}
|
|
263
|
+
onChangeText={handleTextChange}
|
|
264
|
+
style={[styles.textInput, isExpanded && styles.textInputExpanded]}
|
|
265
|
+
placeholder="Jot something down"
|
|
266
|
+
placeholderTextColor="#888"
|
|
267
|
+
multiline
|
|
268
|
+
numberOfLines={isExpanded ? 5 : 2}
|
|
269
|
+
autoCapitalize="sentences"
|
|
270
|
+
autoCorrect={true}
|
|
271
|
+
blurOnSubmit={false}
|
|
272
|
+
textAlignVertical="top"
|
|
273
|
+
/>
|
|
274
|
+
</View>
|
|
275
|
+
|
|
276
|
+
{/* Image preview section - immediately below input, always visible */}
|
|
277
|
+
{selectedImages.length > 0 && (
|
|
278
|
+
<View style={styles.imagePreviewWrapper}>
|
|
279
|
+
<ScrollView
|
|
280
|
+
horizontal
|
|
281
|
+
showsHorizontalScrollIndicator={false}
|
|
282
|
+
style={styles.imagePreviewContainer}
|
|
283
|
+
contentContainerStyle={styles.imagePreviewContent}
|
|
284
|
+
>
|
|
285
|
+
{selectedImages.map((img, index) => (
|
|
286
|
+
<View key={`image-preview-${index}`} style={styles.imagePreview}>
|
|
287
|
+
<View style={styles.imageBox}>
|
|
288
|
+
{img.uri || img.url ? (
|
|
289
|
+
<Image
|
|
290
|
+
source={{ uri: img.uri || img.url }}
|
|
291
|
+
style={{ width: '100%', height: '100%' }}
|
|
292
|
+
resizeMode="cover"
|
|
293
|
+
/>
|
|
294
|
+
) : (
|
|
295
|
+
<View
|
|
296
|
+
style={{
|
|
297
|
+
width: '100%',
|
|
298
|
+
height: '100%',
|
|
299
|
+
backgroundColor: colors.gray[200],
|
|
300
|
+
}}
|
|
301
|
+
/>
|
|
302
|
+
)}
|
|
303
|
+
</View>
|
|
304
|
+
<TouchableOpacity
|
|
305
|
+
onPress={() => onRemoveImage(index)}
|
|
306
|
+
style={styles.removeImageButton}
|
|
307
|
+
>
|
|
308
|
+
<Ionicons name="close" size={16} color="white" />
|
|
309
|
+
</TouchableOpacity>
|
|
310
|
+
</View>
|
|
311
|
+
))}
|
|
312
|
+
</ScrollView>
|
|
313
|
+
</View>
|
|
314
|
+
)}
|
|
315
|
+
|
|
316
|
+
{/* Extra content area - only in expanded mode */}
|
|
317
|
+
{isExpanded && (
|
|
318
|
+
<ScrollView style={styles.extraContentArea} showsVerticalScrollIndicator={false}>
|
|
319
|
+
{/* This area only appears when expanded */}
|
|
320
|
+
<View style={styles.expandedContentPlaceholder} />
|
|
321
|
+
</ScrollView>
|
|
322
|
+
)}
|
|
323
|
+
|
|
324
|
+
{/* Bottom controls always at bottom */}
|
|
325
|
+
<HStack style={styles.controlsContainer}>
|
|
326
|
+
<View style={styles.leftControls}>
|
|
327
|
+
<TouchableOpacity onPress={onSelectImages} style={styles.actionButton}>
|
|
328
|
+
<MaterialIcons name="add" size={24} color="#888" />
|
|
329
|
+
</TouchableOpacity>
|
|
330
|
+
</View>
|
|
331
|
+
|
|
332
|
+
<TouchableOpacity
|
|
333
|
+
onPress={() => {
|
|
334
|
+
// Make sure input is focused and synchronized before sending
|
|
335
|
+
if (inputRef.current) {
|
|
336
|
+
// Force a blur to commit any pending text changes
|
|
337
|
+
inputRef.current.blur();
|
|
338
|
+
// Short timeout to ensure state is updated
|
|
339
|
+
setTimeout(() => {
|
|
340
|
+
onSend();
|
|
341
|
+
}, 50);
|
|
342
|
+
} else {
|
|
343
|
+
onSend();
|
|
344
|
+
}
|
|
345
|
+
}}
|
|
346
|
+
disabled={isSendDisabled || loading}
|
|
347
|
+
style={styles.sendIconContainer}
|
|
348
|
+
>
|
|
349
|
+
<View style={{ padding: 4 }}>
|
|
350
|
+
{loading ? (
|
|
351
|
+
<View
|
|
352
|
+
style={{
|
|
353
|
+
width: 32,
|
|
354
|
+
height: 32,
|
|
355
|
+
alignItems: 'center',
|
|
356
|
+
justifyContent: 'center',
|
|
357
|
+
}}
|
|
358
|
+
>
|
|
359
|
+
<ActivityIndicator size="small" color={colors.blue[400]} />
|
|
360
|
+
</View>
|
|
361
|
+
) : (
|
|
362
|
+
<MaterialCommunityIcons
|
|
363
|
+
name="send-circle"
|
|
364
|
+
size={32}
|
|
365
|
+
color={isSendDisabled ? colors.gray[400] : colors.blue[500]}
|
|
366
|
+
/>
|
|
367
|
+
)}
|
|
368
|
+
</View>
|
|
369
|
+
</TouchableOpacity>
|
|
370
|
+
</HStack>
|
|
371
|
+
</View>
|
|
372
|
+
</Animated.View>
|
|
373
|
+
</KeyboardAvoidingView>
|
|
374
|
+
</Modal>
|
|
375
|
+
);
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
const styles = StyleSheet.create({
|
|
379
|
+
container: {
|
|
380
|
+
flex: 1,
|
|
381
|
+
justifyContent: 'flex-end',
|
|
382
|
+
},
|
|
383
|
+
backdrop: {
|
|
384
|
+
position: 'absolute',
|
|
385
|
+
top: 0,
|
|
386
|
+
left: 0,
|
|
387
|
+
right: 0,
|
|
388
|
+
bottom: 0,
|
|
389
|
+
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
390
|
+
},
|
|
391
|
+
sheetContainer: {
|
|
392
|
+
backgroundColor: 'white',
|
|
393
|
+
borderTopLeftRadius: 20,
|
|
394
|
+
borderTopRightRadius: 20,
|
|
395
|
+
overflow: 'hidden',
|
|
396
|
+
paddingBottom: 15,
|
|
397
|
+
elevation: 5, // For Android
|
|
398
|
+
shadowColor: '#000', // For iOS
|
|
399
|
+
shadowOffset: { width: 0, height: -3 },
|
|
400
|
+
shadowOpacity: 0.2,
|
|
401
|
+
shadowRadius: 5,
|
|
402
|
+
width: SCREEN_WIDTH,
|
|
403
|
+
},
|
|
404
|
+
handleContainer: {
|
|
405
|
+
height: HANDLE_HEIGHT,
|
|
406
|
+
width: '100%',
|
|
407
|
+
alignItems: 'center',
|
|
408
|
+
justifyContent: 'center',
|
|
409
|
+
},
|
|
410
|
+
handle: {
|
|
411
|
+
width: 40,
|
|
412
|
+
height: 5,
|
|
413
|
+
borderRadius: 3,
|
|
414
|
+
backgroundColor: '#ddd',
|
|
415
|
+
},
|
|
416
|
+
sheetContent: {
|
|
417
|
+
flex: 1,
|
|
418
|
+
paddingHorizontal: 15,
|
|
419
|
+
paddingTop: 0,
|
|
420
|
+
flexDirection: 'column',
|
|
421
|
+
justifyContent: 'space-between',
|
|
422
|
+
},
|
|
423
|
+
inputContainer: {
|
|
424
|
+
backgroundColor: '#fff',
|
|
425
|
+
borderRadius: 12,
|
|
426
|
+
padding: 12,
|
|
427
|
+
marginTop: 5,
|
|
428
|
+
// marginBottom: 10,
|
|
429
|
+
},
|
|
430
|
+
textInput: {
|
|
431
|
+
backgroundColor: 'transparent',
|
|
432
|
+
borderWidth: 0,
|
|
433
|
+
fontSize: 16,
|
|
434
|
+
color: '#444',
|
|
435
|
+
paddingVertical: 0,
|
|
436
|
+
paddingHorizontal: 0,
|
|
437
|
+
minHeight: 40,
|
|
438
|
+
},
|
|
439
|
+
textInputExpanded: {
|
|
440
|
+
minHeight: 80,
|
|
441
|
+
maxHeight: 200,
|
|
442
|
+
},
|
|
443
|
+
imagePreviewWrapper: {
|
|
444
|
+
marginBottom: 10,
|
|
445
|
+
},
|
|
446
|
+
imagePreviewContainer: {
|
|
447
|
+
height: 65,
|
|
448
|
+
},
|
|
449
|
+
imagePreviewContent: {
|
|
450
|
+
alignItems: 'center',
|
|
451
|
+
paddingRight: 5,
|
|
452
|
+
},
|
|
453
|
+
extraContentArea: {
|
|
454
|
+
flex: 1,
|
|
455
|
+
marginBottom: 10,
|
|
456
|
+
},
|
|
457
|
+
expandedContentPlaceholder: {
|
|
458
|
+
height: 20,
|
|
459
|
+
},
|
|
460
|
+
controlsContainer: {
|
|
461
|
+
height: 45,
|
|
462
|
+
alignItems: 'center',
|
|
463
|
+
justifyContent: 'space-between',
|
|
464
|
+
paddingHorizontal: 0,
|
|
465
|
+
flexDirection: 'row',
|
|
466
|
+
// borderTopWidth: 1,
|
|
467
|
+
// borderTopColor: colors.gray[200],
|
|
468
|
+
// paddingTop: 5,
|
|
469
|
+
paddingBottom: 10,
|
|
470
|
+
},
|
|
471
|
+
leftControls: {
|
|
472
|
+
flexDirection: 'row',
|
|
473
|
+
alignItems: 'center',
|
|
474
|
+
},
|
|
475
|
+
actionButton: {
|
|
476
|
+
width: 40,
|
|
477
|
+
height: 40,
|
|
478
|
+
borderRadius: 20,
|
|
479
|
+
alignItems: 'center',
|
|
480
|
+
justifyContent: 'center',
|
|
481
|
+
marginRight: 8,
|
|
482
|
+
// padding: 6,
|
|
483
|
+
},
|
|
484
|
+
imagePreview: {
|
|
485
|
+
width: 60,
|
|
486
|
+
height: 60,
|
|
487
|
+
marginRight: 8,
|
|
488
|
+
position: 'relative',
|
|
489
|
+
},
|
|
490
|
+
imageBox: {
|
|
491
|
+
width: '100%',
|
|
492
|
+
height: '100%',
|
|
493
|
+
borderRadius: 8,
|
|
494
|
+
overflow: 'hidden',
|
|
495
|
+
backgroundColor: colors.gray[200],
|
|
496
|
+
},
|
|
497
|
+
removeImageButton: {
|
|
498
|
+
position: 'absolute',
|
|
499
|
+
top: -5,
|
|
500
|
+
right: -5,
|
|
501
|
+
backgroundColor: 'rgba(0,0,0,0.6)',
|
|
502
|
+
borderRadius: 12,
|
|
503
|
+
width: 20,
|
|
504
|
+
height: 20,
|
|
505
|
+
alignItems: 'center',
|
|
506
|
+
justifyContent: 'center',
|
|
507
|
+
zIndex: 10,
|
|
508
|
+
},
|
|
509
|
+
sendIconContainer: {
|
|
510
|
+
width: 48,
|
|
511
|
+
height: 48,
|
|
512
|
+
alignItems: 'center',
|
|
513
|
+
justifyContent: 'center',
|
|
514
|
+
// padding: 6,
|
|
515
|
+
},
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
export default ExpandableInputActionSheet;
|