@planningcenter/chat-react-native 3.18.0-rc.9 → 3.19.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.
Files changed (31) hide show
  1. package/build/components/conversation/message.d.ts.map +1 -1
  2. package/build/components/conversation/message.js +28 -12
  3. package/build/components/conversation/message.js.map +1 -1
  4. package/build/components/conversation/message_form.js +1 -1
  5. package/build/components/conversation/message_form.js.map +1 -1
  6. package/build/components/conversation/reply_shadow_message.d.ts.map +1 -1
  7. package/build/components/conversation/reply_shadow_message.js +8 -3
  8. package/build/components/conversation/reply_shadow_message.js.map +1 -1
  9. package/build/hooks/use_conversation_messages.d.ts.map +1 -1
  10. package/build/hooks/use_conversation_messages.js +2 -1
  11. package/build/hooks/use_conversation_messages.js.map +1 -1
  12. package/build/hooks/use_message_draft.d.ts +1 -1
  13. package/build/hooks/use_message_draft.d.ts.map +1 -1
  14. package/build/hooks/use_message_draft.js +6 -2
  15. package/build/hooks/use_message_draft.js.map +1 -1
  16. package/build/screens/age_check/age_check_required_screen.js +1 -1
  17. package/build/screens/age_check/age_check_required_screen.js.map +1 -1
  18. package/build/screens/age_check/components/age_check_select_birthdate_modal.js +2 -2
  19. package/build/screens/age_check/components/age_check_select_birthdate_modal.js.map +1 -1
  20. package/build/screens/conversation_screen.d.ts.map +1 -1
  21. package/build/screens/conversation_screen.js +18 -8
  22. package/build/screens/conversation_screen.js.map +1 -1
  23. package/package.json +2 -2
  24. package/src/components/conversation/message.tsx +40 -11
  25. package/src/components/conversation/message_form.tsx +1 -1
  26. package/src/components/conversation/reply_shadow_message.tsx +9 -2
  27. package/src/hooks/use_conversation_messages.ts +3 -1
  28. package/src/hooks/use_message_draft.ts +6 -2
  29. package/src/screens/age_check/age_check_required_screen.tsx +1 -1
  30. package/src/screens/age_check/components/age_check_select_birthdate_modal.tsx +2 -0
  31. package/src/screens/conversation_screen.tsx +21 -8
@@ -25,6 +25,8 @@ import { TheirReplyConnector, MyReplyConnector } from './reply_connectors'
25
25
  import { assertKeysAreNumbers, pluralize } from '../../utils'
26
26
  import { useNavigation } from '@react-navigation/native'
27
27
  import { useConversationMessage } from '../../hooks/use_conversation_message'
28
+ import { useLiveRelativeTime } from '../../hooks/use_live_relative_time'
29
+ import { some } from 'lodash'
28
30
 
29
31
  interface ReplyShadowMessageProps extends MessageResource {
30
32
  messageId: string
@@ -61,10 +63,11 @@ interface ShadowMessageContentProps extends MessageResource {
61
63
  }
62
64
 
63
65
  function ShadowMessageContent({ conversation_id, ...message }: ShadowMessageContentProps) {
64
- const { text, deletedAt } = message
66
+ const { text, deletedAt, author, attachments } = message
65
67
  const styles = useStyles(message)
66
68
  const { colors } = useTheme()
67
69
  const navigation = useNavigation()
70
+ const timestamp = useLiveRelativeTime(message.createdAt)
68
71
 
69
72
  const [messageBubbleHeight, setMessageBubbleHeight] = React.useState(0)
70
73
  const { animatedBackgroundColor, handleMessagePressIn, handleMessagePressOut } =
@@ -82,12 +85,16 @@ function ShadowMessageContent({ conversation_id, ...message }: ShadowMessageCont
82
85
  })
83
86
  }
84
87
 
