@planningcenter/chat-react-native 3.18.0-rc.8 → 3.18.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 (37) 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/messages_disabled_banners.d.ts +3 -0
  5. package/build/components/conversation/messages_disabled_banners.d.ts.map +1 -0
  6. package/build/components/conversation/messages_disabled_banners.js +53 -0
  7. package/build/components/conversation/messages_disabled_banners.js.map +1 -0
  8. package/build/components/conversation/reply_shadow_message.d.ts.map +1 -1
  9. package/build/components/conversation/reply_shadow_message.js +8 -3
  10. package/build/components/conversation/reply_shadow_message.js.map +1 -1
  11. package/build/hooks/use_conversation_messages.d.ts.map +1 -1
  12. package/build/hooks/use_conversation_messages.js +2 -1
  13. package/build/hooks/use_conversation_messages.js.map +1 -1
  14. package/build/screens/age_check/age_check_required_screen.js +1 -1
  15. package/build/screens/age_check/age_check_required_screen.js.map +1 -1
  16. package/build/screens/age_check/components/age_check_select_birthdate_modal.js +2 -2
  17. package/build/screens/age_check/components/age_check_select_birthdate_modal.js.map +1 -1
  18. package/build/screens/conversation_details_screen.d.ts.map +1 -1
  19. package/build/screens/conversation_details_screen.js +6 -2
  20. package/build/screens/conversation_details_screen.js.map +1 -1
  21. package/build/screens/conversation_screen.d.ts.map +1 -1
  22. package/build/screens/conversation_screen.js +21 -11
  23. package/build/screens/conversation_screen.js.map +1 -1
  24. package/package.json +2 -2
  25. package/src/components/conversation/message.tsx +40 -11
  26. package/src/components/conversation/messages_disabled_banners.tsx +69 -0
  27. package/src/components/conversation/reply_shadow_message.tsx +9 -2
  28. package/src/hooks/use_conversation_messages.ts +3 -1
  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_details_screen.tsx +6 -2
  32. package/src/screens/conversation_screen.tsx +26 -13
  33. package/build/components/conversation/disabled_replies_banners.d.ts +0 -3
  34. package/build/components/conversation/disabled_replies_banners.d.ts.map +0 -1
  35. package/build/components/conversation/disabled_replies_banners.js +0 -41
  36. package/build/components/conversation/disabled_replies_banners.js.map +0 -1
  37. package/src/components/conversation/disabled_replies_banners.tsx +0 -58
@@ -1,6 +1,12 @@
1
1
  import { useNavigation } from '@react-navigation/native'
2
2
  import React, { useEffect } from 'react'
3
- import { Pressable, StyleSheet, useWindowDimensions, View } from 'react-native'
3
+ import {
4
+ AccessibilityActionEvent,
5
+ Pressable,
6
+ StyleSheet,
7
+ useWindowDimensions,
8
+ View,
9
+ } from 'react-native'
4
10
  import { MessageReaction } from '../../components/conversation/message_reaction'
5
11
  import { Avatar, Icon, Spinner, Text, TextButton, TextInlineButton } from '../../components/display'
