react-native-gifted-chat 2.8.1 → 2.8.2-alpha.1
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/README.md +18 -17
- package/package.json +41 -35
- package/src/Bubble/index.tsx +15 -39
- package/src/Bubble/types.ts +5 -5
- package/src/Composer.tsx +19 -26
- package/src/Constant.ts +0 -1
- package/src/GiftedAvatar.tsx +29 -36
- package/src/GiftedChat/index.tsx +34 -65
- package/src/GiftedChat/types.ts +8 -53
- package/src/InputToolbar.tsx +25 -8
- package/src/LoadEarlier.tsx +19 -17
- package/src/MessageAudio.tsx +19 -7
- package/src/MessageContainer/components/DayAnimated/index.tsx +14 -9
- package/src/MessageContainer/components/Item/index.tsx +7 -1
- package/src/MessageContainer/index.tsx +104 -64
- package/src/MessageContainer/styles.ts +3 -2
- package/src/MessageContainer/types.ts +36 -14
- package/src/MessageImage.tsx +18 -6
- package/src/MessageText.tsx +88 -128
- package/src/MessageVideo.tsx +19 -7
- package/src/QuickReplies.tsx +17 -10
- package/src/Send.tsx +7 -1
- package/src/SystemMessage.tsx +12 -2
- package/src/Time.tsx +9 -2
- package/src/TypingIndicator/index.tsx +2 -1
- package/src/TypingIndicator/types.ts +3 -0
- package/src/__tests__/Actions.test.tsx +3 -4
- package/src/__tests__/Avatar.test.tsx +5 -6
- package/src/__tests__/Bubble.test.tsx +14 -19
- package/src/__tests__/Composer.test.tsx +3 -4
- package/src/__tests__/Day.test.tsx +5 -8
- package/src/__tests__/DayAnimated.test.tsx +52 -0
- package/src/__tests__/GiftedAvatar.test.tsx +3 -8
- package/src/__tests__/GiftedChat.test.tsx +37 -21
- package/src/__tests__/InputToolbar.test.tsx +3 -4
- package/src/__tests__/LoadEarlier.test.tsx +3 -4
- package/src/__tests__/Message.test.tsx +51 -58
- package/src/__tests__/MessageContainer.test.tsx +39 -5
- package/src/__tests__/MessageImage.test.tsx +12 -15
- package/src/__tests__/MessageText.test.tsx +7 -4
- package/src/__tests__/Send.test.tsx +7 -8
- package/src/__tests__/SystemMessage.test.tsx +12 -15
- package/src/__tests__/Time.test.tsx +5 -8
- package/src/__tests__/__snapshots__/Bubble.test.tsx.snap +48 -50
- package/src/__tests__/__snapshots__/Composer.test.tsx.snap +1 -2
- package/src/__tests__/__snapshots__/Constant.test.tsx.snap +0 -1
- package/src/__tests__/__snapshots__/DayAnimated.test.tsx.snap +5 -0
- package/src/__tests__/__snapshots__/GiftedChat.test.tsx.snap +25 -0
- package/src/__tests__/__snapshots__/InputToolbar.test.tsx.snap +2 -2
- package/src/__tests__/__snapshots__/Message.test.tsx.snap +146 -150
- package/src/__tests__/__snapshots__/MessageImage.test.tsx.snap +12 -10
- package/src/__tests__/__snapshots__/MessageText.test.tsx.snap +12 -8
- package/src/__tests__/__snapshots__/Send.test.tsx.snap +2 -0
- package/src/reanimatedCompat.ts +27 -0
- package/src/types.ts +4 -0
- package/src/utils.ts +77 -1
- package/lib/Actions.d.ts +0 -14
- package/lib/Actions.js +0 -57
- package/lib/Actions.js.map +0 -1
- package/lib/Avatar.d.ts +0 -18
- package/lib/Avatar.js +0 -93
- package/lib/Avatar.js.map +0 -1
- package/lib/Bubble/index.d.ts +0 -6
- package/lib/Bubble/index.js +0 -257
- package/lib/Bubble/index.js.map +0 -1
- package/lib/Bubble/styles.d.ts +0 -69
- package/lib/Bubble/styles.js +0 -72
- package/lib/Bubble/styles.js.map +0 -1
- package/lib/Bubble/types.d.ts +0 -47
- package/lib/Bubble/types.js +0 -2
- package/lib/Bubble/types.js.map +0 -1
- package/lib/Color.d.ts +0 -18
- package/lib/Color.js +0 -18
- package/lib/Color.js.map +0 -1
- package/lib/Composer.d.ts +0 -20
- package/lib/Composer.js +0 -60
- package/lib/Composer.js.map +0 -1
- package/lib/Constant.d.ts +0 -10
- package/lib/Constant.js +0 -17
- package/lib/Constant.js.map +0 -1
- package/lib/Day/index.d.ts +0 -4
- package/lib/Day/index.js +0 -39
- package/lib/Day/index.js.map +0 -1
- package/lib/Day/styles.d.ts +0 -20
- package/lib/Day/styles.js +0 -22
- package/lib/Day/styles.js.map +0 -1
- package/lib/Day/types.d.ts +0 -9
- package/lib/Day/types.js +0 -2
- package/lib/Day/types.js.map +0 -1
- package/lib/GiftedAvatar.d.ts +0 -11
- package/lib/GiftedAvatar.js +0 -104
- package/lib/GiftedAvatar.js.map +0 -1
- package/lib/GiftedChat/index.d.ts +0 -26
- package/lib/GiftedChat/index.js +0 -302
- package/lib/GiftedChat/index.js.map +0 -1
- package/lib/GiftedChat/styles.d.ts +0 -6
- package/lib/GiftedChat/styles.js +0 -7
- package/lib/GiftedChat/styles.js.map +0 -1
- package/lib/GiftedChat/types.d.ts +0 -117
- package/lib/GiftedChat/types.js +0 -2
- package/lib/GiftedChat/types.js.map +0 -1
- package/lib/GiftedChatContext.d.ts +0 -9
- package/lib/GiftedChatContext.js +0 -9
- package/lib/GiftedChatContext.js.map +0 -1
- package/lib/InputToolbar.d.ts +0 -23
- package/lib/InputToolbar.js +0 -56
- package/lib/InputToolbar.js.map +0 -1
- package/lib/LoadEarlier.d.ts +0 -14
- package/lib/LoadEarlier.js +0 -45
- package/lib/LoadEarlier.js.map +0 -1
- package/lib/Message/index.d.ts +0 -6
- package/lib/Message/index.js +0 -80
- package/lib/Message/index.js.map +0 -1
- package/lib/Message/styles.d.ts +0 -21
- package/lib/Message/styles.js +0 -22
- package/lib/Message/styles.js.map +0 -1
- package/lib/Message/types.d.ts +0 -22
- package/lib/Message/types.js +0 -2
- package/lib/Message/types.js.map +0 -1
- package/lib/MessageAudio.d.ts +0 -2
- package/lib/MessageAudio.js +0 -14
- package/lib/MessageAudio.js.map +0 -1
- package/lib/MessageContainer/components/DayAnimated/index.d.ts +0 -5
- package/lib/MessageContainer/components/DayAnimated/index.js +0 -85
- package/lib/MessageContainer/components/DayAnimated/index.js.map +0 -1
- package/lib/MessageContainer/components/DayAnimated/styles.d.ts +0 -11
- package/lib/MessageContainer/components/DayAnimated/styles.js +0 -12
- package/lib/MessageContainer/components/DayAnimated/styles.js.map +0 -1
- package/lib/MessageContainer/components/DayAnimated/types.d.ts +0 -17
- package/lib/MessageContainer/components/DayAnimated/types.js +0 -2
- package/lib/MessageContainer/components/DayAnimated/types.js.map +0 -1
- package/lib/MessageContainer/components/Item/index.d.ts +0 -23
- package/lib/MessageContainer/components/Item/index.js +0 -88
- package/lib/MessageContainer/components/Item/index.js.map +0 -1
- package/lib/MessageContainer/components/Item/types.d.ts +0 -17
- package/lib/MessageContainer/components/Item/types.js +0 -2
- package/lib/MessageContainer/components/Item/types.js.map +0 -1
- package/lib/MessageContainer/index.d.ts +0 -6
- package/lib/MessageContainer/index.js +0 -224
- package/lib/MessageContainer/index.js.map +0 -1
- package/lib/MessageContainer/styles.d.ts +0 -34
- package/lib/MessageContainer/styles.js +0 -31
- package/lib/MessageContainer/styles.js.map +0 -1
- package/lib/MessageContainer/types.d.ts +0 -54
- package/lib/MessageContainer/types.js +0 -2
- package/lib/MessageContainer/types.js.map +0 -1
- package/lib/MessageImage.d.ts +0 -13
- package/lib/MessageImage.js +0 -30
- package/lib/MessageImage.js.map +0 -1
- package/lib/MessageText.d.ts +0 -15
- package/lib/MessageText.js +0 -108
- package/lib/MessageText.js.map +0 -1
- package/lib/MessageVideo.d.ts +0 -2
- package/lib/MessageVideo.js +0 -14
- package/lib/MessageVideo.js.map +0 -1
- package/lib/QuickReplies.d.ts +0 -15
- package/lib/QuickReplies.js +0 -101
- package/lib/QuickReplies.js.map +0 -1
- package/lib/Send.d.ts +0 -15
- package/lib/Send.js +0 -34
- package/lib/Send.js.map +0 -1
- package/lib/SystemMessage.d.ts +0 -10
- package/lib/SystemMessage.js +0 -26
- package/lib/SystemMessage.js.map +0 -1
- package/lib/Time.d.ts +0 -11
- package/lib/Time.js +0 -56
- package/lib/Time.js.map +0 -1
- package/lib/TypingIndicator/index.d.ts +0 -5
- package/lib/TypingIndicator/index.js +0 -94
- package/lib/TypingIndicator/index.js.map +0 -1
- package/lib/TypingIndicator/styles.d.ts +0 -20
- package/lib/TypingIndicator/styles.js +0 -22
- package/lib/TypingIndicator/styles.js.map +0 -1
- package/lib/TypingIndicator/types.d.ts +0 -3
- package/lib/TypingIndicator/types.js +0 -2
- package/lib/TypingIndicator/types.js.map +0 -1
- package/lib/hooks/useUpdateLayoutEffect.d.ts +0 -8
- package/lib/hooks/useUpdateLayoutEffect.js +0 -17
- package/lib/hooks/useUpdateLayoutEffect.js.map +0 -1
- package/lib/index.d.ts +0 -4
- package/lib/index.js +0 -5
- package/lib/index.js.map +0 -1
- package/lib/logging.d.ts +0 -2
- package/lib/logging.js +0 -5
- package/lib/logging.js.map +0 -1
- package/lib/styles.d.ts +0 -10
- package/lib/styles.js +0 -11
- package/lib/styles.js.map +0 -1
- package/lib/types.d.ts +0 -67
- package/lib/types.js +0 -2
- package/lib/types.js.map +0 -1
- package/lib/utils.d.ts +0 -3
- package/lib/utils.js +0 -17
- package/lib/utils.js.map +0 -1
- package/src/__tests__/__snapshots__/MessageContainer.test.tsx.snap +0 -101
package/src/GiftedChat/index.tsx
CHANGED
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
import dayjs from 'dayjs'
|
|
15
15
|
import localizedFormat from 'dayjs/plugin/localizedFormat'
|
|
16
16
|
import {
|
|
17
|
-
Platform,
|
|
18
17
|
TextInput,
|
|
19
18
|
View,
|
|
20
19
|
LayoutChangeEvent,
|
|
@@ -72,23 +71,18 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
|
|
|
72
71
|
onSend,
|
|
73
72
|
locale = 'en',
|
|
74
73
|
renderLoading,
|
|
75
|
-
actionSheet
|
|
74
|
+
actionSheet,
|
|
76
75
|
textInputProps,
|
|
77
|
-
renderChatFooter
|
|
78
|
-
renderInputToolbar
|
|
76
|
+
renderChatFooter,
|
|
77
|
+
renderInputToolbar,
|
|
79
78
|
bottomOffset = 0,
|
|
80
79
|
focusOnInputWhenOpeningKeyboard = true,
|
|
81
|
-
|
|
82
|
-
ios: 'never',
|
|
83
|
-
android: 'always',
|
|
84
|
-
default: 'never',
|
|
85
|
-
}),
|
|
86
|
-
onInputTextChanged = null,
|
|
87
|
-
maxInputLength = null,
|
|
80
|
+
onInputTextChanged,
|
|
88
81
|
inverted = true,
|
|
89
82
|
minComposerHeight = MIN_COMPOSER_HEIGHT,
|
|
90
83
|
maxComposerHeight = MAX_COMPOSER_HEIGHT,
|
|
91
84
|
isKeyboardInternallyHandled = true,
|
|
85
|
+
disableKeyboardController = false,
|
|
92
86
|
} = props
|
|
93
87
|
|
|
94
88
|
const actionSheetRef = useRef<ActionSheetProviderRef>(null)
|
|
@@ -110,11 +104,18 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
|
|
|
110
104
|
minComposerHeight!
|
|
111
105
|
)
|
|
112
106
|
const [text, setText] = useState<string | undefined>(() => props.text || '')
|
|
113
|
-
const [isTypingDisabled, setIsTypingDisabled] = useState<boolean>(false)
|
|
114
107
|
|
|
115
|
-
|
|
108
|
+
// Always call the hook, but conditionally use its data
|
|
109
|
+
const keyboardControllerData = useReanimatedKeyboardAnimation()
|
|
110
|
+
|
|
111
|
+
// Create a mock keyboard object when disabled
|
|
112
|
+
const keyboard = useMemo(() => {
|
|
113
|
+
if (disableKeyboardController)
|
|
114
|
+
return { height: { value: 0 } }
|
|
115
|
+
return keyboardControllerData
|
|
116
|
+
}, [disableKeyboardController, keyboardControllerData])
|
|
117
|
+
|
|
116
118
|
const trackingKeyboardMovement = useSharedValue(false)
|
|
117
|
-
const debounceEnableTypingTimeoutId = useRef<ReturnType<typeof setTimeout>>(undefined)
|
|
118
119
|
const keyboardOffsetBottom = useSharedValue(0)
|
|
119
120
|
|
|
120
121
|
const contentStyleAnim = useAnimatedStyle(
|
|
@@ -164,23 +165,6 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
|
|
|
164
165
|
isTextInputWasFocused.current = false
|
|
165
166
|
}, [textInputRef])
|
|
166
167
|
|
|
167
|
-
const disableTyping = useCallback(() => {
|
|
168
|
-
clearTimeout(debounceEnableTypingTimeoutId.current)
|
|
169
|
-
setIsTypingDisabled(true)
|
|
170
|
-
}, [])
|
|
171
|
-
|
|
172
|
-
const enableTyping = useCallback(() => {
|
|
173
|
-
clearTimeout(debounceEnableTypingTimeoutId.current)
|
|
174
|
-
setIsTypingDisabled(false)
|
|
175
|
-
}, [])
|
|
176
|
-
|
|
177
|
-
const debounceEnableTyping = useCallback(() => {
|
|
178
|
-
clearTimeout(debounceEnableTypingTimeoutId.current)
|
|
179
|
-
debounceEnableTypingTimeoutId.current = setTimeout(() => {
|
|
180
|
-
enableTyping()
|
|
181
|
-
}, 50)
|
|
182
|
-
}, [enableTyping])
|
|
183
|
-
|
|
184
168
|
const scrollToBottom = useCallback(
|
|
185
169
|
(isAnimated = true) => {
|
|
186
170
|
if (!messageContainerRef?.current)
|
|
@@ -209,10 +193,7 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
|
|
|
209
193
|
<View style={[stylesCommon.fill, messagesContainerStyle]}>
|
|
210
194
|
<MessageContainer<TMessage>
|
|
211
195
|
{...messagesContainerProps}
|
|
212
|
-
|
|
213
|
-
inverted,
|
|
214
|
-
keyboardShouldPersistTaps,
|
|
215
|
-
}}
|
|
196
|
+
inverted={inverted}
|
|
216
197
|
messages={messages}
|
|
217
198
|
forwardRef={messageContainerRef}
|
|
218
199
|
isTyping={isTyping}
|
|
@@ -226,7 +207,6 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
|
|
|
226
207
|
messages,
|
|
227
208
|
props,
|
|
228
209
|
inverted,
|
|
229
|
-
keyboardShouldPersistTaps,
|
|
230
210
|
messageContainerRef,
|
|
231
211
|
renderChatFooter,
|
|
232
212
|
])
|
|
@@ -242,13 +222,11 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
|
|
|
242
222
|
|
|
243
223
|
setComposerHeight(minComposerHeight!)
|
|
244
224
|
setText(getTextFromProp(''))
|
|
245
|
-
enableTyping()
|
|
246
225
|
}, [
|
|
247
226
|
minComposerHeight,
|
|
248
227
|
getTextFromProp,
|
|
249
228
|
textInputRef,
|
|
250
229
|
notifyInputTextReset,
|
|
251
|
-
enableTyping,
|
|
252
230
|
])
|
|
253
231
|
|
|
254
232
|
const _onSend = useCallback(
|
|
@@ -265,17 +243,14 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
|
|
|
265
243
|
}
|
|
266
244
|
})
|
|
267
245
|
|
|
268
|
-
if (shouldResetInputToolbar === true)
|
|
269
|
-
disableTyping()
|
|
270
|
-
|
|
246
|
+
if (shouldResetInputToolbar === true)
|
|
271
247
|
resetInputToolbar()
|
|
272
|
-
}
|
|
273
248
|
|
|
274
249
|
onSend?.(newMessages)
|
|
275
250
|
|
|
276
251
|
setTimeout(() => scrollToBottom(), 10)
|
|
277
252
|
},
|
|
278
|
-
[messageIdGenerator, onSend, user, resetInputToolbar,
|
|
253
|
+
[messageIdGenerator, onSend, user, resetInputToolbar, scrollToBottom]
|
|
279
254
|
)
|
|
280
255
|
|
|
281
256
|
const onInputSizeChanged = useCallback(
|
|
@@ -291,17 +266,14 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
|
|
|
291
266
|
)
|
|
292
267
|
|
|
293
268
|
const _onInputTextChanged = useCallback(
|
|
294
|
-
(
|
|
295
|
-
|
|
296
|
-
return
|
|
297
|
-
|
|
298
|
-
onInputTextChanged?.(_text)
|
|
269
|
+
(text: string) => {
|
|
270
|
+
onInputTextChanged?.(text)
|
|
299
271
|
|
|
300
272
|
// Only set state if it's not being overridden by a prop.
|
|
301
273
|
if (props.text === undefined)
|
|
302
|
-
setText(
|
|
274
|
+
setText(text)
|
|
303
275
|
},
|
|
304
|
-
[onInputTextChanged,
|
|
276
|
+
[onInputTextChanged, props.text]
|
|
305
277
|
)
|
|
306
278
|
|
|
307
279
|
const onInitialLayoutViewLayout = useCallback(
|
|
@@ -337,7 +309,6 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
|
|
|
337
309
|
textInputProps: {
|
|
338
310
|
...textInputProps,
|
|
339
311
|
ref: textInputRef,
|
|
340
|
-
maxLength: isTypingDisabled ? 0 : maxInputLength,
|
|
341
312
|
},
|
|
342
313
|
}
|
|
343
314
|
|
|
@@ -349,14 +320,12 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
|
|
|
349
320
|
isInitialized,
|
|
350
321
|
_onSend,
|
|
351
322
|
getTextFromProp,
|
|
352
|
-
maxInputLength,
|
|
353
323
|
minComposerHeight,
|
|
354
324
|
onInputSizeChanged,
|
|
355
325
|
props,
|
|
356
326
|
text,
|
|
357
327
|
renderInputToolbar,
|
|
358
328
|
composerHeight,
|
|
359
|
-
isTypingDisabled,
|
|
360
329
|
textInputRef,
|
|
361
330
|
textInputProps,
|
|
362
331
|
_onInputTextChanged,
|
|
@@ -380,9 +349,14 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
|
|
|
380
349
|
setText(props.text)
|
|
381
350
|
}, [props.text])
|
|
382
351
|
|
|
352
|
+
// Only set up keyboard animation when keyboard controller is enabled
|
|
383
353
|
useAnimatedReaction(
|
|
384
|
-
() => -keyboard.height.value,
|
|
354
|
+
() => disableKeyboardController ? 0 : -keyboard.height.value,
|
|
385
355
|
(value, prevValue) => {
|
|
356
|
+
// Skip keyboard handling when disabled
|
|
357
|
+
if (disableKeyboardController)
|
|
358
|
+
return
|
|
359
|
+
|
|
386
360
|
if (prevValue !== null && value !== prevValue) {
|
|
387
361
|
const isKeyboardMovingUp = value > prevValue
|
|
388
362
|
if (isKeyboardMovingUp !== trackingKeyboardMovement.value) {
|
|
@@ -400,13 +374,6 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
|
|
|
400
374
|
runOnJS(handleTextInputFocusWhenKeyboardShow)()
|
|
401
375
|
else
|
|
402
376
|
runOnJS(handleTextInputFocusWhenKeyboardHide)()
|
|
403
|
-
|
|
404
|
-
if (value === 0) {
|
|
405
|
-
runOnJS(enableTyping)()
|
|
406
|
-
} else {
|
|
407
|
-
runOnJS(disableTyping)()
|
|
408
|
-
runOnJS(debounceEnableTyping)()
|
|
409
|
-
}
|
|
410
377
|
}
|
|
411
378
|
}
|
|
412
379
|
},
|
|
@@ -416,10 +383,8 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
|
|
|
416
383
|
focusOnInputWhenOpeningKeyboard,
|
|
417
384
|
handleTextInputFocusWhenKeyboardHide,
|
|
418
385
|
handleTextInputFocusWhenKeyboardShow,
|
|
419
|
-
enableTyping,
|
|
420
|
-
disableTyping,
|
|
421
|
-
debounceEnableTyping,
|
|
422
386
|
bottomOffset,
|
|
387
|
+
disableKeyboardController,
|
|
423
388
|
]
|
|
424
389
|
)
|
|
425
390
|
|
|
@@ -433,7 +398,7 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
|
|
|
433
398
|
>
|
|
434
399
|
{isInitialized
|
|
435
400
|
? (
|
|
436
|
-
<Animated.View style={[stylesCommon.fill, isKeyboardInternallyHandled && contentStyleAnim]}>
|
|
401
|
+
<Animated.View style={[stylesCommon.fill, (isKeyboardInternallyHandled && !disableKeyboardController) && contentStyleAnim]}>
|
|
437
402
|
{renderMessages}
|
|
438
403
|
{inputToolbarFragment}
|
|
439
404
|
</Animated.View>
|
|
@@ -448,6 +413,10 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
|
|
|
448
413
|
}
|
|
449
414
|
|
|
450
415
|
function GiftedChatWrapper<TMessage extends IMessage = IMessage> (props: GiftedChatProps<TMessage>) {
|
|
416
|
+
// Don't use KeyboardProvider when keyboard controller is disabled
|
|
417
|
+
if (props.disableKeyboardController)
|
|
418
|
+
return <GiftedChat<TMessage> {...props} />
|
|
419
|
+
|
|
451
420
|
return (
|
|
452
421
|
<KeyboardProvider>
|
|
453
422
|
<GiftedChat<TMessage> {...props} />
|
package/src/GiftedChat/types.ts
CHANGED
|
@@ -12,9 +12,7 @@ import { LightboxProps } from 'react-native-lightbox-v2'
|
|
|
12
12
|
import { ActionsProps } from '../Actions'
|
|
13
13
|
import { AvatarProps } from '../Avatar'
|
|
14
14
|
import { ComposerProps } from '../Composer'
|
|
15
|
-
import { DayProps } from '../Day'
|
|
16
15
|
import { InputToolbarProps } from '../InputToolbar'
|
|
17
|
-
import { LoadEarlierProps } from '../LoadEarlier'
|
|
18
16
|
import { MessageProps } from '../Message'
|
|
19
17
|
import { MessageImageProps } from '../MessageImage'
|
|
20
18
|
import { MessageTextProps } from '../MessageText'
|
|
@@ -23,14 +21,13 @@ import {
|
|
|
23
21
|
LeftRightStyle,
|
|
24
22
|
MessageAudioProps,
|
|
25
23
|
MessageVideoProps,
|
|
26
|
-
Reply,
|
|
27
24
|
User,
|
|
28
25
|
} from '../types'
|
|
29
26
|
import { QuickRepliesProps } from '../QuickReplies'
|
|
30
27
|
import { SendProps } from '../Send'
|
|
31
28
|
import { SystemMessageProps } from '../SystemMessage'
|
|
32
29
|
import { TimeProps } from '../Time'
|
|
33
|
-
import { AnimatedList,
|
|
30
|
+
import { AnimatedList, MessageContainerProps } from '../MessageContainer'
|
|
34
31
|
import { BubbleProps } from '../Bubble'
|
|
35
32
|
|
|
36
33
|
export interface GiftedChatProps<TMessage extends IMessage> extends Partial<MessageContainerProps<TMessage>> {
|
|
@@ -38,27 +35,13 @@ export interface GiftedChatProps<TMessage extends IMessage> extends Partial<Mess
|
|
|
38
35
|
messageContainerRef?: RefObject<AnimatedList<TMessage>>
|
|
39
36
|
/* text input ref */
|
|
40
37
|
textInputRef?: RefObject<TextInput>
|
|
41
|
-
/* Messages to display */
|
|
42
|
-
messages?: TMessage[]
|
|
43
|
-
/* Typing Indicator state */
|
|
44
|
-
isTyping?: boolean
|
|
45
38
|
/* Controls whether or not to show user.name property in the message bubble */
|
|
46
39
|
renderUsernameOnMessage?: boolean
|
|
47
40
|
/* Messages container style */
|
|
48
41
|
messagesContainerStyle?: StyleProp<ViewStyle>
|
|
49
42
|
/* Input text; default is undefined, but if specified, it will override GiftedChat's internal state */
|
|
50
43
|
text?: string
|
|
51
|
-
/* Controls whether or not the message bubbles appear at the top of the chat */
|
|
52
|
-
alignTop?: boolean
|
|
53
|
-
/* enables the isScrollToBottomEnabled Component */
|
|
54
|
-
isScrollToBottomEnabled?: boolean
|
|
55
|
-
/* Scroll to bottom wrapper style */
|
|
56
|
-
scrollToBottomStyle?: StyleProp<ViewStyle>
|
|
57
44
|
initialText?: string
|
|
58
|
-
/* Placeholder when text is empty; default is 'Type a message...' */
|
|
59
|
-
placeholder?: string
|
|
60
|
-
/* Makes the composer not editable */
|
|
61
|
-
disableComposer?: boolean
|
|
62
45
|
/* User sending the messages: { _id, name, avatar } */
|
|
63
46
|
user?: User
|
|
64
47
|
/* Locale to localize the dates */
|
|
@@ -69,19 +52,16 @@ export interface GiftedChatProps<TMessage extends IMessage> extends Partial<Mess
|
|
|
69
52
|
dateFormat?: string
|
|
70
53
|
/* Format to use for rendering relative times; Today - for now. See more: https://day.js.org/docs/en/plugin/calendar */
|
|
71
54
|
dateFormatCalendar?: object
|
|
72
|
-
/* Enables the "Load earlier messages" button */
|
|
73
|
-
loadEarlier?: boolean
|
|
74
|
-
/* Display an ActivityIndicator when loading earlier messages */
|
|
75
|
-
isLoadingEarlier?: boolean
|
|
76
55
|
/* Determine whether to handle keyboard awareness inside the plugin. If you have your own keyboard handling outside the plugin set this to false; default is `true` */
|
|
77
56
|
isKeyboardInternallyHandled?: boolean
|
|
57
|
+
/* Completely disable react-native-keyboard-controller. Useful when using react-native-navigation or other conflicting keyboard libraries; default is `false` */
|
|
58
|
+
disableKeyboardController?: boolean
|
|
78
59
|
/* Whether to render an avatar for the current user; default is false, only show avatars for other users */
|
|
79
60
|
showUserAvatar?: boolean
|
|
80
61
|
/* When false, avatars will only be displayed when a consecutive message is from the same user on the same day; default is false */
|
|
81
62
|
showAvatarForEveryMessage?: boolean
|
|
82
63
|
/* Render the message avatar at the top of consecutive messages, rather than the bottom; default is false */
|
|
83
64
|
renderAvatarOnTop?: boolean
|
|
84
|
-
inverted?: boolean
|
|
85
65
|
/* Extra props to be passed to the <Image> component created by the default renderMessageImage */
|
|
86
66
|
imageProps?: MessageImageProps<TMessage>
|
|
87
67
|
/* Extra props to be passed to the MessageImage's Lightbox */
|
|
@@ -92,20 +72,12 @@ export interface GiftedChatProps<TMessage extends IMessage> extends Partial<Mess
|
|
|
92
72
|
focusOnInputWhenOpeningKeyboard?: boolean
|
|
93
73
|
/* Minimum height of the input toolbar; default is 44 */
|
|
94
74
|
minInputToolbarHeight?: number
|
|
95
|
-
/*
|
|
96
|
-
|
|
97
|
-
/* Extra props to be passed to the <TextInput> */
|
|
98
|
-
textInputProps?: object
|
|
99
|
-
/* Determines whether the keyboard should stay visible after a tap; see <ScrollView> docs */
|
|
100
|
-
keyboardShouldPersistTaps?: 'always' | 'never' | 'handled'
|
|
101
|
-
/* Max message composer TextInput length */
|
|
102
|
-
maxInputLength?: number
|
|
75
|
+
/* Extra props to be passed to the <TextInput>. See https://reactnative.dev/docs/textinput */
|
|
76
|
+
textInputProps?: Partial<React.ComponentProps<typeof TextInput>>
|
|
103
77
|
/* Force send button */
|
|
104
78
|
alwaysShowSend?: boolean
|
|
105
79
|
/* Image style */
|
|
106
80
|
imageStyle?: StyleProp<ViewStyle>
|
|
107
|
-
/* This can be used to pass unknown data which needs to be re-rendered */
|
|
108
|
-
extraData?: object
|
|
109
81
|
/* composer min Height */
|
|
110
82
|
minComposerHeight?: number
|
|
111
83
|
/* composer min Height */
|
|
@@ -117,8 +89,6 @@ export interface GiftedChatProps<TMessage extends IMessage> extends Partial<Mess
|
|
|
117
89
|
quickReplyContainerStyle?: StyleProp<ViewStyle>
|
|
118
90
|
/* optional prop used to place customView below text, image and video views; default is false */
|
|
119
91
|
isCustomViewBottom?: boolean
|
|
120
|
-
/* infinite scroll up when reach the top of messages container, automatically call onLoadEarlier function if exist */
|
|
121
|
-
infiniteScroll?: boolean
|
|
122
92
|
timeTextStyle?: LeftRightStyle<TextStyle>
|
|
123
93
|
/* Custom action sheet */
|
|
124
94
|
actionSheet?(): {
|
|
@@ -135,12 +105,8 @@ export interface GiftedChatProps<TMessage extends IMessage> extends Partial<Mess
|
|
|
135
105
|
messageIdGenerator?(message?: TMessage): string
|
|
136
106
|
/* Callback when sending a message */
|
|
137
107
|
onSend?(messages: TMessage[]): void
|
|
138
|
-
/* Callback when loading earlier messages */
|
|
139
|
-
onLoadEarlier?(): void
|
|
140
108
|
/* Render a loading view when initializing */
|
|
141
109
|
renderLoading?(): React.ReactNode
|
|
142
|
-
/* Custom "Load earlier messages" button */
|
|
143
|
-
renderLoadEarlier?(props: LoadEarlierProps): React.ReactNode
|
|
144
110
|
/* Custom message avatar; set to null to not render any avatar for the message */
|
|
145
111
|
renderAvatar?: null | ((props: AvatarProps<TMessage>) => React.ReactNode)
|
|
146
112
|
/* Custom message bubble */
|
|
@@ -148,14 +114,12 @@ export interface GiftedChatProps<TMessage extends IMessage> extends Partial<Mess
|
|
|
148
114
|
/* Custom system message */
|
|
149
115
|
renderSystemMessage?(props: SystemMessageProps<TMessage>): React.ReactNode
|
|
150
116
|
/* Callback when a message bubble is pressed; default is to do nothing */
|
|
151
|
-
|
|
117
|
+
onPressMessage?(context: unknown, message: TMessage): void
|
|
152
118
|
/* Callback when a message bubble is long-pressed; default is to show an ActionSheet with "Copy Text" (see example using showActionSheetWithOptions()) */
|
|
153
|
-
|
|
119
|
+
onLongPressMessage?(context: unknown, message: TMessage): void
|
|
154
120
|
/* Custom Username container */
|
|
155
121
|
renderUsername?(user: User): React.ReactNode
|
|
156
122
|
/* Reverses display order of messages; default is true */
|
|
157
|
-
/* Custom message container */
|
|
158
|
-
renderMessage?(message: MessageProps<TMessage>): React.ReactElement
|
|
159
123
|
/* Custom message text */
|
|
160
124
|
renderMessageText?(messageText: MessageTextProps<TMessage>): React.ReactNode
|
|
161
125
|
/* Custom message image */
|
|
@@ -166,14 +130,8 @@ export interface GiftedChatProps<TMessage extends IMessage> extends Partial<Mess
|
|
|
166
130
|
renderMessageAudio?(props: MessageAudioProps<TMessage>): React.ReactNode
|
|
167
131
|
/* Custom view inside the bubble */
|
|
168
132
|
renderCustomView?(props: BubbleProps<TMessage>): React.ReactNode
|
|
169
|
-
/* Custom day above a message */
|
|
170
|
-
renderDay?(props: DayProps): React.ReactNode
|
|
171
133
|
/* Custom time inside a message */
|
|
172
134
|
renderTime?(props: TimeProps<TMessage>): React.ReactNode
|
|
173
|
-
/* Custom footer component on the ListView, e.g. 'User is typing...' */
|
|
174
|
-
renderFooter?(props: MessageContainerProps<TMessage>): React.ReactNode
|
|
175
|
-
/* Custom component to render in the ListView when messages are empty */
|
|
176
|
-
renderChatEmpty?(): React.ReactNode
|
|
177
135
|
/* Custom component to render below the MessageContainer (separate from the ListView) */
|
|
178
136
|
renderChatFooter?(): React.ReactNode
|
|
179
137
|
/* Custom message composer container */
|
|
@@ -191,14 +149,11 @@ export interface GiftedChatProps<TMessage extends IMessage> extends Partial<Mess
|
|
|
191
149
|
/* Callback when the input text changes */
|
|
192
150
|
onInputTextChanged?(text: string): void
|
|
193
151
|
/* Custom parse patterns for react-native-parsed-text used to linking message content (like URLs and phone numbers) */
|
|
194
|
-
|
|
195
|
-
onQuickReply?(replies: Reply[]): void
|
|
152
|
+
matchers?: MessageTextProps<TMessage>['matchers']
|
|
196
153
|
renderQuickReplies?(
|
|
197
154
|
quickReplies: QuickRepliesProps<TMessage>,
|
|
198
155
|
): React.ReactNode
|
|
199
156
|
renderQuickReplySend?(): React.ReactNode
|
|
200
|
-
/* Scroll to bottom custom component */
|
|
201
|
-
scrollToBottomComponent?(): React.ReactNode
|
|
202
157
|
shouldUpdateMessage?(
|
|
203
158
|
props: MessageProps<TMessage>,
|
|
204
159
|
nextProps: MessageProps<TMessage>,
|
package/src/InputToolbar.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useMemo } from 'react'
|
|
2
|
-
import { StyleSheet, View, StyleProp, ViewStyle } from 'react-native'
|
|
2
|
+
import { StyleSheet, View, StyleProp, ViewStyle, useColorScheme } from 'react-native'
|
|
3
3
|
|
|
4
4
|
import { Composer, ComposerProps } from './Composer'
|
|
5
5
|
import { Send, SendProps } from './Send'
|
|
@@ -38,6 +38,8 @@ export function InputToolbar<TMessage extends IMessage = IMessage> (
|
|
|
38
38
|
containerStyle,
|
|
39
39
|
} = props
|
|
40
40
|
|
|
41
|
+
const colorScheme = useColorScheme()
|
|
42
|
+
|
|
41
43
|
const actionsFragment = useMemo(() => {
|
|
42
44
|
const props = {
|
|
43
45
|
onPressActionButton,
|
|
@@ -69,18 +71,29 @@ export function InputToolbar<TMessage extends IMessage = IMessage> (
|
|
|
69
71
|
)
|
|
70
72
|
}, [renderComposer, props])
|
|
71
73
|
|
|
74
|
+
const sendFragment = useMemo(() => {
|
|
75
|
+
return renderSend?.(props) || <Send {...props} />
|
|
76
|
+
}, [renderSend, props])
|
|
77
|
+
|
|
78
|
+
const accessoryFragment = useMemo(() => {
|
|
79
|
+
if (!renderAccessory)
|
|
80
|
+
return null
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<View style={[styles.accessory, props.accessoryStyle]}>
|
|
84
|
+
{renderAccessory(props)}
|
|
85
|
+
</View>
|
|
86
|
+
)
|
|
87
|
+
}, [renderAccessory, props])
|
|
88
|
+
|
|
72
89
|
return (
|
|
73
|
-
<View style={[styles.container, containerStyle]}>
|
|
90
|
+
<View style={[styles.container, styles[`container_${colorScheme}`], containerStyle]}>
|
|
74
91
|
<View style={[styles.primary, props.primaryStyle]}>
|
|
75
92
|
{actionsFragment}
|
|
76
93
|
{composerFragment}
|
|
77
|
-
{
|
|
94
|
+
{sendFragment}
|
|
78
95
|
</View>
|
|
79
|
-
{
|
|
80
|
-
<View style={[styles.accessory, props.accessoryStyle]}>
|
|
81
|
-
{renderAccessory(props)}
|
|
82
|
-
</View>
|
|
83
|
-
)}
|
|
96
|
+
{accessoryFragment}
|
|
84
97
|
</View>
|
|
85
98
|
)
|
|
86
99
|
}
|
|
@@ -91,6 +104,10 @@ const styles = StyleSheet.create({
|
|
|
91
104
|
borderTopColor: Color.defaultColor,
|
|
92
105
|
backgroundColor: Color.white,
|
|
93
106
|
},
|
|
107
|
+
container_dark: {
|
|
108
|
+
backgroundColor: '#1a1a1a',
|
|
109
|
+
borderTopColor: '#444',
|
|
110
|
+
},
|
|
94
111
|
primary: {
|
|
95
112
|
flexDirection: 'row',
|
|
96
113
|
alignItems: 'flex-end',
|
package/src/LoadEarlier.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useMemo } from 'react'
|
|
2
2
|
import {
|
|
3
3
|
ActivityIndicator,
|
|
4
4
|
Platform,
|
|
@@ -63,6 +63,23 @@ export function LoadEarlier ({
|
|
|
63
63
|
activityIndicatorSize = 'small',
|
|
64
64
|
activityIndicatorStyle,
|
|
65
65
|
}: LoadEarlierProps): React.ReactElement {
|
|
66
|
+
const loadingContent = useMemo(() => (
|
|
67
|
+
<View>
|
|
68
|
+
<Text style={[styles.text, textStyle, { opacity: 0 }]}>
|
|
69
|
+
{label}
|
|
70
|
+
</Text>
|
|
71
|
+
<ActivityIndicator
|
|
72
|
+
color={activityIndicatorColor!}
|
|
73
|
+
size={activityIndicatorSize!}
|
|
74
|
+
style={[styles.activityIndicator, activityIndicatorStyle]}
|
|
75
|
+
/>
|
|
76
|
+
</View>
|
|
77
|
+
), [label, textStyle, activityIndicatorColor, activityIndicatorSize, activityIndicatorStyle])
|
|
78
|
+
|
|
79
|
+
const labelContent = useMemo(() => (
|
|
80
|
+
<Text style={[styles.text, textStyle]}>{label}</Text>
|
|
81
|
+
), [label, textStyle])
|
|
82
|
+
|
|
66
83
|
return (
|
|
67
84
|
<TouchableOpacity
|
|
68
85
|
style={[styles.container, containerStyle]}
|
|
@@ -71,22 +88,7 @@ export function LoadEarlier ({
|
|
|
71
88
|
accessibilityRole='button'
|
|
72
89
|
>
|
|
73
90
|
<View style={[stylesCommon.centerItems, styles.wrapper, wrapperStyle]}>
|
|
74
|
-
{isLoadingEarlier
|
|
75
|
-
? (
|
|
76
|
-
<View>
|
|
77
|
-
<Text style={[styles.text, textStyle, { opacity: 0 }]}>
|
|
78
|
-
{label}
|
|
79
|
-
</Text>
|
|
80
|
-
<ActivityIndicator
|
|
81
|
-
color={activityIndicatorColor!}
|
|
82
|
-
size={activityIndicatorSize!}
|
|
83
|
-
style={[styles.activityIndicator, activityIndicatorStyle]}
|
|
84
|
-
/>
|
|
85
|
-
</View>
|
|
86
|
-
)
|
|
87
|
-
: (
|
|
88
|
-
<Text style={[styles.text, textStyle]}>{label}</Text>
|
|
89
|
-
)}
|
|
91
|
+
{isLoadingEarlier ? loadingContent : labelContent}
|
|
90
92
|
</View>
|
|
91
93
|
</TouchableOpacity>
|
|
92
94
|
)
|
package/src/MessageAudio.tsx
CHANGED
|
@@ -1,16 +1,28 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useMemo } from 'react'
|
|
2
2
|
import Color from './Color'
|
|
3
|
-
import { View, Text } from 'react-native'
|
|
3
|
+
import { View, Text, StyleSheet } from 'react-native'
|
|
4
|
+
|
|
5
|
+
const styles = StyleSheet.create({
|
|
6
|
+
container: {
|
|
7
|
+
padding: 20,
|
|
8
|
+
},
|
|
9
|
+
text: {
|
|
10
|
+
color: Color.alizarin,
|
|
11
|
+
fontWeight: '600',
|
|
12
|
+
},
|
|
13
|
+
})
|
|
4
14
|
|
|
5
15
|
export function MessageAudio () {
|
|
6
|
-
|
|
7
|
-
<View style={
|
|
8
|
-
<Text style={
|
|
16
|
+
const content = useMemo(() => (
|
|
17
|
+
<View style={styles.container}>
|
|
18
|
+
<Text style={styles.text}>
|
|
9
19
|
{'Audio is not implemented by GiftedChat.'}
|
|
10
20
|
</Text>
|
|
11
|
-
<Text style={
|
|
21
|
+
<Text style={styles.text}>
|
|
12
22
|
{'\nYou need to provide your own implementation by using renderMessageAudio prop.'}
|
|
13
23
|
</Text>
|
|
14
24
|
</View>
|
|
15
|
-
)
|
|
25
|
+
), [])
|
|
26
|
+
|
|
27
|
+
return content
|
|
16
28
|
}
|
|
@@ -114,6 +114,19 @@ const DayAnimated = ({ scrolledY, daysPositions, listHeight, renderDay, messages
|
|
|
114
114
|
isLoadingEarlierAnim.value = isLoadingEarlier
|
|
115
115
|
}, [isLoadingEarlierAnim, isLoadingEarlier])
|
|
116
116
|
|
|
117
|
+
const dayContent = useMemo(() => {
|
|
118
|
+
if (!createdAt)
|
|
119
|
+
return null
|
|
120
|
+
|
|
121
|
+
return renderDay
|
|
122
|
+
? renderDay({ ...rest, createdAt })
|
|
123
|
+
: <Day
|
|
124
|
+
{...rest}
|
|
125
|
+
containerStyle={[styles.dayAnimatedDayContainerStyle, rest.containerStyle]}
|
|
126
|
+
createdAt={createdAt}
|
|
127
|
+
/>
|
|
128
|
+
}, [createdAt, renderDay, rest])
|
|
129
|
+
|
|
117
130
|
if (!createdAt)
|
|
118
131
|
return null
|
|
119
132
|
|
|
@@ -126,15 +139,7 @@ const DayAnimated = ({ scrolledY, daysPositions, listHeight, renderDay, messages
|
|
|
126
139
|
style={contentStyle}
|
|
127
140
|
pointerEvents='none'
|
|
128
141
|
>
|
|
129
|
-
{
|
|
130
|
-
renderDay
|
|
131
|
-
? renderDay({ ...rest, createdAt })
|
|
132
|
-
: <Day
|
|
133
|
-
{...rest}
|
|
134
|
-
containerStyle={[styles.dayAnimatedDayContainerStyle, rest.containerStyle]}
|
|
135
|
-
createdAt={createdAt}
|
|
136
|
-
/>
|
|
137
|
-
}
|
|
142
|
+
{dayContent}
|
|
138
143
|
</Animated.View>
|
|
139
144
|
</Animated.View>
|
|
140
145
|
)
|
|
@@ -33,7 +33,13 @@ export const useRelativeScrolledPositionToBottomOfDay = (
|
|
|
33
33
|
const absoluteScrolledPositionToBottomOfDay = useAbsoluteScrolledPositionToBottomOfDay(listHeight, scrolledY, containerHeight, dayBottomMargin, dayTopOffset)
|
|
34
34
|
|
|
35
35
|
// sorted array of days positions by y
|
|
36
|
-
const daysPositionsArray = useDerivedValue(() =>
|
|
36
|
+
const daysPositionsArray = useDerivedValue(() => {
|
|
37
|
+
return Object.values(daysPositions.value).sort((a, b) => {
|
|
38
|
+
'worklet'
|
|
39
|
+
|
|
40
|
+
return a.y - b.y
|
|
41
|
+
})
|
|
42
|
+
})
|
|
37
43
|
|
|
38
44
|
// find current day position by scrolled position
|
|
39
45
|
const currentDayPosition = useDerivedValue(() => {
|