@planningcenter/chat-react-native 3.15.0-rc.9 → 3.16.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/components/conversation/message.d.ts.map +1 -1
- package/build/components/conversation/message.js +11 -9
- package/build/components/conversation/message.js.map +1 -1
- package/build/components/conversation/reply_connectors.d.ts +9 -0
- package/build/components/conversation/reply_connectors.d.ts.map +1 -0
- package/build/components/conversation/reply_connectors.js +147 -0
- package/build/components/conversation/reply_connectors.js.map +1 -0
- package/build/components/display/avatar.d.ts +2 -1
- package/build/components/display/avatar.d.ts.map +1 -1
- package/build/components/display/avatar.js +2 -2
- package/build/components/display/avatar.js.map +1 -1
- package/build/components/display/avatar_group.d.ts +2 -1
- package/build/components/display/avatar_group.d.ts.map +1 -1
- package/build/components/display/avatar_group.js +2 -2
- package/build/components/display/avatar_group.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 +25 -19
- package/build/components/primitive/avatar_primitive.js.map +1 -1
- package/build/hooks/use_app_name.d.ts +3 -0
- package/build/hooks/use_app_name.d.ts.map +1 -0
- package/build/hooks/use_app_name.js +12 -0
- package/build/hooks/use_app_name.js.map +1 -0
- package/build/hooks/use_report_bug_action.d.ts +1 -1
- package/build/hooks/use_report_bug_action.d.ts.map +1 -1
- package/build/hooks/use_report_bug_action.js +1 -9
- package/build/hooks/use_report_bug_action.js.map +1 -1
- package/build/navigation/index.d.ts +20 -5
- package/build/navigation/index.d.ts.map +1 -1
- package/build/navigation/index.js +23 -15
- package/build/navigation/index.js.map +1 -1
- package/build/screens/bug_report_screen.d.ts.map +1 -1
- package/build/screens/bug_report_screen.js +62 -57
- package/build/screens/bug_report_screen.js.map +1 -1
- package/build/screens/conversation_screen.d.ts +1 -0
- package/build/screens/conversation_screen.d.ts.map +1 -1
- package/build/screens/conversation_screen.js +1 -0
- package/build/screens/conversation_screen.js.map +1 -1
- package/build/screens/conversations/conversations_screen.d.ts.map +1 -1
- package/build/screens/conversations/conversations_screen.js +6 -6
- package/build/screens/conversations/conversations_screen.js.map +1 -1
- package/build/screens/get_help_screen.d.ts +5 -0
- package/build/screens/get_help_screen.d.ts.map +1 -0
- package/build/screens/get_help_screen.js +94 -0
- package/build/screens/get_help_screen.js.map +1 -0
- package/build/utils/styles.d.ts +1 -0
- package/build/utils/styles.d.ts.map +1 -1
- package/build/utils/styles.js +1 -0
- package/build/utils/styles.js.map +1 -1
- package/package.json +2 -2
- package/src/components/conversation/message.tsx +22 -8
- package/src/components/conversation/reply_connectors.tsx +192 -0
- package/src/components/display/avatar.tsx +8 -1
- package/src/components/display/avatar_group.tsx +8 -1
- package/src/components/primitive/avatar_primitive.tsx +28 -17
- package/src/hooks/use_app_name.ts +17 -0
- package/src/hooks/use_report_bug_action.ts +2 -10
- package/src/navigation/index.tsx +38 -25
- package/src/screens/bug_report_screen.tsx +79 -67
- package/src/screens/conversation_screen.tsx +2 -0
- package/src/screens/conversations/conversations_screen.tsx +7 -7
- package/src/screens/get_help_screen.tsx +131 -0
- package/src/utils/styles.ts +1 -0
|
@@ -12,6 +12,7 @@ import { MessageMarkdown } from './message_markdown'
|
|
|
12
12
|
import { DenormalizedMessageAttachmentResource } from '../../types/resources/denormalized_attachment_resource'
|
|
13
13
|
import {
|
|
14
14
|
CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL,
|
|
15
|
+
MESSAGE_AUTHOR_AVATAR_COLUMN_WIDTH,
|
|
15
16
|
platformFontWeightMedium,
|
|
16
17
|
} from '../../utils/styles'
|
|
17
18
|
import Animated, {
|
|
@@ -25,6 +26,7 @@ import { useLiveRelativeTime } from '../../hooks/use_live_relative_time'
|
|
|
25
26
|
import { MessageReadReceipts } from './message_read_receipts'
|
|
26
27
|
import { isNewMessage, useMessageCreateOrUpdate } from '../../hooks/use_message_create_or_update'
|
|
27
28
|
import { Haptic } from '../../utils/native_adapters'
|
|
29
|
+
import { TheirReplyConnector, MyReplyConnector } from './reply_connectors'
|
|
28
30
|
|
|
29
31
|
/** Message
|
|
30
32
|
* Component for display of a message within a conversation list
|
|
@@ -53,6 +55,7 @@ export function Message({
|
|
|
53
55
|
const wasEdited = Boolean(message.textEditedAt)
|
|
54
56
|
const isPersisted = !isNewMessage(message)
|
|
55
57
|
const [temporarilyHidePendingState, setTemporarilyHidePendingState] = React.useState(true)
|
|
58
|
+
const [messageBubbleHeight, setMessageBubbleHeight] = React.useState(0)
|
|
56
59
|
|
|
57
60
|
useEffect(() => {
|
|
58
61
|
if (pending) {
|
|
@@ -153,17 +156,27 @@ export function Message({
|
|
|
153
156
|
>
|
|
154
157
|
<Animated.View style={[styles.message, animatedBackgroundColor]}>
|
|
155
158
|
{!message.mine && (
|
|
156
|
-
<View
|
|
159
|
+
<View>
|
|
157
160
|
{renderAuthor ? (
|
|
158
|
-
<Avatar
|
|
161
|
+
<Avatar
|
|
162
|
+
size={'md'}
|
|
163
|
+
sourceUri={message.author.avatar}
|
|
164
|
+
style={styles.avatar}
|
|
165
|
+
maxFontSizeMultiplier={1}
|
|
166
|
+
minFontSizeMultiplier={1}
|
|
167
|
+
/>
|
|
159
168
|
) : (
|
|
160
169
|
<View style={styles.avatarPlaceholder} />
|
|
161
170
|
)}
|
|
171
|
+
<TheirReplyConnector message={message} messageBubbleHeight={messageBubbleHeight} />
|
|
162
172
|
</View>
|
|
163
173
|
)}
|
|
164
174
|
<View style={[styles.messageContent, { marginBottom: messageBottomMargin }]}>
|
|
165
175
|
{renderAuthor && <Text variant="tertiary">{message.author.name}</Text>}
|
|
166
|
-
<View
|
|
176
|
+
<View
|
|
177
|
+
style={styles.messageBubble}
|
|
178
|
+
onLayout={e => setMessageBubbleHeight(e.nativeEvent.layout.height)}
|
|
179
|
+
>
|
|
167
180
|
<ErrorBoundary>
|
|
168
181
|
<MessageAttachments
|
|
169
182
|
attachments={message.attachments}
|
|
@@ -241,6 +254,9 @@ export function Message({
|
|
|
241
254
|
</View>
|
|
242
255
|
)}
|
|
243
256
|
</View>
|
|
257
|
+
{message.mine && (
|
|
258
|
+
<MyReplyConnector message={message} messageBubbleHeight={messageBubbleHeight} />
|
|
259
|
+
)}
|
|
244
260
|
</Animated.View>
|
|
245
261
|
</Pressable>
|
|
246
262
|
)
|
|
@@ -264,13 +280,11 @@ const useMessageStyles = ({ mine }: MessageResource) => {
|
|
|
264
280
|
flex: 1,
|
|
265
281
|
gap: 4,
|
|
266
282
|
},
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
gap: 8,
|
|
283
|
+
avatar: {
|
|
284
|
+
marginBottom: 8,
|
|
270
285
|
},
|
|
271
286
|
avatarPlaceholder: {
|
|
272
|
-
width:
|
|
273
|
-
height: 32, // Same height as avatar
|
|
287
|
+
width: MESSAGE_AUTHOR_AVATAR_COLUMN_WIDTH, // Same width as avatar
|
|
274
288
|
},
|
|
275
289
|
messageBubble: {
|
|
276
290
|
backgroundColor: messageBubbleBackgroundColor,
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { StyleSheet, View, ViewStyle } from 'react-native'
|
|
2
|
+
import Svg, { Path } from 'react-native-svg'
|
|
3
|
+
import { useTheme } from '../../hooks'
|
|
4
|
+
import { MessageResource } from '../../types'
|
|
5
|
+
import {
|
|
6
|
+
CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL,
|
|
7
|
+
MESSAGE_AUTHOR_AVATAR_COLUMN_WIDTH,
|
|
8
|
+
} from '../../utils/styles'
|
|
9
|
+
import { REPLIES_FEATURE_ENABLED } from '../../screens/conversation_screen'
|
|
10
|
+
|
|
11
|
+
const MY_REPLY_CONNECTOR_WIDTH = 38
|
|
12
|
+
const CONNECTOR_BORDER_WIDTH = 4
|
|
13
|
+
|
|
14
|
+
interface ReplyConnectorProps {
|
|
15
|
+
message: MessageResource
|
|
16
|
+
messageBubbleHeight: number
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function TheirReplyConnector({ message, messageBubbleHeight }: ReplyConnectorProps) {
|
|
20
|
+
const styles = useStyles()
|
|
21
|
+
|
|
22
|
+
if (!REPLIES_FEATURE_ENABLED) return null
|
|
23
|
+
|
|
24
|
+
// TODO: Need to remove, just adding this to remove the lint warning about message being unused
|
|
25
|
+
console.log('message', message)
|
|
26
|
+
|
|
27
|
+
const connectorMap: Record<string, React.ReactNode | null> = {
|
|
28
|
+
shortTailCurve: <ShortTailCurveConnector height={messageBubbleHeight / 2} />,
|
|
29
|
+
verticalLine: <VerticalLineConnector />,
|
|
30
|
+
default: null,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// TODO: Currently using fake message attributes. Will need to refactor once we have the message reply logic in place.
|
|
34
|
+
const getConnectorKey = () => {
|
|
35
|
+
// TODO: if (message.previousMessageIsTheirReplyMessage && message.nextMessageIsSomeoneElseReplyMessage) return 'shortTailCurve'
|
|
36
|
+
// TODO: if (message.isRootMessage || (message.isTheirReplyMessage && message.nextMessageIsTheirReplyMessage) || (message.isTheirReplyMessage && message.nextMessageIsSomeoneElseReplyMessage && !message.nextMessageIsMyMessage)) return 'verticalLine'
|
|
37
|
+
return 'default'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const ConnectorComponent = connectorMap[getConnectorKey()]
|
|
41
|
+
|
|
42
|
+
if (!ConnectorComponent) return null
|
|
43
|
+
|
|
44
|
+
return <View style={styles.theirReplyConnectorContainer}>{ConnectorComponent}</View>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// TODO: Refactor how we choose the correct connector once we have the logic in place
|
|
48
|
+
export function MyReplyConnector({ message, messageBubbleHeight }: ReplyConnectorProps) {
|
|
49
|
+
const styles = useStyles()
|
|
50
|
+
|
|
51
|
+
if (!REPLIES_FEATURE_ENABLED) return null
|
|
52
|
+
|
|
53
|
+
// TODO: Need to remove, just adding this to remove the lint warning about message being unused
|
|
54
|
+
console.log('message', message)
|
|
55
|
+
|
|
56
|
+
const connectorMap: Record<string, React.ReactNode | null> = {
|
|
57
|
+
longTailCurve: (
|
|
58
|
+
<LongTailCurveConnector
|
|
59
|
+
height={messageBubbleHeight / 2}
|
|
60
|
+
style={styles.myReplyConnectorPosition}
|
|
61
|
+
/>
|
|
62
|
+
),
|
|
63
|
+
longHeadCurve: (
|
|
64
|
+
<LongHeadCurveConnector
|
|
65
|
+
height={messageBubbleHeight / 2}
|
|
66
|
+
style={styles.myReplyConnectorPosition}
|
|
67
|
+
/>
|
|
68
|
+
),
|
|
69
|
+
verticalLine: <VerticalLineConnector style={styles.myReplyConnectorPosition} />,
|
|
70
|
+
swirl: <SwirlConnector style={styles.myReplyConnectorPosition} />,
|
|
71
|
+
default: null,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// TODO: Currently using fake message attributes. Will need to refactor once we have the message reply logic in place.
|
|
75
|
+
const getConnectorKey = () => {
|
|
76
|
+
// TODO: if (message.currentMessageIsReply && (message.nextMessageIsNotReplyMessage || message.nextMessageIsDifferentReplyRootId)) return 'longTailCurve'
|
|
77
|
+
// TODO: if (message.currentMessageIsReplyRoot && message.nextMessageIsMyReply) return 'longHeadCurve'
|
|
78
|
+
// TODO: if (message.currentMessageIsReply && message.nextMessageIsReply) return 'verticalLine'
|
|
79
|
+
// TODO: if (message.currentMessageIsReply && message.previousMessageSomeoneElseReply && (message.nextMessageIsSomeoneElseReply || message.nextMessageIsMyReply)) return 'swirl'
|
|
80
|
+
return 'default'
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const ConnectorComponent = connectorMap[getConnectorKey()]
|
|
84
|
+
|
|
85
|
+
if (!ConnectorComponent) return null
|
|
86
|
+
|
|
87
|
+
return <View style={styles.myReplyConnectorContainer}>{ConnectorComponent}</View>
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function VerticalLineConnector({ style }: { style?: ViewStyle }) {
|
|
91
|
+
const styles = useStyles()
|
|
92
|
+
return <View style={[styles.verticalLineConnector, style]} />
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function LongHeadCurveConnector({ height, style }: { height: number; style?: ViewStyle }) {
|
|
96
|
+
const styles = useStyles()
|
|
97
|
+
return <View style={[styles.longHeadCurveConnector, { height, marginTop: height }, style]} />
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function LongTailCurveConnector({ height, style }: { height: number; style?: ViewStyle }) {
|
|
101
|
+
const styles = useStyles()
|
|
102
|
+
return <View style={[styles.longTailCurveConnector, { height }, style]} />
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function ShortTailCurveConnector({ height }: { height: number }) {
|
|
106
|
+
const styles = useStyles()
|
|
107
|
+
return <View style={[styles.shortTailCurveConnector, { height }]} />
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function SwirlConnector({ style }: { style?: ViewStyle }) {
|
|
111
|
+
const styles = useStyles()
|
|
112
|
+
const { colors } = useTheme()
|
|
113
|
+
const borderColor = colors.borderColorDefaultBase
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<View style={[styles.swirlConnectorContainer, style]}>
|
|
117
|
+
<View style={styles.swirlConnectorVerticalLineHead} />
|
|
118
|
+
<Svg width={27} height={34} fill="none">
|
|
119
|
+
<Path
|
|
120
|
+
stroke={borderColor}
|
|
121
|
+
strokeWidth={CONNECTOR_BORDER_WIDTH}
|
|
122
|
+
d="M2.07 34c0-6.142 1.201-12.283 3.343-17m0 0c2.305-5.075 5.699-8.5 9.857-8.5 4.86 0 8.8 3.806 8.8 8.5s-3.94 8.5-8.8 8.5c-4.158 0-7.552-3.425-9.857-8.5zm0 0C3.271 12.283 2.07 6.142 2.07 0"
|
|
123
|
+
/>
|
|
124
|
+
</Svg>
|
|
125
|
+
<View style={styles.swirlConnectorVerticalLineTail} />
|
|
126
|
+
</View>
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const useStyles = () => {
|
|
131
|
+
const { colors } = useTheme()
|
|
132
|
+
const borderColor = colors.borderColorDefaultBase
|
|
133
|
+
|
|
134
|
+
return StyleSheet.create({
|
|
135
|
+
theirReplyConnectorContainer: {
|
|
136
|
+
width: '50%',
|
|
137
|
+
alignSelf: 'flex-end',
|
|
138
|
+
flex: 1,
|
|
139
|
+
},
|
|
140
|
+
myReplyConnectorContainer: {
|
|
141
|
+
width: MESSAGE_AUTHOR_AVATAR_COLUMN_WIDTH,
|
|
142
|
+
position: 'absolute',
|
|
143
|
+
left: CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL,
|
|
144
|
+
top: 0,
|
|
145
|
+
bottom: 0,
|
|
146
|
+
},
|
|
147
|
+
myReplyConnectorPosition: {
|
|
148
|
+
left: '50%',
|
|
149
|
+
},
|
|
150
|
+
verticalLineConnector: {
|
|
151
|
+
flex: 1,
|
|
152
|
+
borderLeftWidth: CONNECTOR_BORDER_WIDTH,
|
|
153
|
+
borderLeftColor: borderColor,
|
|
154
|
+
},
|
|
155
|
+
longHeadCurveConnector: {
|
|
156
|
+
width: MY_REPLY_CONNECTOR_WIDTH,
|
|
157
|
+
borderColor: borderColor,
|
|
158
|
+
borderLeftWidth: CONNECTOR_BORDER_WIDTH,
|
|
159
|
+
borderTopWidth: CONNECTOR_BORDER_WIDTH,
|
|
160
|
+
borderTopLeftRadius: 16,
|
|
161
|
+
flex: 1,
|
|
162
|
+
},
|
|
163
|
+
longTailCurveConnector: {
|
|
164
|
+
width: MY_REPLY_CONNECTOR_WIDTH,
|
|
165
|
+
borderColor: borderColor,
|
|
166
|
+
borderLeftWidth: CONNECTOR_BORDER_WIDTH,
|
|
167
|
+
borderBottomWidth: CONNECTOR_BORDER_WIDTH,
|
|
168
|
+
borderBottomLeftRadius: 16,
|
|
169
|
+
},
|
|
170
|
+
shortTailCurveConnector: {
|
|
171
|
+
borderColor: borderColor,
|
|
172
|
+
borderLeftWidth: CONNECTOR_BORDER_WIDTH,
|
|
173
|
+
borderBottomWidth: CONNECTOR_BORDER_WIDTH,
|
|
174
|
+
borderBottomLeftRadius: 16,
|
|
175
|
+
},
|
|
176
|
+
swirlConnectorContainer: {
|
|
177
|
+
flex: 1,
|
|
178
|
+
},
|
|
179
|
+
swirlConnectorVerticalLineHead: {
|
|
180
|
+
backgroundColor: borderColor,
|
|
181
|
+
width: CONNECTOR_BORDER_WIDTH,
|
|
182
|
+
flex: 1,
|
|
183
|
+
marginBottom: -1, // Ensures there is no gap between the vertical line and the swirl connector
|
|
184
|
+
},
|
|
185
|
+
swirlConnectorVerticalLineTail: {
|
|
186
|
+
backgroundColor: borderColor,
|
|
187
|
+
width: CONNECTOR_BORDER_WIDTH,
|
|
188
|
+
flex: 1,
|
|
189
|
+
marginTop: -1, // Ensures there is no gap between the vertical line and the swirl connector
|
|
190
|
+
},
|
|
191
|
+
})
|
|
192
|
+
}
|
|
@@ -14,6 +14,7 @@ interface AvatarProps {
|
|
|
14
14
|
fallbackIconName?: IconString
|
|
15
15
|
style?: AvatarRootProps['style']
|
|
16
16
|
maxFontSizeMultiplier?: AvatarRootProps['maxFontSizeMultiplier']
|
|
17
|
+
minFontSizeMultiplier?: AvatarRootProps['minFontSizeMultiplier']
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export function Avatar({
|
|
@@ -24,11 +25,17 @@ export function Avatar({
|
|
|
24
25
|
fallbackIconName = 'general.person',
|
|
25
26
|
style,
|
|
26
27
|
maxFontSizeMultiplier,
|
|
28
|
+
minFontSizeMultiplier,
|
|
27
29
|
}: AvatarProps) {
|
|
28
30
|
const shouldShowFallback = showFallback || !sourceUri
|
|
29
31
|
|
|
30
32
|
return (
|
|
31
|
-
<AvatarPrimitive.Root
|
|
33
|
+
<AvatarPrimitive.Root
|
|
34
|
+
size={size}
|
|
35
|
+
style={style}
|
|
36
|
+
maxFontSizeMultiplier={maxFontSizeMultiplier}
|
|
37
|
+
minFontSizeMultiplier={minFontSizeMultiplier}
|
|
38
|
+
>
|
|
32
39
|
<AvatarPrimitive.Mask>
|
|
33
40
|
{shouldShowFallback ? (
|
|
34
41
|
<AvatarPrimitive.ImageFallback name={fallbackIconName} />
|
|
@@ -12,6 +12,7 @@ interface AvatarGroupDisplayProps {
|
|
|
12
12
|
size?: AvatarRootProps['size']
|
|
13
13
|
style?: AvatarRootProps['style']
|
|
14
14
|
maxFontSizeMultiplier?: AvatarRootProps['maxFontSizeMultiplier']
|
|
15
|
+
minFontSizeMultiplier?: AvatarRootProps['minFontSizeMultiplier']
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export function AvatarGroup({
|
|
@@ -21,11 +22,17 @@ export function AvatarGroup({
|
|
|
21
22
|
size = 'lg',
|
|
22
23
|
style,
|
|
23
24
|
maxFontSizeMultiplier,
|
|
25
|
+
minFontSizeMultiplier,
|
|
24
26
|
}: AvatarGroupDisplayProps) {
|
|
25
27
|
const shouldShowFallback = showFallback || !sourceUris || sourceUris.length === 0
|
|
26
28
|
|
|
27
29
|
return (
|
|
28
|
-
<AvatarPrimitive.Root
|
|
30
|
+
<AvatarPrimitive.Root
|
|
31
|
+
size={size}
|
|
32
|
+
style={style}
|
|
33
|
+
maxFontSizeMultiplier={maxFontSizeMultiplier}
|
|
34
|
+
minFontSizeMultiplier={minFontSizeMultiplier}
|
|
35
|
+
>
|
|
29
36
|
<AvatarPrimitive.Mask>
|
|
30
37
|
{shouldShowFallback ? (
|
|
31
38
|
<AvatarPrimitive.ImageFallback name={fallbackIconName} />
|
|
@@ -86,6 +86,7 @@ interface AvatarContextType {
|
|
|
86
86
|
allImagesLoaded: boolean
|
|
87
87
|
setAllImagesLoaded: React.Dispatch<React.SetStateAction<boolean>>
|
|
88
88
|
maxFontSizeMultiplier: number
|
|
89
|
+
minFontSizeMultiplier?: number
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
const AvatarContext = createContext<AvatarContextType | null>(null)
|
|
@@ -107,6 +108,7 @@ interface AvatarRootProps {
|
|
|
107
108
|
size?: AvatarSize
|
|
108
109
|
style?: ViewProps['style']
|
|
109
110
|
maxFontSizeMultiplier?: number
|
|
111
|
+
minFontSizeMultiplier?: number
|
|
110
112
|
}
|
|
111
113
|
|
|
112
114
|
function AvatarRoot({
|
|
@@ -114,13 +116,20 @@ function AvatarRoot({
|
|
|
114
116
|
size = 'md',
|
|
115
117
|
style,
|
|
116
118
|
maxFontSizeMultiplier = MAX_FONT_SIZE_MULTIPLIER,
|
|
119
|
+
minFontSizeMultiplier = undefined,
|
|
117
120
|
}: AvatarRootProps) {
|
|
118
121
|
const [allImagesLoaded, setAllImagesLoaded] = useState(false)
|
|
119
|
-
const styles = useStyles({ size, maxFontSizeMultiplier })
|
|
122
|
+
const styles = useStyles({ size, maxFontSizeMultiplier, minFontSizeMultiplier })
|
|
120
123
|
|
|
121
124
|
return (
|
|
122
125
|
<AvatarContext.Provider
|
|
123
|
-
value={{
|
|
126
|
+
value={{
|
|
127
|
+
size,
|
|
128
|
+
allImagesLoaded,
|
|
129
|
+
setAllImagesLoaded,
|
|
130
|
+
maxFontSizeMultiplier,
|
|
131
|
+
minFontSizeMultiplier,
|
|
132
|
+
}}
|
|
124
133
|
>
|
|
125
134
|
<View style={[styles.rootContainer, style]}>{children}</View>
|
|
126
135
|
</AvatarContext.Provider>
|
|
@@ -136,8 +145,8 @@ AvatarRoot.displayName = 'Avatar.Root'
|
|
|
136
145
|
type AvatarMaskProps = ViewProps
|
|
137
146
|
|
|
138
147
|
function AvatarMask({ children, ...props }: AvatarMaskProps) {
|
|
139
|
-
const { maxFontSizeMultiplier } = useAvatarContext()
|
|
140
|
-
const styles = useStyles({ maxFontSizeMultiplier })
|
|
148
|
+
const { maxFontSizeMultiplier, minFontSizeMultiplier } = useAvatarContext()
|
|
149
|
+
const styles = useStyles({ maxFontSizeMultiplier, minFontSizeMultiplier })
|
|
141
150
|
|
|
142
151
|
return (
|
|
143
152
|
<View style={styles.mask} {...props}>
|
|
@@ -157,8 +166,8 @@ interface AvatarImageProps extends Omit<ImageProps, 'source' | 'alt'> {
|
|
|
157
166
|
}
|
|
158
167
|
|
|
159
168
|
function AvatarImage({ sourceUri, ...props }: AvatarImageProps) {
|
|
160
|
-
const { size, maxFontSizeMultiplier } = useAvatarContext()
|
|
161
|
-
const fontScale = useFontScale({ maxFontSizeMultiplier })
|
|
169
|
+
const { size, maxFontSizeMultiplier, minFontSizeMultiplier } = useAvatarContext()
|
|
170
|
+
const fontScale = useFontScale({ maxFontSizeMultiplier, minFontSizeMultiplier })
|
|
162
171
|
const scaledAvatarSize = AVATAR_PX[size] * fontScale
|
|
163
172
|
|
|
164
173
|
return <Image source={{ uri: sourceUri }} loaderSize={scaledAvatarSize} {...props} alt="" />
|
|
@@ -183,9 +192,9 @@ interface AvatarImageFallbackProps {
|
|
|
183
192
|
}
|
|
184
193
|
|
|
185
194
|
function AvatarImageFallback({ name = 'general.person' }: AvatarImageFallbackProps) {
|
|
186
|
-
const { size, maxFontSizeMultiplier } = useAvatarContext()
|
|
187
|
-
const styles = useStyles({ maxFontSizeMultiplier })
|
|
188
|
-
const fontScale = useFontScale({ maxFontSizeMultiplier })
|
|
195
|
+
const { size, maxFontSizeMultiplier, minFontSizeMultiplier } = useAvatarContext()
|
|
196
|
+
const styles = useStyles({ maxFontSizeMultiplier, minFontSizeMultiplier })
|
|
197
|
+
const fontScale = useFontScale({ maxFontSizeMultiplier, minFontSizeMultiplier })
|
|
189
198
|
const scaledIconSize = AVATAR_FALLBACK_ICON_PX[size] * fontScale
|
|
190
199
|
|
|
191
200
|
return (
|
|
@@ -213,8 +222,8 @@ interface AvatarGroupProps {
|
|
|
213
222
|
type AvatarIndex = 0 | 1 | 2 | 3
|
|
214
223
|
|
|
215
224
|
function AvatarGroup({ sourceUris }: AvatarGroupProps) {
|
|
216
|
-
const { setAllImagesLoaded, maxFontSizeMultiplier } = useAvatarContext()
|
|
217
|
-
const styles = useStyles({ maxFontSizeMultiplier })
|
|
225
|
+
const { setAllImagesLoaded, maxFontSizeMultiplier, minFontSizeMultiplier } = useAvatarContext()
|
|
226
|
+
const styles = useStyles({ maxFontSizeMultiplier, minFontSizeMultiplier })
|
|
218
227
|
const [loadingStatus, setLoadingStatus] = useState<Record<AvatarIndex, boolean>>({
|
|
219
228
|
0: false,
|
|
220
229
|
1: false,
|
|
@@ -323,9 +332,9 @@ AvatarGroup.displayName = 'Avatar.Group'
|
|
|
323
332
|
// =================================
|
|
324
333
|
|
|
325
334
|
function AvatarGroupLoader() {
|
|
326
|
-
const { size, allImagesLoaded, maxFontSizeMultiplier } = useAvatarContext()
|
|
327
|
-
const styles = useStyles({ size, maxFontSizeMultiplier })
|
|
328
|
-
const fontScale = useFontScale({ maxFontSizeMultiplier })
|
|
335
|
+
const { size, allImagesLoaded, maxFontSizeMultiplier, minFontSizeMultiplier } = useAvatarContext()
|
|
336
|
+
const styles = useStyles({ size, maxFontSizeMultiplier, minFontSizeMultiplier })
|
|
337
|
+
const fontScale = useFontScale({ maxFontSizeMultiplier, minFontSizeMultiplier })
|
|
329
338
|
const scaledSpinnerSize = AVATAR_PX[size] * fontScale
|
|
330
339
|
|
|
331
340
|
if (allImagesLoaded) return null
|
|
@@ -348,8 +357,8 @@ interface AvatarPresenceProps extends ViewProps {
|
|
|
348
357
|
}
|
|
349
358
|
|
|
350
359
|
function AvatarPresence({ presence, ...props }: AvatarPresenceProps) {
|
|
351
|
-
const { size, maxFontSizeMultiplier } = useAvatarContext()
|
|
352
|
-
const styles = useStyles({ size, presence, maxFontSizeMultiplier })
|
|
360
|
+
const { size, maxFontSizeMultiplier, minFontSizeMultiplier } = useAvatarContext()
|
|
361
|
+
const styles = useStyles({ size, presence, maxFontSizeMultiplier, minFontSizeMultiplier })
|
|
353
362
|
|
|
354
363
|
return <View style={styles.presence} {...props} />
|
|
355
364
|
}
|
|
@@ -364,15 +373,17 @@ interface Styles {
|
|
|
364
373
|
size?: AvatarSize
|
|
365
374
|
presence?: AvatarPresenceType
|
|
366
375
|
maxFontSizeMultiplier?: number
|
|
376
|
+
minFontSizeMultiplier?: number
|
|
367
377
|
}
|
|
368
378
|
|
|
369
379
|
const useStyles = ({
|
|
370
380
|
size = 'md',
|
|
371
381
|
presence = 'offline',
|
|
372
382
|
maxFontSizeMultiplier = MAX_FONT_SIZE_MULTIPLIER,
|
|
383
|
+
minFontSizeMultiplier = undefined,
|
|
373
384
|
}: Styles = {}) => {
|
|
374
385
|
const { colors } = useTheme()
|
|
375
|
-
const fontScale = useFontScale({ maxFontSizeMultiplier })
|
|
386
|
+
const fontScale = useFontScale({ maxFontSizeMultiplier, minFontSizeMultiplier })
|
|
376
387
|
const PRESENCE_COLOR = {
|
|
377
388
|
online: colors.fillColorInteractionOnlineDefault,
|
|
378
389
|
offline: colors.iconColorDefaultDisabled,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import DeviceInfo from 'react-native-device-info'
|
|
2
|
+
|
|
3
|
+
export type AppName = 'chat' | 'churchcenter' | 'services'
|
|
4
|
+
|
|
5
|
+
export const useAppName = (): AppName => {
|
|
6
|
+
const applicationName = DeviceInfo.getApplicationName()
|
|
7
|
+
|
|
8
|
+
if (/churchcenter/i.test(applicationName)) {
|
|
9
|
+
return 'churchcenter'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (/services/i.test(applicationName)) {
|
|
13
|
+
return 'services'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return 'chat'
|
|
17
|
+
}
|
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import { useMutation } from '@tanstack/react-query'
|
|
2
2
|
import { useApiClient } from './use_api_client'
|
|
3
|
-
import DeviceInfo from 'react-native-device-info'
|
|
4
|
-
const brand = DeviceInfo.getBrand()
|
|
5
|
-
const model = DeviceInfo.getModel()
|
|
6
|
-
const systemName = DeviceInfo.getSystemName()
|
|
7
|
-
const systemVersion = DeviceInfo.getSystemVersion()
|
|
8
|
-
const readableVersion = DeviceInfo.getReadableVersion()
|
|
9
|
-
const appName = DeviceInfo.getApplicationName()
|
|
10
3
|
|
|
11
4
|
export const useReportBugAction = () => {
|
|
12
5
|
const apiClient = useApiClient()
|
|
@@ -18,7 +11,7 @@ export const useReportBugAction = () => {
|
|
|
18
11
|
attachmentIds,
|
|
19
12
|
}: {
|
|
20
13
|
description: string
|
|
21
|
-
description_json: string
|
|
14
|
+
description_json: Record<string, any>
|
|
22
15
|
attachmentIds: string[]
|
|
23
16
|
}) => {
|
|
24
17
|
return apiClient.chat.post({
|
|
@@ -28,8 +21,7 @@ export const useReportBugAction = () => {
|
|
|
28
21
|
type: '',
|
|
29
22
|
attributes: {
|
|
30
23
|
description,
|
|
31
|
-
description_json,
|
|
32
|
-
device_info: `${appName}/${readableVersion} (${brand}, ${model}, ${systemName}, ${systemVersion})`,
|
|
24
|
+
description_json: JSON.stringify(description_json),
|
|
33
25
|
attachment_ids: attachmentIds,
|
|
34
26
|
},
|
|
35
27
|
},
|
package/src/navigation/index.tsx
CHANGED
|
@@ -4,47 +4,50 @@ import {
|
|
|
4
4
|
createNativeStackNavigator,
|
|
5
5
|
NativeStackHeaderRightProps,
|
|
6
6
|
} from '@react-navigation/native-stack'
|
|
7
|
+
import { CardStyleInterpolators } from '@react-navigation/stack'
|
|
7
8
|
import React from 'react'
|
|
9
|
+
import { Platform } from 'react-native'
|
|
8
10
|
import { Icon } from '../components'
|
|
11
|
+
import { HeaderTextButton } from '../components/display/platform_modal_header_buttons'
|
|
12
|
+
import {
|
|
13
|
+
AttachmentActionsScreen,
|
|
14
|
+
AttachmentActionsScreenOptions,
|
|
15
|
+
} from '../screens/attachment_actions/attachment_actions_screen'
|
|
16
|
+
import { BugReportScreen, BugReportScreenOptions } from '../screens/bug_report_screen'
|
|
17
|
+
import {
|
|
18
|
+
MessageReadReceiptsScreen,
|
|
19
|
+
MessageReadReceiptsScreenOptions,
|
|
20
|
+
} from '../screens/conversation/message_read_receipts_screen'
|
|
9
21
|
import { ConversationDetailsScreen } from '../screens/conversation_details_screen'
|
|
22
|
+
import {
|
|
23
|
+
ConversationFilterReceipientsScreenOptions,
|
|
24
|
+
ConversationFilterRecipientsScreen,
|
|
25
|
+
} from '../screens/conversation_filter_recipients/conversation_filter_recipients_screen'
|
|
26
|
+
import { ConversationFiltersParams } from '../screens/conversation_filters/screen_props'
|
|
27
|
+
import {
|
|
28
|
+
ConversationFiltersScreen,
|
|
29
|
+
ConversationFiltersScreenOptions,
|
|
30
|
+
} from '../screens/conversation_filters_screen'
|
|
31
|
+
import { ConversationNewScreen } from '../screens/conversation_new/conversation_new_screen'
|
|
10
32
|
import {
|
|
11
33
|
ConversationRouteProps,
|
|
12
34
|
ConversationScreen,
|
|
13
35
|
ConversationScreenTitle,
|
|
14
36
|
} from '../screens/conversation_screen'
|
|
15
|
-
import {
|
|
16
|
-
import { ConversationNewScreen } from '../screens/conversation_new/conversation_new_screen'
|
|
17
|
-
import {
|
|
18
|
-
ConversationFilterReceipientsScreenOptions,
|
|
19
|
-
ConversationFilterRecipientsScreen,
|
|
20
|
-
} from '../screens/conversation_filter_recipients/conversation_filter_recipients_screen'
|
|
37
|
+
import { ConversationSelectGroupRecipientsScreen } from '../screens/conversation_select_recipients/conversation_select_group_recipients_screen'
|
|
21
38
|
import { ConversationSelectRecipientsScreen } from '../screens/conversation_select_recipients/conversation_select_recipients_screen'
|
|
39
|
+
import { ConversationSelectTeamsILeadRecipientsScreen } from '../screens/conversation_select_recipients/conversation_select_teams_i_lead_recipients_screen'
|
|
40
|
+
import { ConversationsScreen } from '../screens/conversations/conversations_screen'
|
|
41
|
+
import { GetHelpScreen } from '../screens/get_help_screen'
|
|
22
42
|
import {
|
|
23
43
|
MessageActionsScreen,
|
|
24
44
|
MessageActionsScreenOptions,
|
|
25
45
|
} from '../screens/message_actions_screen'
|
|
26
|
-
import { SendGiphyScreen, SendGiphyScreenOptions } from '../screens/send_giphy_screen'
|
|
27
46
|
import { NotFound } from '../screens/not_found'
|
|
28
47
|
import { ReactionsScreen, ReactionsScreenOptions } from '../screens/reactions_screen'
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
ConversationFiltersScreen,
|
|
32
|
-
ConversationFiltersScreenOptions,
|
|
33
|
-
} from '../screens/conversation_filters_screen'
|
|
34
|
-
import { ConversationFiltersParams } from '../screens/conversation_filters/screen_props'
|
|
35
|
-
import { ConversationSelectGroupRecipientsScreen } from '../screens/conversation_select_recipients/conversation_select_group_recipients_screen'
|
|
36
|
-
import { ConversationSelectTeamsILeadRecipientsScreen } from '../screens/conversation_select_recipients/conversation_select_teams_i_lead_recipients_screen'
|
|
37
|
-
import { AttachmentActionsScreenOptions } from '../screens/attachment_actions/attachment_actions_screen'
|
|
38
|
-
import { AttachmentActionsScreen } from '../screens/attachment_actions/attachment_actions_screen'
|
|
39
|
-
import { BugReportScreen, BugReportScreenOptions } from '../screens/bug_report_screen'
|
|
40
|
-
import {
|
|
41
|
-
MessageReadReceiptsScreen,
|
|
42
|
-
MessageReadReceiptsScreenOptions,
|
|
43
|
-
} from '../screens/conversation/message_read_receipts_screen'
|
|
44
|
-
import { Platform } from 'react-native'
|
|
45
|
-
import { HeaderTextButton } from '../components/display/platform_modal_header_buttons'
|
|
48
|
+
import { SendGiphyScreen, SendGiphyScreenOptions } from '../screens/send_giphy_screen'
|
|
46
49
|
import { TeamConversationScreen } from '../screens/team_conversation_screen'
|
|
47
|
-
import {
|
|
50
|
+
import { ScreenLayout } from './screenLayout'
|
|
48
51
|
|
|
49
52
|
const HEADER_BACK_BUTTON_LAYOUT_RESET_STYLES = {
|
|
50
53
|
marginLeft: Platform.select({ ios: -8, default: -3 }),
|
|
@@ -231,6 +234,16 @@ export const ChatStack = createNativeStackNavigator({
|
|
|
231
234
|
screen: BugReportScreen,
|
|
232
235
|
options: BugReportScreenOptions,
|
|
233
236
|
},
|
|
237
|
+
GetHelp: {
|
|
238
|
+
screen: GetHelpScreen,
|
|
239
|
+
options: ({ navigation }) => ({
|
|
240
|
+
headerTitle: 'Get help',
|
|
241
|
+
presentation: 'modal',
|
|
242
|
+
headerLeft: props => (
|
|
243
|
+
<HeaderTextButton {...props} onPress={navigation.goBack} title="Close" />
|
|
244
|
+
),
|
|
245
|
+
}),
|
|
246
|
+
},
|
|
234
247
|
NotFound: {
|
|
235
248
|
screen: NotFound,
|
|
236
249
|
options: {
|