6
12
  import {
@@ -27,6 +33,7 @@ import { Haptic } from '../../utils/native_adapters'
27
33
  import { TheirReplyConnector, MyReplyConnector, AVATAR_CONNECTOR_SPACING } from './reply_connectors'
28
34
  import { pluralize } from '../../utils'
29
35
  import { useConversationMessage } from '../../hooks/use_conversation_message'
36
+ import { some } from 'lodash'
30
37
  import { isNewMessage } from '../../utils/cache/messages_cache'
31
38
 
32
39
  /** Message
@@ -48,7 +55,7 @@ export function Message({
48
55
  repliesEnabled,
49
56
  ...message
50
57
  }: MessageProps) {
51
- const { text, reactionCounts, pending, error } = message
58
+ const { text, reactionCounts, pending, error, attachments, author } = message
52
59
  const styles = useMessageStyles(message)
53
60
  const navigation = useNavigation()
54
61
  const { colors } = useTheme()
@@ -70,7 +77,7 @@ export function Message({
70
77
  })
71
78
 
72
79
  const metaProps = {
73
- authorName: message.author.name,
80
+ authorName: author.name,
74
81
  createdAt: message.createdAt,
75
82
  }
76
83
 
@@ -79,12 +86,12 @@ export function Message({
79
86
  !inReplyScreen && message.replyRootId === message.id && repliesEnabled
80
87
  const isReplyRootMessage = message.replyRootId === message.id
81
88
  const isDeletedReplyRootMessage = isReplyRootMessage && !!message.deletedAt
89
+ const replyToReplyRootMessage = repliesEnabled && !isReplyRootMessage && !!message.replyRootId
82
90
 
83
91
  const replyCountText = pluralize(message.replyCount, 'reply')
84
92
  const messagePendingLabel = isPersisted ? 'Saving' : 'Sending'
85
- const replyRootAuthorName = message.replyRootId
86
- ? replyRootMessage?.author.name
87
- : message.author.name
93
+ const replyRootAuthorName = message.replyRootId ? replyRootMessage?.author.name : author.name
94
+ const messageText = isDeletedReplyRootMessage ? 'Message deleted' : text
88
95
 
89
96
  const messageBottomMargin =
90
97
  message.lastInGroup || message.nextIsReplyShadowMessage
@@ -93,6 +100,11 @@ export function Message({
93
100
  ? 8
94
101
  : 4
95
102
 
103
+ const messageIsReplyLabel = replyToReplyRootMessage ? 'Reply' : ''
104
+ const attachmentLabel = some(attachments) ? pluralize(attachments.length, 'attachment') : ''
105
+ const replyCountLabel = isReplyRootMessage ? replyCountText : ''
106
+ const accessibilityLabel = `${author?.name || ''} ${messageIsReplyLabel} ${attachmentLabel} ${messageText || ''} ${timestamp} ${replyCountLabel}`
107
+
96
108
  useEffect(() => {
97
109
  if (pending) {
98
110
  const timer = setTimeout(() => {
@@ -159,10 +171,23 @@ export function Message({
159
171
  navigation.navigate('ConversationReply', {
160
172
  conversation_id,
161
173
  reply_root_id: message.id,
162
- reply_root_author_name: message.author.name,
174
+ reply_root_author_name: author.name,
163
175
  })
164
176
  }
165
177
 
178
+ const accessibilityActions = [
179
+ {
180
+ name: 'navigateToReplies',
181
+ label: 'Navigate to replies',
182
+ },
183
+ ]
184
+
185
+ const handleAccessibilityAction = (event: AccessibilityActionEvent) => {
186
+ if (event.nativeEvent.actionName === 'navigateToReplies') {
187
+ handleNavigateToReplyPress()
188
+ }
189
+ }
190
+
166
191
  return (
167
192
  <Pressable
168
193
  onLongPress={handleMessageLongPress}
@@ -170,7 +195,11 @@ export function Message({
170
195
  onPressIn={handleMessagePressIn}
171
196
  onPressOut={handleMessagePressOut}
172
197
  android_ripple={{ color: colors.androidRippleNeutral, borderless: false, foreground: true }}
198
+ accessibilityRole="button"
199
+ accessibilityLabel={accessibilityLabel}
173
200
  accessibilityHint="Long press to view message actions like reacting and copying."
201
+ accessibilityActions={isReplyRootMessage ? accessibilityActions : undefined}
202
+ onAccessibilityAction={isReplyRootMessage ? handleAccessibilityAction : undefined}
174
203
  disabled={isDeletedReplyRootMessage}
175
204
  >
176
205
  <Animated.View style={[styles.message, animatedBackgroundColor]}>
@@ -179,7 +208,7 @@ export function Message({
179
208
  {renderAuthor ? (
180
209
  <Avatar
181
210
  size={'md'}
182
- sourceUri={message.author.avatar}
211
+ sourceUri={author.avatar}
183
212
  style={styles.avatar}
184
213
  maxFontSizeMultiplier={1}
185
214
  minFontSizeMultiplier={1}
@@ -197,7 +226,7 @@ export function Message({
197
226
  <View style={[styles.messageContent, { marginBottom: messageBottomMargin }]}>
198
227
  {renderAuthor && !isDeletedReplyRootMessage && (
199
228
  <Text variant="footnote" style={styles.authorName}>
200
- {message.author.name}
229
+ {author.name}
201
230
  </Text>
202
231
  )}
203
232
  <View
@@ -206,13 +235,13 @@ export function Message({
206
235
  >
207
236
  {isDeletedReplyRootMessage ? (
208
237
  <View style={styles.messageText}>
209
- <Text style={styles.replyRootDeletedText}>Message deleted</Text>
238
+ <Text style={styles.replyRootDeletedText}>{messageText}</Text>
210
239
  </View>
211
240
  ) : (
212
241
  <>
213
242
  <ErrorBoundary>
214
243
  <MessageAttachments
215
- attachments={message.attachments}
244
+ attachments={attachments}
216
245
  metaProps={metaProps}
217
246
  onMessageAttachmentLongPress={handleMessageAttachmentLongPress}
218
247
  onMessageLongPress={handleMessageLongPress}
@@ -0,0 +1,69 @@
1
+ import { StyleSheet, View, type ViewStyle } from 'react-native'
2
+ import { useTheme } from '../../hooks'
3
+ import { Text } from '../display'
4
+ import { useSafeAreaInsets } from 'react-native-safe-area-context'
5
+ import { useFeatures } from '../../hooks/use_features'
6
+ import { availableFeatures } from '../../hooks/use_features'
7
+
8
+ export const LeaderMessagesDisabledBanner = () => {
9
+ const { featureEnabled } = useFeatures()
10
+ const repliesEnabled = featureEnabled(availableFeatures.threaded_replies)
11
+
12
+ const description = repliesEnabled
13
+ ? 'Only leaders can send messages in this conversation.'
14
+ : 'Replies are frozen for everyone else.'
15
+
16
+ return <MessagesDisabledBanner description={description} />
17
+ }
18
+
19
+ export const MemberMessagesDisabledBanner = () => {
20
+ const styles = useStyles()
21
+ const { featureEnabled } = useFeatures()
22
+ const repliesEnabled = featureEnabled(availableFeatures.threaded_replies)
23
+
24
+ const description = repliesEnabled
25
+ ? 'Only leaders can send messages, but you can still add reactions.'
26
+ : 'Replies have been disabled by a leader, but you can still add reactions.'
27
+
28
+ return <MessagesDisabledBanner description={description} style={styles.memberBanner} />
29
+ }
30
+
31
+ interface MessagesDisabledBannerProps {
32
+ description: string
33
+ style?: ViewStyle
34
+ }
35
+
36
+ const MessagesDisabledBanner = ({ description, style }: MessagesDisabledBannerProps) => {
37
+ const styles = useStyles()
38
+
39
+ return (
40
+ <View style={[styles.baseBanner, style]}>
41
+ <Text style={styles.text} variant="tertiary">
42
+ {description}
43
+ </Text>
44
+ </View>
45
+ )
46
+ }
47
+
48
+ const useStyles = () => {
49
+ const { colors } = useTheme()
50
+ const { bottom } = useSafeAreaInsets()
51
+
52
+ return StyleSheet.create({
53
+ baseBanner: {
54
+ paddingHorizontal: 16,
55
+ paddingVertical: 4,
56
+ backgroundColor: colors.statusNeutralComposedBackground,
57
+ borderTopWidth: 1,
58
+ borderTopColor: colors.borderColorDefaultBase,
59
+ },
60
+ text: {
61
+ textAlign: 'center',
62
+ },
63
+ memberBanner: {
64
+ paddingTop: 16,
65
+ paddingBottom: 16 + bottom,
66
+ marginBottom: -bottom,
67
+ },
68
+ })
69
+ }
@@ -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]
@@ -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"
@@ -44,6 +44,8 @@ import { HeaderTextButton } from '../components/display/platform_modal_header_bu
44
44
  import { tokens } from '../vendor/tapestry/tokens'
45
45
  import { ButtonAppearanceUnion } from '../components/display/utils/button_colors'
46
46
  import { GroupResource } from '../types/resources/group_resource'
47
+ import { useFeatures } from '../hooks/use_features'
48
+ import { availableFeatures } from '../hooks/use_features'
47
49
 
48
50
  // =========================================
49
51
  // ====== Factory Constants & Types ========
@@ -93,6 +95,8 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
93
95
  const { repliesDisabled, setRepliesDisabled } = useConversationDisableReplies(route.params)
94
96
  const { mutate: saveTitle } = useConversationUpdate(route.params)
95
97
  const { mutate: deleteConversation } = useConversationDelete(route.params)
98
+ const { featureEnabled } = useFeatures()
99
+ const repliesEnabled = featureEnabled(availableFeatures.threaded_replies)
96
100
 
97
101
  const trimmedTitle = title.trim()
98
102
  const emptyTitle = trimmedTitle === '' || title === null
@@ -250,8 +254,8 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
250
254
  {
251
255
  type: canUpdate ? SectionTypes.setting : SectionTypes.hidden,
252
256
  data: {
253
- title: 'Freeze conversation',
254
- subtitle: 'Disables replies for everyone except leaders.',
257
+ title: repliesEnabled ? 'Leader messages only' : 'Freeze conversation',
258
+ subtitle: repliesEnabled ? undefined : 'Disables replies for everyone except leaders.',
255
259
  rightItem: (
256
260
  <Switch value={repliesDisabled} onChange={() => setRepliesDisabled(!repliesDisabled)} />
257
261
  ),
@@ -14,9 +14,9 @@ import { FlatList, Platform, StyleSheet, View } from 'react-native'
14
14
  import { useSafeAreaInsets } from 'react-native-safe-area-context'
15
15
  import { Badge, Icon, Text } from '../components'
16
16
  import {
17
- LeaderDisabledRepliesBanner,
18
- MemberDisabledRepliesBanner,
19
- } from '../components/conversation/disabled_replies_banners'
17
+ LeaderMessagesDisabledBanner,
18
+ MemberMessagesDisabledBanner,
19
+ } from '../components/conversation/messages_disabled_banners'
20
20
  import { EmptyConversationBlankState } from '../components/conversation/empty_conversation_blank_state'
21
21
  import BlankState from '../components/primitive/blank_state_primitive'
22
22
  import { Message } from '../components/conversation/message'
@@ -194,7 +194,7 @@ function ConversationScreenContent({ route }: ConversationScreenProps) {
194
194
  )}
195
195
  <JumpToBottomButton onPress={handleReturnToBottom} visible={showJumpToBottomButton} />
196
196
  {!noMessages && <TypingIndicator />}
197
- {showLeaderDisabledReplyBanner && <LeaderDisabledRepliesBanner />}
197
+ {showLeaderDisabledReplyBanner && <LeaderMessagesDisabledBanner />}
198
198
  {canReply ? (
199
199
  <MessageForm.Root
200
200
  replyRootAuthorFirstName={replyRootAuthorFirstName}
@@ -215,7 +215,7 @@ function ConversationScreenContent({ route }: ConversationScreenProps) {
215
215
  <MessageForm.SubmitButton />
216
216
  </MessageForm.Root>
217
217
  ) : (
218
- <MemberDisabledRepliesBanner />
218
+ <MemberMessagesDisabledBanner />
219
219
  )}
220
220
  </KeyboardView>
221
221
  </View>
@@ -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
@@ -1,3 +0,0 @@
1
- export declare const LeaderDisabledRepliesBanner: () => import("react").JSX.Element;
2
- export declare const MemberDisabledRepliesBanner: () => import("react").JSX.Element;
3
- //# sourceMappingURL=disabled_replies_banners.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"disabled_replies_banners.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/disabled_replies_banners.tsx"],"names":[],"mappings":"AAKA,eAAO,MAAM,2BAA2B,mCAEvC,CAAA;AAED,eAAO,MAAM,2BAA2B,mCAQvC,CAAA"}
@@ -1,41 +0,0 @@
1
- import { StyleSheet, View } from 'react-native';
2
- import { useTheme } from '../../hooks';
3
- import { Text } from '../display';
4
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
5
- export const LeaderDisabledRepliesBanner = () => {
6
- return <DisabledRepliesBanner description="Replies are frozen for everyone else."/>;
7
- };
8
- export const MemberDisabledRepliesBanner = () => {
9
- const styles = useStyles();
10
- return (<DisabledRepliesBanner description="Replies have been disabled by a leader, but you can still add reactions." style={styles.memberBanner}/>);
11
- };
12
- const DisabledRepliesBanner = ({ description, style }) => {
13
- const styles = useStyles();
14
- return (<View style={[styles.baseBanner, style]}>
15
- <Text style={styles.text} variant="tertiary">
16
- {description}
17
- </Text>
18
- </View>);
19
- };
20
- const useStyles = () => {
21
- const { colors } = useTheme();
22
- const { bottom } = useSafeAreaInsets();
23
- return StyleSheet.create({
24
- baseBanner: {
25
- paddingHorizontal: 16,
26
- paddingVertical: 4,
27
- backgroundColor: colors.statusNeutralComposedBackground,
28
- borderTopWidth: 1,
29
- borderTopColor: colors.borderColorDefaultBase,
30
- },
31
- text: {
32
- textAlign: 'center',
33
- },
34
- memberBanner: {
35
- paddingTop: 16,
36
- paddingBottom: 16 + bottom,
37
- marginBottom: -bottom,
38
- },
39
- });
40
- };
41
- //# sourceMappingURL=disabled_replies_banners.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"disabled_replies_banners.js","sourceRoot":"","sources":["../../../src/components/conversation/disabled_replies_banners.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,IAAI,EAAkB,MAAM,cAAc,CAAA;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAElE,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,EAAE;IAC9C,OAAO,CAAC,qBAAqB,CAAC,WAAW,CAAC,uCAAuC,EAAG,CAAA;AACtF,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,EAAE;IAC9C,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,OAAO,CACL,CAAC,qBAAqB,CACpB,WAAW,CAAC,0EAA0E,CACtF,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,EAC3B,CACH,CAAA;AACH,CAAC,CAAA;AAOD,MAAM,qBAAqB,GAAG,CAAC,EAAE,WAAW,EAAE,KAAK,EAA8B,EAAE,EAAE;IACnF,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CACtC;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,CAC1C;QAAA,CAAC,WAAW,CACd;MAAA,EAAE,IAAI,CACR;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAC7B,MAAM,EAAE,MAAM,EAAE,GAAG,iBAAiB,EAAE,CAAA;IAEtC,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,UAAU,EAAE;YACV,iBAAiB,EAAE,EAAE;YACrB,eAAe,EAAE,CAAC;YAClB,eAAe,EAAE,MAAM,CAAC,+BAA+B;YACvD,cAAc,EAAE,CAAC;YACjB,cAAc,EAAE,MAAM,CAAC,sBAAsB;SAC9C;QACD,IAAI,EAAE;YACJ,SAAS,EAAE,QAAQ;SACpB;QACD,YAAY,EAAE;YACZ,UAAU,EAAE,EAAE;YACd,aAAa,EAAE,EAAE,GAAG,MAAM;YAC1B,YAAY,EAAE,CAAC,MAAM;SACtB;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import { StyleSheet, View, type ViewStyle } from 'react-native'\nimport { useTheme } from '../../hooks'\nimport { Text } from '../display'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\n\nexport const LeaderDisabledRepliesBanner = () => {\n return <DisabledRepliesBanner description=\"Replies are frozen for everyone else.\" />\n}\n\nexport const MemberDisabledRepliesBanner = () => {\n const styles = useStyles()\n return (\n <DisabledRepliesBanner\n description=\"Replies have been disabled by a leader, but you can still add reactions.\"\n style={styles.memberBanner}\n />\n )\n}\n\ninterface DisabledRepliesBannerProps {\n description: string\n style?: ViewStyle\n}\n\nconst DisabledRepliesBanner = ({ description, style }: DisabledRepliesBannerProps) => {\n const styles = useStyles()\n\n return (\n <View style={[styles.baseBanner, style]}>\n <Text style={styles.text} variant=\"tertiary\">\n {description}\n </Text>\n </View>\n )\n}\n\nconst useStyles = () => {\n const { colors } = useTheme()\n const { bottom } = useSafeAreaInsets()\n\n return StyleSheet.create({\n baseBanner: {\n paddingHorizontal: 16,\n paddingVertical: 4,\n backgroundColor: colors.statusNeutralComposedBackground,\n borderTopWidth: 1,\n borderTopColor: colors.borderColorDefaultBase,\n },\n text: {\n textAlign: 'center',\n },\n memberBanner: {\n paddingTop: 16,\n paddingBottom: 16 + bottom,\n marginBottom: -bottom,\n },\n })\n}\n"]}
@@ -1,58 +0,0 @@
1
- import { StyleSheet, View, type ViewStyle } from 'react-native'
2
- import { useTheme } from '../../hooks'
3
- import { Text } from '../display'
4
- import { useSafeAreaInsets } from 'react-native-safe-area-context'
5
-
6
- export const LeaderDisabledRepliesBanner = () => {
7
- return <DisabledRepliesBanner description="Replies are frozen for everyone else." />
8
- }
9
-
10
- export const MemberDisabledRepliesBanner = () => {
11
- const styles = useStyles()
12
- return (
13
- <DisabledRepliesBanner
14
- description="Replies have been disabled by a leader, but you can still add reactions."
15
- style={styles.memberBanner}
16
- />
17
- )
18
- }
19
-
20
- interface DisabledRepliesBannerProps {
21
- description: string
22
- style?: ViewStyle
23
- }
24
-
25
- const DisabledRepliesBanner = ({ description, style }: DisabledRepliesBannerProps) => {
26
- const styles = useStyles()
27
-
28
- return (
29
- <View style={[styles.baseBanner, style]}>
30
- <Text style={styles.text} variant="tertiary">
31
- {description}
32
- </Text>
33
- </View>
34
- )
35
- }
36
-
37
- const useStyles = () => {
38
- const { colors } = useTheme()
39
- const { bottom } = useSafeAreaInsets()
40
-
41
- return StyleSheet.create({
42
- baseBanner: {
43
- paddingHorizontal: 16,
44
- paddingVertical: 4,
45
- backgroundColor: colors.statusNeutralComposedBackground,
46
- borderTopWidth: 1,
47
- borderTopColor: colors.borderColorDefaultBase,
48
- },
49
- text: {
50
- textAlign: 'center',
51
- },
52
- memberBanner: {
53
- paddingTop: 16,
54
- paddingBottom: 16 + bottom,
55
- marginBottom: -bottom,
56
- },
57
- })
58
- }