@planningcenter/chat-react-native 3.16.0-rc.2 → 3.16.0-rc.4
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/build/components/conversation/attachments/giphy_attachment.d.ts.map +1 -1
- package/build/components/conversation/attachments/giphy_attachment.js +1 -11
- package/build/components/conversation/attachments/giphy_attachment.js.map +1 -1
- package/build/components/conversation/message.d.ts +2 -1
- package/build/components/conversation/message.d.ts.map +1 -1
- package/build/components/conversation/message.js +23 -23
- package/build/components/conversation/message.js.map +1 -1
- package/build/components/conversation/message_form.d.ts +2 -1
- package/build/components/conversation/message_form.d.ts.map +1 -1
- package/build/components/conversation/message_form.js +38 -16
- package/build/components/conversation/message_form.js.map +1 -1
- package/build/components/conversation/reply_connectors.js +1 -1
- package/build/components/conversation/reply_connectors.js.map +1 -1
- package/build/components/conversation/shadow_message.d.ts +8 -0
- package/build/components/conversation/shadow_message.d.ts.map +1 -0
- package/build/components/conversation/shadow_message.js +161 -0
- package/build/components/conversation/shadow_message.js.map +1 -0
- package/build/components/display/icon.d.ts +3 -1
- package/build/components/display/icon.d.ts.map +1 -1
- package/build/components/display/icon.js +2 -0
- package/build/components/display/icon.js.map +1 -1
- package/build/components/primitive/avatar_primitive.d.ts +1 -0
- package/build/components/primitive/avatar_primitive.d.ts.map +1 -1
- package/build/components/primitive/avatar_primitive.js +4 -0
- package/build/components/primitive/avatar_primitive.js.map +1 -1
- package/build/hooks/index.d.ts +1 -0
- package/build/hooks/index.d.ts.map +1 -1
- package/build/hooks/index.js +1 -0
- package/build/hooks/index.js.map +1 -1
- package/build/hooks/use_animated_message_background_color.d.ts +8 -0
- package/build/hooks/use_animated_message_background_color.d.ts.map +1 -0
- package/build/hooks/use_animated_message_background_color.js +29 -0
- package/build/hooks/use_animated_message_background_color.js.map +1 -0
- package/build/hooks/use_conversation_messages.d.ts +6 -3
- package/build/hooks/use_conversation_messages.d.ts.map +1 -1
- package/build/hooks/use_conversation_messages.js +32 -25
- package/build/hooks/use_conversation_messages.js.map +1 -1
- package/build/hooks/use_message_create_or_update.d.ts +2 -1
- package/build/hooks/use_message_create_or_update.d.ts.map +1 -1
- package/build/hooks/use_message_create_or_update.js +6 -2
- package/build/hooks/use_message_create_or_update.js.map +1 -1
- package/build/hooks/use_suspense_api.d.ts +3 -1
- package/build/hooks/use_suspense_api.d.ts.map +1 -1
- package/build/hooks/use_suspense_api.js +1 -0
- package/build/hooks/use_suspense_api.js.map +1 -1
- package/build/navigation/index.d.ts +6 -0
- package/build/navigation/index.d.ts.map +1 -1
- package/build/navigation/index.js +6 -0
- package/build/navigation/index.js.map +1 -1
- package/build/screens/conversation_screen.d.ts +2 -1
- package/build/screens/conversation_screen.d.ts.map +1 -1
- package/build/screens/conversation_screen.js +7 -5
- package/build/screens/conversation_screen.js.map +1 -1
- package/build/screens/message_actions_screen.d.ts +1 -0
- package/build/screens/message_actions_screen.d.ts.map +1 -1
- package/build/screens/message_actions_screen.js +16 -3
- package/build/screens/message_actions_screen.js.map +1 -1
- package/build/types/jolt_events/message_events.d.ts +2 -0
- package/build/types/jolt_events/message_events.d.ts.map +1 -1
- package/build/types/jolt_events/message_events.js.map +1 -1
- package/build/types/resources/message.d.ts +2 -0
- package/build/types/resources/message.d.ts.map +1 -1
- package/build/types/resources/message.js.map +1 -1
- package/build/utils/assert_keys_are_numbers.d.ts +2 -0
- package/build/utils/assert_keys_are_numbers.d.ts.map +1 -0
- package/build/utils/assert_keys_are_numbers.js +12 -0
- package/build/utils/assert_keys_are_numbers.js.map +1 -0
- package/build/utils/cache/optimistically_create_message.d.ts.map +1 -1
- package/build/utils/cache/optimistically_create_message.js +2 -0
- package/build/utils/cache/optimistically_create_message.js.map +1 -1
- package/build/utils/index.d.ts +2 -0
- package/build/utils/index.d.ts.map +1 -1
- package/build/utils/index.js +2 -0
- package/build/utils/index.js.map +1 -1
- package/build/utils/jolt/transform_message_event_data_to_message_resource.d.ts.map +1 -1
- package/build/utils/jolt/transform_message_event_data_to_message_resource.js +2 -0
- package/build/utils/jolt/transform_message_event_data_to_message_resource.js.map +1 -1
- package/build/utils/replies_local_feature_flag.d.ts +2 -0
- package/build/utils/replies_local_feature_flag.d.ts.map +1 -0
- package/build/utils/replies_local_feature_flag.js +3 -0
- package/build/utils/replies_local_feature_flag.js.map +1 -0
- package/package.json +2 -2
- package/src/components/conversation/attachments/giphy_attachment.tsx +1 -14
- package/src/components/conversation/message.tsx +40 -36
- package/src/components/conversation/message_form.tsx +85 -15
- package/src/components/conversation/reply_connectors.tsx +1 -1
- package/src/components/conversation/shadow_message.tsx +274 -0
- package/src/components/display/icon.tsx +3 -0
- package/src/components/primitive/avatar_primitive.tsx +4 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use_animated_message_background_color.ts +44 -0
- package/src/hooks/use_conversation_messages.ts +45 -25
- package/src/hooks/use_message_create_or_update.ts +7 -2
- package/src/hooks/use_suspense_api.ts +3 -0
- package/src/navigation/index.tsx +6 -0
- package/src/screens/conversation_screen.tsx +9 -4
- package/src/screens/message_actions_screen.tsx +27 -1
- package/src/types/jolt_events/message_events.ts +2 -0
- package/src/types/resources/message.ts +2 -0
- package/src/utils/assert_keys_are_numbers.ts +13 -0
- package/src/utils/cache/optimistically_create_message.ts +2 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/jolt/transform_message_event_data_to_message_resource.ts +2 -0
- package/src/utils/replies_local_feature_flag.ts +2 -0
|
@@ -17,6 +17,8 @@ export function transformMessageEventDataToMessageResource({ data, currentPerson
|
|
|
17
17
|
avatar: data.author_avatar,
|
|
18
18
|
},
|
|
19
19
|
reactionCounts: [],
|
|
20
|
+
replyCount: data.reply_count || 0,
|
|
21
|
+
replyRootId: data.reply_root_id || null,
|
|
20
22
|
};
|
|
21
23
|
}
|
|
22
24
|
//# sourceMappingURL=transform_message_event_data_to_message_resource.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform_message_event_data_to_message_resource.js","sourceRoot":"","sources":["../../../src/utils/jolt/transform_message_event_data_to_message_resource.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAExD,MAAM,UAAU,0CAA0C,CAAC,EACzD,IAAI,EACJ,eAAe,GAIhB;IACC,OAAO;QACL,IAAI,EAAE,SAAS;QACf,EAAE,EAAE,IAAI,CAAC,QAAQ;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,SAAS,EAAE,IAAI,CAAC,UAAU;QAC1B,SAAS,EAAE,IAAI,CAAC,UAAU;QAC1B,YAAY,EAAE,IAAI,CAAC,cAAc;QACjC,IAAI,EAAE,IAAI,CAAC,SAAS,KAAK,eAAe;QACxC,WAAW,EAAE,iBAAiB,CAAmC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;QACxF,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,IAAI,CAAC,SAAS;YAClB,IAAI,EAAE,IAAI,CAAC,WAAW;YACtB,MAAM,EAAE,IAAI,CAAC,aAAa;SAC3B;QACD,cAAc,EAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"transform_message_event_data_to_message_resource.js","sourceRoot":"","sources":["../../../src/utils/jolt/transform_message_event_data_to_message_resource.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAExD,MAAM,UAAU,0CAA0C,CAAC,EACzD,IAAI,EACJ,eAAe,GAIhB;IACC,OAAO;QACL,IAAI,EAAE,SAAS;QACf,EAAE,EAAE,IAAI,CAAC,QAAQ;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,SAAS,EAAE,IAAI,CAAC,UAAU;QAC1B,SAAS,EAAE,IAAI,CAAC,UAAU;QAC1B,YAAY,EAAE,IAAI,CAAC,cAAc;QACjC,IAAI,EAAE,IAAI,CAAC,SAAS,KAAK,eAAe;QACxC,WAAW,EAAE,iBAAiB,CAAmC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;QACxF,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,IAAI,CAAC,SAAS;YAClB,IAAI,EAAE,IAAI,CAAC,WAAW;YACtB,MAAM,EAAE,IAAI,CAAC,aAAa;SAC3B;QACD,cAAc,EAAE,EAAE;QAClB,UAAU,EAAE,IAAI,CAAC,WAAW,IAAI,CAAC;QACjC,WAAW,EAAE,IAAI,CAAC,aAAa,IAAI,IAAI;KACxC,CAAA;AACH,CAAC","sourcesContent":["import { MessageResource } from '../../types'\nimport { MessageCreatedEvent } from '../../types/jolt_events/message_events'\nimport { DenormalizedAttachmentResource } from '../../types/resources/denormalized_attachment_resource'\nimport { deepCamelCaseKeys } from '../deepCamelCaseKeys'\n\nexport function transformMessageEventDataToMessageResource({\n data,\n currentPersonId,\n}: {\n data: MessageCreatedEvent['data']['data']\n currentPersonId: number\n}): MessageResource {\n return {\n type: 'Message',\n id: data.sort_key,\n text: data.text,\n html: data.html,\n createdAt: data.created_at,\n deletedAt: data.deleted_at,\n textEditedAt: data.text_edited_at,\n mine: data.author_id === currentPersonId,\n attachments: deepCamelCaseKeys<DenormalizedAttachmentResource[]>(data.attachments) || [],\n author: {\n type: 'Person',\n id: data.author_id,\n name: data.author_name,\n avatar: data.author_avatar,\n },\n reactionCounts: [],\n replyCount: data.reply_count || 0,\n replyRootId: data.reply_root_id || null,\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replies_local_feature_flag.d.ts","sourceRoot":"","sources":["../../src/utils/replies_local_feature_flag.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,uBAAuB,QAAQ,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replies_local_feature_flag.js","sourceRoot":"","sources":["../../src/utils/replies_local_feature_flag.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,CAAA","sourcesContent":["// TODO: Replace this whole file with the flipper flag\nexport const REPLIES_FEATURE_ENABLED = false\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/chat-react-native",
|
|
3
|
-
"version": "3.16.0-rc.
|
|
3
|
+
"version": "3.16.0-rc.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
"react-native-url-polyfill": "^2.0.0",
|
|
56
56
|
"typescript": "<5.6.0"
|
|
57
57
|
},
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "9de20581feb4dbad2ab84082321718816506a330"
|
|
59
59
|
}
|
|
@@ -5,6 +5,7 @@ import { useTheme } from '../../../hooks'
|
|
|
5
5
|
import { DenormalizedGiphyAttachmentResource } from '../../../types/resources/denormalized_attachment_resource'
|
|
6
6
|
import { PlatformPressable } from '@react-navigation/elements'
|
|
7
7
|
import { Image } from '../../display'
|
|
8
|
+
import { assertKeysAreNumbers } from '../../../utils'
|
|
8
9
|
|
|
9
10
|
export function GiphyAttachment({
|
|
10
11
|
attachment,
|
|
@@ -46,20 +47,6 @@ export function GiphyAttachment({
|
|
|
46
47
|
)
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
const assertKeysAreNumbers = (obj: Object): Record<any, number> => {
|
|
50
|
-
return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, assertNumber(value)]))
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const assertNumber = (value: string): number => {
|
|
54
|
-
if (typeof value === 'number') return value
|
|
55
|
-
|
|
56
|
-
if (typeof value === 'string' && !isNaN(Number(value))) {
|
|
57
|
-
return Number(value)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return 0
|
|
61
|
-
}
|
|
62
|
-
|
|
63
50
|
const useStyles = ({ imageWidth, imageHeight }: { imageWidth: number; imageHeight: number }) => {
|
|
64
51
|
const { colors } = useTheme()
|
|
65
52
|
return StyleSheet.create({
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { useNavigation } from '@react-navigation/native'
|
|
2
2
|
import React, { useEffect } from 'react'
|
|
3
|
-
import {
|
|
3
|
+
import { Pressable, StyleSheet, useWindowDimensions, View } from 'react-native'
|
|
4
4
|
import { MessageReaction } from '../../components/conversation/message_reaction'
|
|
5
|
-
import { Avatar, Icon, Spinner, Text, TextInlineButton } from '../../components/display'
|
|
6
|
-
import {
|
|
5
|
+
import { Avatar, Icon, Spinner, Text, TextButton, TextInlineButton } from '../../components/display'
|
|
6
|
+
import {
|
|
7
|
+
useAnimatedMessageBackgroundColor,
|
|
8
|
+
useInteractionGhostBackgroundColor,
|
|
9
|
+
useTheme,
|
|
10
|
+
} from '../../hooks'
|
|
7
11
|
import { MessageResource } from '../../types'
|
|
8
12
|
import { ReactionCountResource } from '../../types/resources/reaction'
|
|
9
13
|
import { MessageAttachments } from './message_attachments'
|
|
@@ -15,18 +19,13 @@ import {
|
|
|
15
19
|
MESSAGE_AUTHOR_AVATAR_COLUMN_WIDTH,
|
|
16
20
|
platformFontWeightMedium,
|
|
17
21
|
} from '../../utils/styles'
|
|
18
|
-
import Animated
|
|
19
|
-
useSharedValue,
|
|
20
|
-
useAnimatedStyle,
|
|
21
|
-
withTiming,
|
|
22
|
-
interpolateColor,
|
|
23
|
-
Easing,
|
|
24
|
-
} from 'react-native-reanimated'
|
|
22
|
+
import Animated from 'react-native-reanimated'
|
|
25
23
|
import { useLiveRelativeTime } from '../../hooks/use_live_relative_time'
|
|
26
24
|
import { MessageReadReceipts } from './message_read_receipts'
|
|
27
25
|
import { isNewMessage, useMessageCreateOrUpdate } from '../../hooks/use_message_create_or_update'
|
|
28
26
|
import { Haptic } from '../../utils/native_adapters'
|
|
29
27
|
import { TheirReplyConnector, MyReplyConnector } from './reply_connectors'
|
|
28
|
+
import { REPLIES_FEATURE_ENABLED } from '../../utils'
|
|
30
29
|
|
|
31
30
|
/** Message
|
|
32
31
|
* Component for display of a message within a conversation list
|
|
@@ -35,12 +34,14 @@ interface MessageProps extends MessageResource {
|
|
|
35
34
|
canDeleteNonAuthoredMessages: boolean
|
|
36
35
|
conversation_id: number
|
|
37
36
|
latestReadMessageSortKey?: string
|
|
37
|
+
inReplyScreen?: boolean
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export function Message({
|
|
41
41
|
canDeleteNonAuthoredMessages,
|
|
42
42
|
conversation_id,
|
|
43
43
|
latestReadMessageSortKey,
|
|
44
|
+
inReplyScreen,
|
|
44
45
|
...message
|
|
45
46
|
}: MessageProps) {
|
|
46
47
|
const { text, reactionCounts, pending, error } = message
|
|
@@ -56,6 +57,8 @@ export function Message({
|
|
|
56
57
|
const isPersisted = !isNewMessage(message)
|
|
57
58
|
const [temporarilyHidePendingState, setTemporarilyHidePendingState] = React.useState(true)
|
|
58
59
|
const [messageBubbleHeight, setMessageBubbleHeight] = React.useState(0)
|
|
60
|
+
const { animatedBackgroundColor, handleMessagePressIn, handleMessagePressOut } =
|
|
61
|
+
useAnimatedMessageBackgroundColor()
|
|
59
62
|
|
|
60
63
|
useEffect(() => {
|
|
61
64
|
if (pending) {
|
|
@@ -81,30 +84,6 @@ export function Message({
|
|
|
81
84
|
}
|
|
82
85
|
}
|
|
83
86
|
|
|
84
|
-
const bgFadeProgress = useSharedValue(0)
|
|
85
|
-
const pressedColor = Platform.select({
|
|
86
|
-
ios: colors.fillColorNeutral050Base,
|
|
87
|
-
default: 'transparent',
|
|
88
|
-
})
|
|
89
|
-
const animatedBackgroundColor = useAnimatedStyle(() => {
|
|
90
|
-
const backgroundColor = interpolateColor(
|
|
91
|
-
bgFadeProgress.value,
|
|
92
|
-
[0, 1],
|
|
93
|
-
['transparent', pressedColor]
|
|
94
|
-
)
|
|
95
|
-
return {
|
|
96
|
-
backgroundColor,
|
|
97
|
-
}
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
const handlePressIn = () => {
|
|
101
|
-
bgFadeProgress.value = withTiming(1, { duration: 300, easing: Easing.inOut(Easing.ease) })
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const handlePressOut = () => {
|
|
105
|
-
bgFadeProgress.value = withTiming(0, { duration: 300, easing: Easing.inOut(Easing.ease) })
|
|
106
|
-
}
|
|
107
|
-
|
|
108
87
|
const handleMessageLongPress = () => {
|
|
109
88
|
if (!isPersisted) return
|
|
110
89
|
|
|
@@ -113,6 +92,7 @@ export function Message({
|
|
|
113
92
|
message_id: message.id,
|
|
114
93
|
conversation_id,
|
|
115
94
|
canDeleteNonAuthoredMessages,
|
|
95
|
+
inReplyScreen,
|
|
116
96
|
})
|
|
117
97
|
}
|
|
118
98
|
const handleReactionLongPress = (reaction: ReactionCountResource) => {
|
|
@@ -136,6 +116,14 @@ export function Message({
|
|
|
136
116
|
})
|
|
137
117
|
}
|
|
138
118
|
|
|
119
|
+
const handleNavigateToReplyPress = () => {
|
|
120
|
+
navigation.navigate('ConversationReply', {
|
|
121
|
+
conversation_id,
|
|
122
|
+
reply_root_id: message.id,
|
|
123
|
+
// TODO: Add a way to pass the reply root author's name
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
|
|
139
127
|
const metaProps = {
|
|
140
128
|
authorName: message.author.name,
|
|
141
129
|
createdAt: message.createdAt,
|
|
@@ -144,13 +132,15 @@ export function Message({
|
|
|
144
132
|
const renderAuthor = (!message.mine && message.renderAuthor) || false
|
|
145
133
|
const messageBottomMargin = message.lastInGroup ? 12 : hasReactions || showMessageMeta ? 8 : 4
|
|
146
134
|
const messagePendingLabel = isPersisted ? 'Saving' : 'Sending'
|
|
135
|
+
const showReplyCountButton =
|
|
136
|
+
!inReplyScreen && message.replyRootId === message.id && REPLIES_FEATURE_ENABLED
|
|
147
137
|
|
|
148
138
|
return (
|
|
149
139
|
<Pressable
|
|
150
140
|
onLongPress={handleMessageLongPress}
|
|
151
141
|
onPress={() => setShowMessageMetaToggle(!showMessageMetaToggle)}
|
|
152
|
-
onPressIn={
|
|
153
|
-
onPressOut={
|
|
142
|
+
onPressIn={handleMessagePressIn}
|
|
143
|
+
onPressOut={handleMessagePressOut}
|
|
154
144
|
android_ripple={{ color: colors.androidRippleNeutral }}
|
|
155
145
|
accessibilityHint="Long press to view message actions like reacting and copying."
|
|
156
146
|
>
|
|
@@ -191,6 +181,17 @@ export function Message({
|
|
|
191
181
|
</View>
|
|
192
182
|
)}
|
|
193
183
|
</View>
|
|
184
|
+
{showReplyCountButton && (
|
|
185
|
+
<TextButton
|
|
186
|
+
variant="footnote"
|
|
187
|
+
onPress={handleNavigateToReplyPress}
|
|
188
|
+
style={styles.messageReplyCount}
|
|
189
|
+
accessibilityHint="Navigates to reply screen for this message"
|
|
190
|
+
accessibilityRole="link"
|
|
191
|
+
>
|
|
192
|
+
{message.replyCount} replies
|
|
193
|
+
</TextButton>
|
|
194
|
+
)}
|
|
194
195
|
{hasReactions && (
|
|
195
196
|
<View style={styles.messageReactions}>
|
|
196
197
|
{reactionCounts.map(reaction => (
|
|
@@ -301,6 +302,9 @@ const useMessageStyles = ({ mine }: MessageResource) => {
|
|
|
301
302
|
gap: 4,
|
|
302
303
|
justifyContent: mine ? 'flex-end' : 'flex-start',
|
|
303
304
|
},
|
|
305
|
+
messageReplyCount: {
|
|
306
|
+
alignSelf: mine ? 'flex-end' : 'flex-start',
|
|
307
|
+
},
|
|
304
308
|
messageMeta: {
|
|
305
309
|
flexDirection: 'row',
|
|
306
310
|
alignItems: 'center',
|
|
@@ -15,11 +15,12 @@ import {
|
|
|
15
15
|
ViewProps,
|
|
16
16
|
Keyboard,
|
|
17
17
|
} from 'react-native'
|
|
18
|
-
import { Icon, IconButton, Text, TextButton } from '../../components'
|
|
18
|
+
import { Heading, Icon, IconButton, IconString, Text, TextButton } from '../../components'
|
|
19
19
|
import {
|
|
20
20
|
useCreateAndroidRippleColor,
|
|
21
21
|
useTheme,
|
|
22
22
|
useInteractionGhostBackgroundColor,
|
|
23
|
+
useScalableNumberOfLines,
|
|
23
24
|
} from '../../hooks'
|
|
24
25
|
import { ConversationResource, MessageResource } from '../../types'
|
|
25
26
|
|
|
@@ -27,7 +28,12 @@ import { ConversationScreenProps } from '../../screens/conversation_screen'
|
|
|
27
28
|
|
|
28
29
|
import { ChatContext } from '../../contexts/chat_context'
|
|
29
30
|
import { Haptic, ImagePicker, ImagePickerResult } from '../../utils/native_adapters'
|
|
30
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
MAX_FONT_SIZE_MULTIPLIER_LANDMARK,
|
|
33
|
+
REPLIES_FEATURE_ENABLED,
|
|
34
|
+
platformFontWeightMedium,
|
|
35
|
+
platformPressedOpacityStyle,
|
|
36
|
+
} from '../../utils'
|
|
31
37
|
import { useAttachmentUploader } from '../../hooks/use_attachment_uploader'
|
|
32
38
|
import { useMessageDraft } from '../../hooks/use_message_draft'
|
|
33
39
|
import {
|
|
@@ -53,6 +59,7 @@ export const MessageForm = {
|
|
|
53
59
|
interface MessagesFormRootProps extends ViewProps {
|
|
54
60
|
conversation: ConversationResource
|
|
55
61
|
currentlyEditingMessage?: MessageResource | null
|
|
62
|
+
replyRootId?: string
|
|
56
63
|
}
|
|
57
64
|
|
|
58
65
|
const MessageFormContext = React.createContext<{
|
|
@@ -66,6 +73,7 @@ const MessageFormContext = React.createContext<{
|
|
|
66
73
|
attachmentUploader?: ReturnType<typeof useAttachmentUploader>
|
|
67
74
|
currentlyEditingMessage?: MessageResource | null
|
|
68
75
|
reset: () => void
|
|
76
|
+
replyRootId?: string
|
|
69
77
|
}>({
|
|
70
78
|
text: '',
|
|
71
79
|
setText: (_text: string) => {},
|
|
@@ -76,6 +84,7 @@ const MessageFormContext = React.createContext<{
|
|
|
76
84
|
setUsingGiphy: (_usingGiphy: boolean) => {},
|
|
77
85
|
currentlyEditingMessage: null,
|
|
78
86
|
reset: () => {},
|
|
87
|
+
replyRootId: undefined,
|
|
79
88
|
})
|
|
80
89
|
|
|
81
90
|
const GIPHY_MAX_LENGTH = 50
|
|
@@ -85,6 +94,7 @@ function MessageFormRoot({
|
|
|
85
94
|
conversation,
|
|
86
95
|
currentlyEditingMessage,
|
|
87
96
|
children,
|
|
97
|
+
replyRootId,
|
|
88
98
|
}: MessagesFormRootProps) {
|
|
89
99
|
const { giphyApiKey } = useContext(ChatContext)
|
|
90
100
|
const canGiphy = !!giphyApiKey && !currentlyEditingMessage
|
|
@@ -105,6 +115,7 @@ function MessageFormRoot({
|
|
|
105
115
|
} = useMessageCreateOrUpdate({
|
|
106
116
|
conversationId: conversation.id,
|
|
107
117
|
message: currentlyEditingMessage || undefined,
|
|
118
|
+
replyRootId,
|
|
108
119
|
})
|
|
109
120
|
const attachmentUploader = useAttachmentUploader({
|
|
110
121
|
conversationId: conversation.id,
|
|
@@ -236,10 +247,12 @@ function MessageFormRoot({
|
|
|
236
247
|
attachmentUploader,
|
|
237
248
|
currentlyEditingMessage,
|
|
238
249
|
reset,
|
|
250
|
+
replyRootId,
|
|
239
251
|
}}
|
|
240
252
|
>
|
|
241
253
|
<View style={styles.container}>
|
|
242
254
|
<EditingIndicator />
|
|
255
|
+
<ReplyIndicator />
|
|
243
256
|
<View style={styles.textInputContainer}>{children}</View>
|
|
244
257
|
</View>
|
|
245
258
|
</MessageFormContext.Provider>
|
|
@@ -529,25 +542,76 @@ function MessageFormCommands() {
|
|
|
529
542
|
|
|
530
543
|
function EditingIndicator() {
|
|
531
544
|
const { currentlyEditingMessage, reset } = React.useContext(MessageFormContext)
|
|
532
|
-
const styles = useMessageFormStyles()
|
|
533
545
|
|
|
534
546
|
if (!currentlyEditingMessage) {
|
|
535
547
|
return null
|
|
536
548
|
}
|
|
537
549
|
|
|
538
550
|
return (
|
|
539
|
-
<
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
551
|
+
<FormIndicatorRow
|
|
552
|
+
title="Editing message"
|
|
553
|
+
buttonText="Cancel"
|
|
554
|
+
accessibilityHint="Exit message editing mode without saving"
|
|
555
|
+
iconName="accounts.editor"
|
|
556
|
+
onPress={() => reset()}
|
|
557
|
+
/>
|
|
558
|
+
)
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
function ReplyIndicator() {
|
|
562
|
+
const { replyRootId } = React.useContext(MessageFormContext)
|
|
563
|
+
const navigation = useNavigation()
|
|
564
|
+
|
|
565
|
+
if (!REPLIES_FEATURE_ENABLED || !replyRootId) return null
|
|
566
|
+
|
|
567
|
+
return (
|
|
568
|
+
<FormIndicatorRow
|
|
569
|
+
title="Reply" // TODO: Get root reply author
|
|
570
|
+
buttonText="Exit replies"
|
|
571
|
+
accessibilityHint="Return to the main conversation"
|
|
572
|
+
iconName="registrations.undo"
|
|
573
|
+
onPress={() => navigation.goBack()}
|
|
574
|
+
/>
|
|
575
|
+
)
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
interface FormIndicatorRowProps {
|
|
579
|
+
title: string
|
|
580
|
+
buttonText: string
|
|
581
|
+
accessibilityHint: string
|
|
582
|
+
onPress: () => void
|
|
583
|
+
iconName: IconString
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
function FormIndicatorRow({
|
|
587
|
+
title,
|
|
588
|
+
buttonText,
|
|
589
|
+
accessibilityHint,
|
|
590
|
+
iconName,
|
|
591
|
+
onPress,
|
|
592
|
+
}: FormIndicatorRowProps) {
|
|
593
|
+
const styles = useMessageFormStyles()
|
|
594
|
+
const scalableNumberOfLines = useScalableNumberOfLines(1)
|
|
595
|
+
|
|
596
|
+
return (
|
|
597
|
+
<View style={styles.formIndicatorRow}>
|
|
598
|
+
<View style={styles.formIndicatorRowTitleContainer}>
|
|
599
|
+
<Icon name={iconName} size={16} style={styles.formIndicatorRowIcon} />
|
|
600
|
+
<Heading
|
|
601
|
+
variant="h4"
|
|
602
|
+
style={styles.formIndicatorRowTitle}
|
|
603
|
+
numberOfLines={scalableNumberOfLines}
|
|
604
|
+
maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}
|
|
605
|
+
>
|
|
606
|
+
{title}
|
|
607
|
+
</Heading>
|
|
545
608
|
</View>
|
|
546
609
|
<TextButton
|
|
547
|
-
onPress={
|
|
548
|
-
accessibilityHint=
|
|
610
|
+
onPress={onPress}
|
|
611
|
+
accessibilityHint={accessibilityHint}
|
|
612
|
+
maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}
|
|
549
613
|
>
|
|
550
|
-
|
|
614
|
+
{buttonText}
|
|
551
615
|
</TextButton>
|
|
552
616
|
</View>
|
|
553
617
|
)
|
|
@@ -681,20 +745,26 @@ const useMessageFormStyles = () => {
|
|
|
681
745
|
paddingHorizontal: 16,
|
|
682
746
|
paddingVertical: 4,
|
|
683
747
|
},
|
|
684
|
-
|
|
748
|
+
formIndicatorRow: {
|
|
685
749
|
flexDirection: 'row',
|
|
686
750
|
alignItems: 'center',
|
|
687
751
|
justifyContent: 'space-between',
|
|
688
752
|
gap: 8,
|
|
689
753
|
paddingBottom: 12,
|
|
690
754
|
},
|
|
691
|
-
|
|
755
|
+
formIndicatorRowTitleContainer: {
|
|
692
756
|
flexDirection: 'row',
|
|
693
757
|
alignItems: 'center',
|
|
694
758
|
gap: 8,
|
|
759
|
+
flex: 1,
|
|
760
|
+
},
|
|
761
|
+
formIndicatorRowIcon: {
|
|
762
|
+
color: theme.colors.iconColorDefaultSecondary,
|
|
695
763
|
},
|
|
696
|
-
|
|
764
|
+
formIndicatorRowTitle: {
|
|
697
765
|
fontWeight: platformFontWeightMedium,
|
|
766
|
+
textTransform: 'none',
|
|
767
|
+
flexShrink: 1,
|
|
698
768
|
},
|
|
699
769
|
})
|
|
700
770
|
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL,
|
|
7
7
|
MESSAGE_AUTHOR_AVATAR_COLUMN_WIDTH,
|
|
8
8
|
} from '../../utils/styles'
|
|
9
|
-
import { REPLIES_FEATURE_ENABLED } from '../../
|
|
9
|
+
import { REPLIES_FEATURE_ENABLED } from '../../utils'
|
|
10
10
|
|
|
11
11
|
const MY_REPLY_CONNECTOR_WIDTH = 38
|
|
12
12
|
const CONNECTOR_BORDER_WIDTH = 4
|