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/README.md
CHANGED
|
@@ -78,6 +78,10 @@
|
|
|
78
78
|
<a href="https://bit.ly/ethorachat" target="_blank">Check out our GitHub</a>
|
|
79
79
|
</p>
|
|
80
80
|
</p>
|
|
81
|
+
<br>
|
|
82
|
+
<p align="center">
|
|
83
|
+
<a href="https://amzn.to/3ZmTyb2" target="_blank">React Key Concepts: Consolidate your knowledge of React’s core features (2nd ed. Edition)</a>
|
|
84
|
+
</p>
|
|
81
85
|
|
|
82
86
|
## Features
|
|
83
87
|
|
|
@@ -351,8 +355,9 @@ interface QuickReplies {
|
|
|
351
355
|
- **`messages`** _(Array)_ - Messages to display
|
|
352
356
|
- **`isTyping`** _(Bool)_ - Typing Indicator state; default `false`. If you use`renderFooter` it will override this.
|
|
353
357
|
- **`isKeyboardInternallyHandled`** _(Bool)_ - 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`
|
|
358
|
+
- **`disableKeyboardController`** _(Bool)_ - Completely disable react-native-keyboard-controller. Useful when using react-native-navigation or other conflicting keyboard libraries; default is `false`
|
|
354
359
|
- **`text`** _(String)_ - Input text; default is `undefined`, but if specified, it will override GiftedChat's internal state (e.g. for redux; [see notes below](#notes-for-redux))
|
|
355
|
-
- **`
|
|
360
|
+
- **`onInputTextChanged`** _(Function)_ - Callback when the input text changes
|
|
356
361
|
- **`messageIdGenerator`** _(Function)_ - Generate an id for new messages. Defaults to UUID v4, generated by [uuid](https://github.com/kelektiv/node-uuid)
|
|
357
362
|
- **`user`** _(Object)_ - User sending the messages: `{ _id, name, avatar }`
|
|
358
363
|
- **`onSend`** _(Function)_ - Callback when sending a message
|
|
@@ -360,7 +365,7 @@ interface QuickReplies {
|
|
|
360
365
|
- **`locale`** _(String)_ - Locale to localize the dates. You need first to import the locale you need (ie. `require('dayjs/locale/de')` or `import 'dayjs/locale/fr'`)
|
|
361
366
|
- **`timeFormat`** _(String)_ - Format to use for rendering times; default is `'LT'` (see [Day.js Format](https://day.js.org/docs/en/display/format))
|
|
362
367
|
- **`dateFormat`** _(String)_ - Format to use for rendering dates; default is `'D MMMM'` (see [Day.js Format](https://day.js.org/docs/en/display/format))
|
|
363
|
-
- **`dateFormatCalendar`** _(
|
|
368
|
+
- **`dateFormatCalendar`** _(Object)_ - Format to use for rendering relative times; default is `{ sameDay: '[Today]' }` (see [Day.js Calendar](https://day.js.org/docs/en/plugin/calendar))
|
|
364
369
|
- **`loadEarlier`** _(Bool)_ - Enables the "load earlier messages" button, required for `infiniteScroll`
|
|
365
370
|
- **`onLoadEarlier`** _(Function)_ - Callback when loading earlier messages
|
|
366
371
|
- **`isLoadingEarlier`** _(Bool)_ - Display an `ActivityIndicator` when loading earlier messages
|
|
@@ -375,8 +380,8 @@ interface QuickReplies {
|
|
|
375
380
|
- **`renderBubble`** _(Function)_ - Custom message bubble
|
|
376
381
|
- **`renderTicks`** _(Function(`message`))_ - Custom ticks indicator to display message status
|
|
377
382
|
- **`renderSystemMessage`** _(Function)_ - Custom system message
|
|
378
|
-
- **`
|
|
379
|
-
- **`
|
|
383
|
+
- **`onPressMessage`** _(Function(`context`, `message`))_ - Callback when a message bubble is pressed
|
|
384
|
+
- **`onLongPressMessage`** _(Function(`context`, `message`))_ - Callback when a message bubble is long-pressed (see [example using `showActionSheetWithOptions()`](https://github.com/FaridSafi/react-native-gifted-chat/blob/master@%7B2017-09-25%7D/src/Bubble.js#L96-L119))
|
|
380
385
|
- **`inverted`** _(Bool)_ - Reverses display order of `messages`; default is `true`
|
|
381
386
|
- **`renderUsernameOnMessage`** _(Bool)_ - Indicate whether to show the user's username inside the message bubble; default is `false`
|
|
382
387
|
- **`renderUsername`** _(Function)_ - Custom Username container
|
|
@@ -384,7 +389,7 @@ interface QuickReplies {
|
|
|
384
389
|
- **`renderMessageText`** _(Function)_ - Custom message text
|
|
385
390
|
- **`renderMessageImage`** _(Function)_ - Custom message image
|
|
386
391
|
- **`renderMessageVideo`** _(Function)_ - Custom message video
|
|
387
|
-
- **`imageProps`** _(Object)_ - Extra props to be passed to the [`<Image>`](https://
|
|
392
|
+
- **`imageProps`** _(Object)_ - Extra props to be passed to the [`<Image>`](https://reactnative.dev/docs/image.html) component created by the default `renderMessageImage`
|
|
388
393
|
- **`videoProps`** _(Object)_ - Extra props to be passed to the video component created by the required `renderMessageVideo`
|
|
389
394
|
- **`lightboxProps`** _(Object)_ - Extra props to be passed to the `MessageImage`'s [Lightbox](https://github.com/oblador/react-native-lightbox)
|
|
390
395
|
- **`isCustomViewBottom`** _(Bool)_ - Determine whether renderCustomView is displayed before or after the text, image and video views; default is `false`
|
|
@@ -403,20 +408,15 @@ interface QuickReplies {
|
|
|
403
408
|
- **`bottomOffset`** _(Integer)_ - Distance of the chat from the bottom of the screen (e.g. useful if you display a tab bar)
|
|
404
409
|
- **`focusOnInputWhenOpeningKeyboard`** _(Bool)_ - Focus on <TextInput> automatically when opening the keyboard; default `true`
|
|
405
410
|
- **`minInputToolbarHeight`** _(Integer)_ - Minimum height of the input toolbar; default is `44`
|
|
406
|
-
- **`
|
|
407
|
-
- **`textInputProps`** _(Object)_ -
|
|
408
|
-
- **`
|
|
409
|
-
- **`multiline`** _(Bool)_ - Indicates whether to allow the [`<TextInput>`](https://facebook.github.io/react-native/docs/textinput.html) to be multiple lines or not; default `true`.
|
|
410
|
-
- **`keyboardShouldPersistTaps`** _(Enum)_ - Determines whether the keyboard should stay visible after a tap; see [`<ScrollView>`](https://facebook.github.io/react-native/docs/scrollview.html) docs
|
|
411
|
-
- **`onInputTextChanged`** _(Function)_ - Callback when the input text changes
|
|
412
|
-
- **`maxInputLength`** _(Integer)_ - Max message composer TextInput length
|
|
413
|
-
- **`parsePatterns`** _(Function)_ - Custom parse patterns for [react-native-parsed-text](https://github.com/taskrabbit/react-native-parsed-text) used to linking message content (like URLs and phone numbers), e.g.:
|
|
411
|
+
- **`listProps`** _(Object)_ - Extra props to be passed to the messages [`<FlatList>`](https://reactnative.dev/docs/flatlist.html); some props can't be overridden, see the code in `MessageContainer.render()` for details
|
|
412
|
+
- **`textInputProps`** _(Object)_ - props to be passed to the [`<TextInput>`](https://reactnative.dev/docs/textinput.html).
|
|
413
|
+
- **`matchers`** _(Array)_ - Custom matchers for [react-native-autolink](https://github.com/joshswan/react-native-autolink) used to linking message content (like URLs and phone numbers), e.g.:
|
|
414
414
|
|
|
415
415
|
```js
|
|
416
416
|
<GiftedChat
|
|
417
|
-
|
|
418
|
-
{ type: 'phone', style: linkStyle, onPress:
|
|
419
|
-
{ pattern: /#(\w+)/, style:
|
|
417
|
+
matchers={[
|
|
418
|
+
{ type: 'phone', style: linkStyle, onPress: onPressPhoneNumber },
|
|
419
|
+
{ pattern: /#(\w+)/, style: [linkStyle, styles.hashtag], onPress: onPressHashtag },
|
|
420
420
|
]}
|
|
421
421
|
/>
|
|
422
422
|
```
|
|
@@ -436,6 +436,7 @@ interface QuickReplies {
|
|
|
436
436
|
* **`renderQuickReplySend`** _(Function)_ - Custom quick reply **send** view
|
|
437
437
|
* **`shouldUpdateMessage`** _(Function)_ - Lets the message component know when to update outside of normal cases.
|
|
438
438
|
* **`infiniteScroll`** _(Bool)_ - infinite scroll up when reach the top of messages container, automatically call onLoadEarlier function if exist (not yet supported for the web). You need to add `loadEarlier` prop too.
|
|
439
|
+
* **`typingIndicatorStyle`** _(StyleProp<ViewStyle>)_ - Custom style for the TypingIndicator component.
|
|
439
440
|
|
|
440
441
|
## Notes for [Redux](https://github.com/reactjs/redux)
|
|
441
442
|
|
|
@@ -469,7 +470,7 @@ If you are using Create React Native App / Expo, no Android specific installatio
|
|
|
469
470
|
|
|
470
471
|
- For **Expo**, there are at least 2 solutions to fix it:
|
|
471
472
|
|
|
472
|
-
- Append [`KeyboardAvoidingView`](https://
|
|
473
|
+
- Append [`KeyboardAvoidingView`](https://reactnative.dev/docs/keyboardavoidingview) after GiftedChat. This should only be done for Android, as `KeyboardAvoidingView` may conflict with the iOS keyboard avoidance already built into GiftedChat, e.g.:
|
|
473
474
|
|
|
474
475
|
```
|
|
475
476
|
<View style={{ flex: 1 }}>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-gifted-chat",
|
|
3
|
-
"version": "2.8.1",
|
|
3
|
+
"version": "2.8.2-alpha.1",
|
|
4
4
|
"description": "The most complete chat UI for React Native",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"android",
|
|
@@ -23,17 +23,15 @@
|
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"author": "Farid Safi",
|
|
25
25
|
"type": "module",
|
|
26
|
-
"main": "
|
|
27
|
-
"types": "
|
|
26
|
+
"main": "src/index.ts",
|
|
27
|
+
"types": "src/index.ts",
|
|
28
28
|
"files": [
|
|
29
|
-
"src"
|
|
30
|
-
"lib"
|
|
29
|
+
"src"
|
|
31
30
|
],
|
|
32
31
|
"scripts": {
|
|
33
|
-
"build": "rm -rf lib/ && yarn tsc",
|
|
34
32
|
"lint": "yarn eslint src",
|
|
35
33
|
"lint:fix": "yarn eslint --cache --fix",
|
|
36
|
-
"prepublishOnly": "yarn lint && yarn
|
|
34
|
+
"prepublishOnly": "yarn lint && yarn test",
|
|
37
35
|
"start": "cd example && expo start",
|
|
38
36
|
"start:web": "cd example && expo start -w --dev",
|
|
39
37
|
"test": "TZ=Europe/Paris jest --no-watchman",
|
|
@@ -46,64 +44,72 @@
|
|
|
46
44
|
},
|
|
47
45
|
"lint-staged": {
|
|
48
46
|
"src/*.{json,js,jsx,ts,tsx}": [
|
|
49
|
-
"yarn lint:fix"
|
|
50
|
-
"bash -c 'yarn tsc:write'"
|
|
47
|
+
"yarn lint:fix"
|
|
51
48
|
]
|
|
52
49
|
},
|
|
53
50
|
"dependencies": {
|
|
54
51
|
"@expo/react-native-action-sheet": "^4.1.1",
|
|
55
52
|
"@types/lodash.isequal": "^4.5.8",
|
|
56
|
-
"dayjs": "^1.11.
|
|
53
|
+
"dayjs": "^1.11.19",
|
|
57
54
|
"lodash.isequal": "^4.5.0",
|
|
55
|
+
"react-native-autolink": "^4.2.0",
|
|
58
56
|
"react-native-communications": "^2.2.1",
|
|
59
|
-
"react-native-
|
|
60
|
-
"react-native-lightbox-v2": "^0.9.2",
|
|
61
|
-
"react-native-parsed-text": "^0.0.22"
|
|
57
|
+
"react-native-lightbox-v2": "^0.9.2"
|
|
62
58
|
},
|
|
63
59
|
"devDependencies": {
|
|
64
|
-
"@babel/core": "^7.
|
|
65
|
-
"@babel/plugin-transform-react-jsx": "^7.
|
|
66
|
-
"@babel/plugin-transform-unicode-property-regex": "^7.
|
|
67
|
-
"@babel/preset-env": "^7.
|
|
68
|
-
"@react-native/
|
|
60
|
+
"@babel/core": "^7.28.5",
|
|
61
|
+
"@babel/plugin-transform-react-jsx": "^7.27.1",
|
|
62
|
+
"@babel/plugin-transform-unicode-property-regex": "^7.27.1",
|
|
63
|
+
"@babel/preset-env": "^7.28.5",
|
|
64
|
+
"@react-native-community/cli": "20.0.0",
|
|
65
|
+
"@react-native-community/cli-platform-android": "20.0.0",
|
|
66
|
+
"@react-native-community/cli-platform-ios": "20.0.0",
|
|
67
|
+
"@react-native/babel-preset": "0.81.5",
|
|
68
|
+
"@react-native/eslint-config": "0.81.5",
|
|
69
|
+
"@react-native/metro-config": "0.81.5",
|
|
70
|
+
"@react-native/typescript-config": "0.81.5",
|
|
69
71
|
"@stylistic/eslint-plugin": "^3.1.0",
|
|
70
|
-
"@
|
|
71
|
-
"@
|
|
72
|
-
"@
|
|
72
|
+
"@testing-library/dom": "^10.4.1",
|
|
73
|
+
"@testing-library/react": "^16.3.0",
|
|
74
|
+
"@testing-library/react-native": "^13.3.3",
|
|
75
|
+
"@types/jest": "^29.5.13",
|
|
76
|
+
"@types/react": "^19.2.5",
|
|
77
|
+
"@types/react-dom": "^19.2.3",
|
|
73
78
|
"@types/react-native": "^0.72.8",
|
|
74
|
-
"@
|
|
75
|
-
"@typescript-eslint/
|
|
79
|
+
"@types/react-test-renderer": "^19.1.0",
|
|
80
|
+
"@typescript-eslint/eslint-plugin": "^8.46.4",
|
|
81
|
+
"@typescript-eslint/parser": "^8.46.4",
|
|
76
82
|
"babel-jest": "^29.7.0",
|
|
77
83
|
"eslint": "^8.57.0",
|
|
78
84
|
"eslint-config-standard": "^17.1.0",
|
|
79
85
|
"eslint-config-standard-jsx": "^11.0.0",
|
|
80
|
-
"eslint-plugin-import": "^2.
|
|
86
|
+
"eslint-plugin-import": "^2.32.0",
|
|
81
87
|
"eslint-plugin-jest": "^28.11.0",
|
|
82
88
|
"eslint-plugin-json": "^4.0.1",
|
|
83
|
-
"eslint-plugin-n": "^17.
|
|
89
|
+
"eslint-plugin-n": "^17.23.1",
|
|
84
90
|
"eslint-plugin-node": "^11.1.0",
|
|
85
91
|
"eslint-plugin-promise": "^7.2.1",
|
|
86
|
-
"eslint-plugin-react": "^7.37.
|
|
92
|
+
"eslint-plugin-react": "^7.37.5",
|
|
87
93
|
"husky": "^9.1.7",
|
|
88
94
|
"jest": "^29.7.0",
|
|
89
95
|
"json": "^11.0.0",
|
|
90
96
|
"lint-staged": "^15.5.0",
|
|
91
|
-
"react": "
|
|
92
|
-
"react-dom": "
|
|
93
|
-
"react-native": "
|
|
94
|
-
"react-native-keyboard-controller": "^1.
|
|
95
|
-
"react-native-reanimated": "^3.
|
|
96
|
-
"react-test-renderer": "
|
|
97
|
-
"typescript": "^5.
|
|
97
|
+
"react": "19.1.0",
|
|
98
|
+
"react-dom": "19.1.0",
|
|
99
|
+
"react-native": "0.81.5",
|
|
100
|
+
"react-native-keyboard-controller": "^1.19.5",
|
|
101
|
+
"react-native-reanimated": "^3.19.4",
|
|
102
|
+
"react-test-renderer": "19.1.0",
|
|
103
|
+
"typescript": "^5.9.3"
|
|
98
104
|
},
|
|
99
105
|
"peerDependencies": {
|
|
100
106
|
"react": ">=18.0.0",
|
|
101
107
|
"react-native": "*",
|
|
102
108
|
"react-native-keyboard-controller": ">=1.0.0",
|
|
103
|
-
"react-native-reanimated": ">=3.0.0"
|
|
109
|
+
"react-native-reanimated": ">=3.0.0 || ^4.0.0"
|
|
104
110
|
},
|
|
105
111
|
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e",
|
|
106
112
|
"engines": {
|
|
107
|
-
"node": ">=
|
|
113
|
+
"node": ">=20"
|
|
108
114
|
}
|
|
109
115
|
}
|
package/src/Bubble/index.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import React, { useCallback } from 'react'
|
|
1
|
+
import React, { JSX, useCallback } from 'react'
|
|
2
2
|
import {
|
|
3
3
|
Text,
|
|
4
|
-
|
|
4
|
+
Pressable,
|
|
5
5
|
View,
|
|
6
6
|
} from 'react-native'
|
|
7
7
|
|
|
@@ -22,7 +22,7 @@ import styles from './styles'
|
|
|
22
22
|
|
|
23
23
|
export * from './types'
|
|
24
24
|
|
|
25
|
-
const Bubble
|
|
25
|
+
const Bubble = <TMessage extends IMessage = IMessage>(props: BubbleProps<TMessage>): JSX.Element => {
|
|
26
26
|
const {
|
|
27
27
|
currentMessage,
|
|
28
28
|
nextMessage,
|
|
@@ -38,46 +38,22 @@ const Bubble: React.FC<BubbleProps<IMessage>> = (props: BubbleProps<IMessage>) =
|
|
|
38
38
|
containerStyle,
|
|
39
39
|
wrapperStyle,
|
|
40
40
|
bottomContainerStyle,
|
|
41
|
+
onPressMessage: onPressMessageProp,
|
|
42
|
+
onLongPressMessage: onLongPressMessageProp,
|
|
41
43
|
} = props
|
|
42
44
|
|
|
43
45
|
const context = useChatContext()
|
|
44
46
|
|
|
45
47
|
const onPress = useCallback(() => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}, [context, props, currentMessage])
|
|
48
|
+
onPressMessageProp?.(context, currentMessage)
|
|
49
|
+
}, [onPressMessageProp, context, currentMessage])
|
|
49
50
|
|
|
50
51
|
const onLongPress = useCallback(() => {
|
|
51
|
-
|
|
52
|
-
onLongPress,
|
|
53
|
-
optionTitles,
|
|
54
|
-
} = props
|
|
55
|
-
|
|
56
|
-
if (onLongPress) {
|
|
57
|
-
onLongPress(context, currentMessage)
|
|
58
|
-
return
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (!optionTitles?.length)
|
|
62
|
-
return
|
|
63
|
-
|
|
64
|
-
const options = optionTitles
|
|
65
|
-
const cancelButtonIndex = options.length - 1
|
|
66
|
-
|
|
67
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
68
|
-
;(context as any).actionSheet().showActionSheetWithOptions(
|
|
69
|
-
{
|
|
70
|
-
options,
|
|
71
|
-
cancelButtonIndex,
|
|
72
|
-
},
|
|
73
|
-
(buttonIndex: number) => {
|
|
74
|
-
console.log('onLongPress', { buttonIndex })
|
|
75
|
-
}
|
|
76
|
-
)
|
|
52
|
+
onLongPressMessageProp?.(context, currentMessage)
|
|
77
53
|
}, [
|
|
78
54
|
currentMessage,
|
|
79
55
|
context,
|
|
80
|
-
|
|
56
|
+
onLongPressMessageProp,
|
|
81
57
|
])
|
|
82
58
|
|
|
83
59
|
const styledBubbleToNext = useCallback(() => {
|
|
@@ -111,7 +87,7 @@ const Bubble: React.FC<BubbleProps<IMessage>> = (props: BubbleProps<IMessage>) =
|
|
|
111
87
|
)
|
|
112
88
|
return [
|
|
113
89
|
styles[position].containerToPrevious,
|
|
114
|
-
containerToPreviousStyle
|
|
90
|
+
containerToPreviousStyle?.[position],
|
|
115
91
|
]
|
|
116
92
|
|
|
117
93
|
return null
|
|
@@ -166,7 +142,6 @@ const Bubble: React.FC<BubbleProps<IMessage>> = (props: BubbleProps<IMessage>) =
|
|
|
166
142
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
167
143
|
containerStyle,
|
|
168
144
|
wrapperStyle,
|
|
169
|
-
optionTitles,
|
|
170
145
|
/* eslint-enable @typescript-eslint/no-unused-vars */
|
|
171
146
|
...messageTextProps
|
|
172
147
|
} = props
|
|
@@ -176,6 +151,7 @@ const Bubble: React.FC<BubbleProps<IMessage>> = (props: BubbleProps<IMessage>) =
|
|
|
176
151
|
|
|
177
152
|
return <MessageText {...messageTextProps} />
|
|
178
153
|
}
|
|
154
|
+
|
|
179
155
|
return null
|
|
180
156
|
}, [props, currentMessage])
|
|
181
157
|
|
|
@@ -194,6 +170,7 @@ const Bubble: React.FC<BubbleProps<IMessage>> = (props: BubbleProps<IMessage>) =
|
|
|
194
170
|
|
|
195
171
|
return <MessageImage {...messageImageProps} />
|
|
196
172
|
}
|
|
173
|
+
|
|
197
174
|
return null
|
|
198
175
|
}, [props, currentMessage])
|
|
199
176
|
|
|
@@ -374,10 +351,9 @@ const Bubble: React.FC<BubbleProps<IMessage>> = (props: BubbleProps<IMessage>) =
|
|
|
374
351
|
wrapperStyle && wrapperStyle[position],
|
|
375
352
|
]}
|
|
376
353
|
>
|
|
377
|
-
<
|
|
354
|
+
<Pressable
|
|
378
355
|
onPress={onPress}
|
|
379
356
|
onLongPress={onLongPress}
|
|
380
|
-
accessibilityRole='text'
|
|
381
357
|
{...props.touchableProps}
|
|
382
358
|
>
|
|
383
359
|
<View>
|
|
@@ -385,7 +361,7 @@ const Bubble: React.FC<BubbleProps<IMessage>> = (props: BubbleProps<IMessage>) =
|
|
|
385
361
|
<View
|
|
386
362
|
style={[
|
|
387
363
|
styles[position].bottom,
|
|
388
|
-
bottomContainerStyle
|
|
364
|
+
bottomContainerStyle?.[position],
|
|
389
365
|
]}
|
|
390
366
|
>
|
|
391
367
|
{renderUsername()}
|
|
@@ -393,7 +369,7 @@ const Bubble: React.FC<BubbleProps<IMessage>> = (props: BubbleProps<IMessage>) =
|
|
|
393
369
|
{renderTicks()}
|
|
394
370
|
</View>
|
|
395
371
|
</View>
|
|
396
|
-
</
|
|
372
|
+
</Pressable>
|
|
397
373
|
</View>
|
|
398
374
|
{renderQuickReplies()}
|
|
399
375
|
</View>
|
package/src/Bubble/types.ts
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
TextStyle,
|
|
6
6
|
} from 'react-native'
|
|
7
7
|
import { QuickRepliesProps } from '../QuickReplies'
|
|
8
|
-
import { MessageTextProps } from '../MessageText'
|
|
8
|
+
import { MessageTextProps, MessageOption } from '../MessageText'
|
|
9
9
|
import { MessageImageProps } from '../MessageImage'
|
|
10
10
|
import { TimeProps } from '../Time'
|
|
11
11
|
import {
|
|
@@ -39,7 +39,7 @@ export type RenderMessageAudioProps<TMessage extends IMessage> = Omit<
|
|
|
39
39
|
|
|
40
40
|
export type RenderMessageTextProps<TMessage extends IMessage> = Omit<
|
|
41
41
|
BubbleProps<TMessage>,
|
|
42
|
-
'containerStyle' | 'wrapperStyle'
|
|
42
|
+
'containerStyle' | 'wrapperStyle' | 'options'
|
|
43
43
|
> &
|
|
44
44
|
MessageTextProps<TMessage>
|
|
45
45
|
/* eslint-enable no-use-before-define */
|
|
@@ -54,7 +54,7 @@ export interface BubbleProps<TMessage extends IMessage> {
|
|
|
54
54
|
currentMessage: TMessage
|
|
55
55
|
nextMessage?: TMessage
|
|
56
56
|
previousMessage?: TMessage
|
|
57
|
-
|
|
57
|
+
options?: MessageOption[]
|
|
58
58
|
containerStyle?: LeftRightStyle<ViewStyle>
|
|
59
59
|
wrapperStyle?: LeftRightStyle<ViewStyle>
|
|
60
60
|
textStyle?: LeftRightStyle<TextStyle>
|
|
@@ -66,8 +66,8 @@ export interface BubbleProps<TMessage extends IMessage> {
|
|
|
66
66
|
quickReplyStyle?: StyleProp<ViewStyle>
|
|
67
67
|
quickReplyTextStyle?: StyleProp<TextStyle>
|
|
68
68
|
quickReplyContainerStyle?: StyleProp<ViewStyle>
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
onPressMessage?(context?: unknown, message?: unknown): void
|
|
70
|
+
onLongPressMessage?(context?: unknown, message?: unknown): void
|
|
71
71
|
onQuickReply?(replies: Reply[]): void
|
|
72
72
|
renderMessageImage?(
|
|
73
73
|
props: RenderMessageImageProps<TMessage>,
|
package/src/Composer.tsx
CHANGED
|
@@ -6,41 +6,30 @@ import {
|
|
|
6
6
|
TextInputProps,
|
|
7
7
|
NativeSyntheticEvent,
|
|
8
8
|
TextInputContentSizeChangeEventData,
|
|
9
|
+
useColorScheme,
|
|
9
10
|
} from 'react-native'
|
|
10
|
-
import { MIN_COMPOSER_HEIGHT
|
|
11
|
+
import { MIN_COMPOSER_HEIGHT } from './Constant'
|
|
11
12
|
import Color from './Color'
|
|
12
13
|
import stylesCommon from './styles'
|
|
13
14
|
|
|
14
15
|
export interface ComposerProps {
|
|
15
16
|
composerHeight?: number
|
|
16
17
|
text?: string
|
|
17
|
-
placeholder?: string
|
|
18
|
-
placeholderTextColor?: string
|
|
19
18
|
textInputProps?: Partial<TextInputProps>
|
|
20
|
-
textInputStyle?: TextInputProps['style']
|
|
21
|
-
textInputAutoFocus?: boolean
|
|
22
|
-
keyboardAppearance?: TextInputProps['keyboardAppearance']
|
|
23
|
-
multiline?: boolean
|
|
24
|
-
disableComposer?: boolean
|
|
25
19
|
onTextChanged?(text: string): void
|
|
26
20
|
onInputSizeChanged?(layout: { width: number, height: number }): void
|
|
27
21
|
}
|
|
28
22
|
|
|
29
23
|
export function Composer ({
|
|
30
24
|
composerHeight = MIN_COMPOSER_HEIGHT,
|
|
31
|
-
disableComposer = false,
|
|
32
|
-
keyboardAppearance = 'default',
|
|
33
|
-
multiline = true,
|
|
34
25
|
onInputSizeChanged,
|
|
35
26
|
onTextChanged,
|
|
36
|
-
placeholder = DEFAULT_PLACEHOLDER,
|
|
37
|
-
placeholderTextColor = Color.defaultColor,
|
|
38
27
|
text = '',
|
|
39
|
-
textInputAutoFocus = false,
|
|
40
28
|
textInputProps,
|
|
41
|
-
textInputStyle,
|
|
42
29
|
}: ComposerProps): React.ReactElement {
|
|
43
30
|
const dimensionsRef = useRef<{ width: number, height: number }>(null)
|
|
31
|
+
const colorScheme = useColorScheme()
|
|
32
|
+
const isDark = colorScheme === 'dark'
|
|
44
33
|
|
|
45
34
|
const determineInputSizeChange = useCallback(
|
|
46
35
|
(dimensions: { width: number, height: number }) => {
|
|
@@ -69,21 +58,28 @@ export function Composer ({
|
|
|
69
58
|
[determineInputSizeChange]
|
|
70
59
|
)
|
|
71
60
|
|
|
61
|
+
const placeholder = textInputProps?.placeholder ?? 'Type a message...'
|
|
62
|
+
|
|
72
63
|
return (
|
|
73
64
|
<TextInput
|
|
74
65
|
testID={placeholder}
|
|
75
66
|
accessible
|
|
76
67
|
accessibilityLabel={placeholder}
|
|
77
|
-
|
|
78
|
-
placeholderTextColor={placeholderTextColor}
|
|
79
|
-
multiline={multiline}
|
|
80
|
-
editable={!disableComposer}
|
|
68
|
+
placeholderTextColor={textInputProps?.placeholderTextColor ?? (isDark ? '#888' : Color.defaultColor)}
|
|
81
69
|
onContentSizeChange={handleContentSizeChange}
|
|
82
70
|
onChangeText={onTextChanged}
|
|
71
|
+
value={text}
|
|
72
|
+
enablesReturnKeyAutomatically
|
|
73
|
+
underlineColorAndroid='transparent'
|
|
74
|
+
keyboardAppearance={isDark ? 'dark' : 'default'}
|
|
75
|
+
multiline
|
|
76
|
+
placeholder={placeholder}
|
|
77
|
+
{...textInputProps}
|
|
83
78
|
style={[
|
|
84
79
|
stylesCommon.fill,
|
|
85
80
|
styles.textInput,
|
|
86
|
-
|
|
81
|
+
styles[`textInput_${colorScheme}`],
|
|
82
|
+
textInputProps?.style,
|
|
87
83
|
{
|
|
88
84
|
height: composerHeight,
|
|
89
85
|
...Platform.select({
|
|
@@ -95,12 +91,6 @@ export function Composer ({
|
|
|
95
91
|
}),
|
|
96
92
|
},
|
|
97
93
|
]}
|
|
98
|
-
autoFocus={textInputAutoFocus}
|
|
99
|
-
value={text}
|
|
100
|
-
enablesReturnKeyAutomatically
|
|
101
|
-
underlineColorAndroid='transparent'
|
|
102
|
-
keyboardAppearance={keyboardAppearance}
|
|
103
|
-
{...textInputProps}
|
|
104
94
|
/>
|
|
105
95
|
)
|
|
106
96
|
}
|
|
@@ -127,4 +117,7 @@ const styles = StyleSheet.create({
|
|
|
127
117
|
web: 4,
|
|
128
118
|
}),
|
|
129
119
|
},
|
|
120
|
+
textInput_dark: {
|
|
121
|
+
color: '#fff',
|
|
122
|
+
},
|
|
130
123
|
})
|
package/src/Constant.ts
CHANGED
package/src/GiftedAvatar.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback,
|
|
1
|
+
import React, { useCallback, useMemo } from 'react'
|
|
2
2
|
import {
|
|
3
3
|
Image,
|
|
4
4
|
Text,
|
|
@@ -51,9 +51,6 @@ export interface GiftedAvatarProps {
|
|
|
51
51
|
export function GiftedAvatar (
|
|
52
52
|
props: GiftedAvatarProps
|
|
53
53
|
) {
|
|
54
|
-
const [avatarName, setAvatarName] = useState<string | undefined>(undefined)
|
|
55
|
-
const [backgroundColor, setBackgroundColor] = useState<string | undefined>(undefined)
|
|
56
|
-
|
|
57
54
|
const {
|
|
58
55
|
user,
|
|
59
56
|
avatarStyle,
|
|
@@ -61,23 +58,23 @@ export function GiftedAvatar (
|
|
|
61
58
|
onPress,
|
|
62
59
|
} = props
|
|
63
60
|
|
|
64
|
-
const
|
|
65
|
-
if (backgroundColor)
|
|
66
|
-
return
|
|
67
|
-
|
|
61
|
+
const avatarName = useMemo(() => {
|
|
68
62
|
const userName = user?.name || ''
|
|
69
63
|
const name = userName.toUpperCase().split(' ')
|
|
70
64
|
|
|
71
65
|
if (name.length === 1)
|
|
72
|
-
|
|
66
|
+
return `${name[0].charAt(0)}`
|
|
73
67
|
else if (name.length > 1)
|
|
74
|
-
|
|
68
|
+
return `${name[0].charAt(0)}${name[1].charAt(0)}`
|
|
75
69
|
else
|
|
76
|
-
|
|
70
|
+
return ''
|
|
71
|
+
}, [user?.name])
|
|
77
72
|
|
|
73
|
+
const backgroundColor = useMemo(() => {
|
|
78
74
|
let sumChars = 0
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
if (user?.name)
|
|
76
|
+
for (let i = 0; i < user.name.length; i += 1)
|
|
77
|
+
sumChars += user.name.charCodeAt(i)
|
|
81
78
|
|
|
82
79
|
// inspired by https://github.com/wbinnssmith/react-user-avatar
|
|
83
80
|
// colors from https://flatuicolors.com/
|
|
@@ -91,8 +88,8 @@ export function GiftedAvatar (
|
|
|
91
88
|
midnightBlue,
|
|
92
89
|
]
|
|
93
90
|
|
|
94
|
-
|
|
95
|
-
}, [user?.name
|
|
91
|
+
return colors[sumChars % colors.length]
|
|
92
|
+
}, [user?.name])
|
|
96
93
|
|
|
97
94
|
const renderAvatar = useCallback(() => {
|
|
98
95
|
switch (typeof user?.avatar) {
|
|
@@ -125,17 +122,16 @@ export function GiftedAvatar (
|
|
|
125
122
|
)
|
|
126
123
|
}, [textStyle, avatarName])
|
|
127
124
|
|
|
128
|
-
const handleOnPress = () => {
|
|
125
|
+
const handleOnPress = useCallback(() => {
|
|
129
126
|
const {
|
|
130
127
|
onPress,
|
|
131
128
|
...rest
|
|
132
129
|
} = props
|
|
133
130
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
131
|
+
onPress?.(rest)
|
|
132
|
+
}, [props])
|
|
137
133
|
|
|
138
|
-
const handleOnLongPress = () => {
|
|
134
|
+
const handleOnLongPress = useCallback(() => {
|
|
139
135
|
const {
|
|
140
136
|
onLongPress,
|
|
141
137
|
...rest
|
|
@@ -143,25 +139,22 @@ export function GiftedAvatar (
|
|
|
143
139
|
|
|
144
140
|
if (onLongPress)
|
|
145
141
|
onLongPress(rest)
|
|
146
|
-
}
|
|
142
|
+
}, [props])
|
|
147
143
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
144
|
+
const placeholderView = useMemo(() => (
|
|
145
|
+
<View
|
|
146
|
+
style={[
|
|
147
|
+
stylesCommon.centerItems,
|
|
148
|
+
styles.avatarStyle,
|
|
149
|
+
styles.avatarTransparent,
|
|
150
|
+
avatarStyle,
|
|
151
|
+
]}
|
|
152
|
+
accessibilityRole='image'
|
|
153
|
+
/>
|
|
154
|
+
), [avatarStyle])
|
|
151
155
|
|
|
152
156
|
if (!user || (!user.name && !user.avatar))
|
|
153
|
-
|
|
154
|
-
return (
|
|
155
|
-
<View
|
|
156
|
-
style={[
|
|
157
|
-
stylesCommon.centerItems,
|
|
158
|
-
styles.avatarStyle,
|
|
159
|
-
styles.avatarTransparent,
|
|
160
|
-
avatarStyle,
|
|
161
|
-
]}
|
|
162
|
-
accessibilityRole='image'
|
|
163
|
-
/>
|
|
164
|
-
)
|
|
157
|
+
return placeholderView
|
|
165
158
|
|
|
166
159
|
if (user.avatar)
|
|
167
160
|
return (
|