88
+ const attachmentLabel = some(attachments) ? pluralize(attachments.length, 'attachment') : ''
89
+ const accessibilityLabel = `${author?.name || ''} Reply Preview ${attachmentLabel} ${messageText || ''} ${timestamp} ${replyCountText}`
90
+
85
91
  return (
86
92
  <Pressable
87
93
  android_ripple={{ color: colors.androidRippleNeutral }}
88
94
  onPress={handleNavigateToReplies}
89
95
  onPressIn={handleMessagePressIn}
90
96
  onPressOut={handleMessagePressOut}
97
+ accessibilityLabel={accessibilityLabel}
91
98
  accessibilityHint="Navigate to reply screen for this message"
92
99
  accessibilityRole="link"
93
100
  >
@@ -112,7 +119,7 @@ function ShadowMessageContent({ conversation_id, ...message }: ShadowMessageCont
112
119
  style={styles.messageBubble}
113
120
  onLayout={e => setMessageBubbleHeight(e.nativeEvent.layout.height)}
114
121
  >
115
- <MessageAttachmentImagery attachments={message.attachments} />
122
+ <MessageAttachmentImagery attachments={attachments} />
116
123
  {text && (
117
124
  <Text
118
125
  variant="footnote"
@@ -16,7 +16,9 @@ export const useConversationMessages = (
16
16
  () =>
17
17
  data
18
18
  .filter(
19
- message => !message.deletedAt && (message.attachments?.length || message.text?.length)
19
+ message =>
20
+ (!message.deletedAt || message.replyRootId) &&
21
+ (message.attachments?.length || message.text?.length)
20
22
  )
21
23
  .sort((a, b) => -a.id.localeCompare(b.id)),
22
24
  [data]
@@ -1,6 +1,7 @@
1
1
  import { useCallback, useEffect, useRef, useState } from 'react'
2
2
  import { useAsyncStorage } from './use_async_storage'
3
3
  import type { FileAttachment } from '../types/resources/denormalized_attachment_resource_for_create'
4
+ import { useConversationContext } from '../contexts/conversation_context'
4
5
 
5
6
  interface MessageDraft {
6
7
  text: string
@@ -14,8 +15,11 @@ const DRAFT_EXPIRY_MS = DRAFT_EXPIRY_HOURS * 60 * 60 * 1000
14
15
  const ATTACHMENT_EXPIRY_HOURS = 48 // 2 days
15
16
  const ATTACHMENT_EXPIRY_MS = ATTACHMENT_EXPIRY_HOURS * 60 * 60 * 1000
16
17
 
17
- export function useMessageDraft(conversationId: number) {
18
- const conversationKey = conversationId.toString()
18
+ export function useMessageDraft() {
19
+ const { conversationId, currentPageReplyRootId } = useConversationContext()
20
+ const conversationKey = currentPageReplyRootId
21
+ ? `${conversationId}/threads/${currentPageReplyRootId}`
22
+ : String(conversationId)
19
23
  const [allDrafts, setAllDrafts] = useAsyncStorage<Record<string, MessageDraft>>(
20
24
  DRAFT_STORAGE_KEY,
21
25
  {}
@@ -30,7 +30,7 @@ export function AgeCheckRequiredScreen() {
30
30
  const styles = useStyles()
31
31
 
32
32
  const birthdateStamp = birthdate
33
- ? formatDate(birthdate, { style: 'standard', year: true })
33
+ ? formatDate(birthdate, { style: 'standard', year: true, timeZone: 'UTC' })
34
34
  : 'Missing'
35
35
 
36
36
  const age = birthdate ? calculateAge(birthdate) : null
@@ -65,6 +65,7 @@ function IOSBirthdateModal({
65
65
  </Text>
66
66
  <View style={styles.pickerContainer}>
67
67
  <DateTimePicker
68
+ timeZoneName="UTC"
68
69
  accessibilityLabelledBy="birthdateLabel"
69
70
  testID="age-check-date-picker"
70
71
  mode="date"
@@ -101,6 +102,7 @@ function AndroidBirthdatePicker({
101
102
 
102
103
  return (
103
104
  <DateTimePicker
105
+ timeZoneName="UTC"
104
106
  testID="age-check-date-picker-android"
105
107
  mode="date"
106
108
  display="spinner"
@@ -310,6 +310,24 @@ export const groupMessages = ({
310
310
  message.replyRootId &&
311
311
  !threadRoot &&
312
312
  (prevMessageDifferentThread || prevMessageIsDateSeparator)
313
+ const lastInGroup =
314
+ !nextMessage ||
315
+ nextMessageDifferentAuthor ||
316
+ nextMessageMoreThan5Minutes ||
317
+ nextMessageDifferentThread ||
318
+ nextMessageIsDateSeparator
319
+ const renderAuthor =
320
+ !message.mine &&
321
+ (!prevMessage ||
322
+ prevMessageDifferentAuthor ||
323
+ prevMessageMoreThan5Minutes ||
324
+ prevMessageDifferentThread ||
325
+ prevMessageIsDateSeparator)
326
+ const nextIsReplyShadowMessage =
327
+ repliesEnabled &&
328
+ nextMessageInThread &&
329
+ !nextMessageThreadRoot &&
330
+ (nextMessageDifferentThread || nextMessageIsDateSeparator)
313
331
 
314
332
  if (message.mine && !encounteredOneOfMyMessages) {
315
333
  encounteredOneOfMyMessages = true
@@ -317,17 +335,12 @@ export const groupMessages = ({
317
335
  } else {
318
336
  message.myLatestInConversation = false
319
337
  }
320
- message.lastInGroup = !nextMessage || nextMessageDifferentAuthor || nextMessageMoreThan5Minutes
321
- message.renderAuthor =
322
- !message.mine && (!prevMessage || prevMessageDifferentAuthor || prevMessageMoreThan5Minutes)
338
+ message.lastInGroup = lastInGroup
339
+ message.renderAuthor = renderAuthor
323
340
  message.threadPosition = null
324
341
  message.nextRendersAuthor = nextMessage?.renderAuthor
325
342
  message.isReplyShadowMessage = false
326
- message.nextIsReplyShadowMessage =
327
- repliesEnabled &&
328
- nextMessageInThread &&
329
- !nextMessageThreadRoot &&
330
- (nextMessageDifferentThread || nextMessageIsDateSeparator)
343
+ message.nextIsReplyShadowMessage = nextIsReplyShadowMessage
331
344
 
332
345
  if (!inReplyScreen && inThread) {
333
346
  message.prevIsMyReply = prevMessage?.mine