@planningcenter/chat-react-native 3.18.0-rc.7 → 3.18.0-rc.9

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 (51) hide show
  1. package/build/components/conversation/message.d.ts.map +1 -1
  2. package/build/components/conversation/message.js +21 -11
  3. package/build/components/conversation/message.js.map +1 -1
  4. package/build/components/conversation/message_form.d.ts.map +1 -1
  5. package/build/components/conversation/message_form.js +2 -4
  6. package/build/components/conversation/message_form.js.map +1 -1
  7. package/build/components/conversation/messages_disabled_banners.d.ts +3 -0
  8. package/build/components/conversation/messages_disabled_banners.d.ts.map +1 -0
  9. package/build/components/conversation/messages_disabled_banners.js +53 -0
  10. package/build/components/conversation/messages_disabled_banners.js.map +1 -0
  11. package/build/components/conversation/typing_indicator.d.ts +1 -5
  12. package/build/components/conversation/typing_indicator.d.ts.map +1 -1
  13. package/build/components/conversation/typing_indicator.js +2 -2
  14. package/build/components/conversation/typing_indicator.js.map +1 -1
  15. package/build/contexts/conversation_context.d.ts +13 -0
  16. package/build/contexts/conversation_context.d.ts.map +1 -0
  17. package/build/contexts/conversation_context.js +14 -0
  18. package/build/contexts/conversation_context.js.map +1 -0
  19. package/build/hooks/use_broadcast_typing_status.d.ts +1 -1
  20. package/build/hooks/use_broadcast_typing_status.d.ts.map +1 -1
  21. package/build/hooks/use_broadcast_typing_status.js +7 -3
  22. package/build/hooks/use_broadcast_typing_status.js.map +1 -1
  23. package/build/hooks/use_typing_indicators.d.ts +1 -1
  24. package/build/hooks/use_typing_indicators.d.ts.map +1 -1
  25. package/build/hooks/use_typing_indicators.js +16 -3
  26. package/build/hooks/use_typing_indicators.js.map +1 -1
  27. package/build/screens/conversation_details_screen.d.ts.map +1 -1
  28. package/build/screens/conversation_details_screen.js +6 -2
  29. package/build/screens/conversation_details_screen.js.map +1 -1
  30. package/build/screens/conversation_screen.d.ts.map +1 -1
  31. package/build/screens/conversation_screen.js +11 -4
  32. package/build/screens/conversation_screen.js.map +1 -1
  33. package/build/types/jolt_events/typing_events.d.ts +1 -0
  34. package/build/types/jolt_events/typing_events.d.ts.map +1 -1
  35. package/build/types/jolt_events/typing_events.js.map +1 -1
  36. package/package.json +2 -2
  37. package/src/components/conversation/message.tsx +32 -15
  38. package/src/components/conversation/message_form.tsx +2 -9
  39. package/src/components/conversation/messages_disabled_banners.tsx +69 -0
  40. package/src/components/conversation/typing_indicator.tsx +2 -6
  41. package/src/contexts/conversation_context.tsx +34 -0
  42. package/src/hooks/use_broadcast_typing_status.ts +7 -3
  43. package/src/hooks/use_typing_indicators.ts +15 -3
  44. package/src/screens/conversation_details_screen.tsx +6 -2
  45. package/src/screens/conversation_screen.tsx +20 -6
  46. package/src/types/jolt_events/typing_events.ts +1 -0
  47. package/build/components/conversation/disabled_replies_banners.d.ts +0 -3
  48. package/build/components/conversation/disabled_replies_banners.d.ts.map +0 -1
  49. package/build/components/conversation/disabled_replies_banners.js +0 -41
  50. package/build/components/conversation/disabled_replies_banners.js.map +0 -1
  51. package/src/components/conversation/disabled_replies_banners.tsx +0 -58
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planningcenter/chat-react-native",
3
- "version": "3.18.0-rc.7",
3
+ "version": "3.18.0-rc.9",
4
4
  "description": "",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -58,5 +58,5 @@
58
58
  "react-native-url-polyfill": "^2.0.0",
59
59
  "typescript": "<5.6.0"
60
60
  },
61
- "gitHead": "6d7c028cd363cb5e85d262ff1e8f9df72f1cd9e7"
61
+ "gitHead": "1c8ef808381f80f84eba2890e1bbfc706574c69d"
62
62
  }
@@ -80,7 +80,6 @@ export function Message({
80
80
  const isReplyRootMessage = message.replyRootId === message.id
81
81
  const isDeletedReplyRootMessage = isReplyRootMessage && !!message.deletedAt
82
82
 
83
- const messageText = isDeletedReplyRootMessage ? 'Message deleted' : text
84
83
  const replyCountText = pluralize(message.replyCount, 'reply')
85
84
  const messagePendingLabel = isPersisted ? 'Saving' : 'Sending'
86
85
  const replyRootAuthorName = message.replyRootId
@@ -118,6 +117,10 @@ export function Message({
118
117
  }
119
118
  }
120
119
 
120
+ const handleMessagePress = () => {
121
+ setShowMessageMetaToggle(!showMessageMetaToggle)
122
+ }
123
+
121
124
  const handleMessageLongPress = () => {
122
125
  if (!isPersisted) return
123
126
 
@@ -130,6 +133,7 @@ export function Message({
130
133
  reply_root_author_name: replyRootAuthorName,
131
134
  })
132
135
  }
136
+
133
137
  const handleReactionLongPress = (reaction: ReactionCountResource) => {
134
138
  Haptic.impactLight()
135
139
  navigation.navigate('Reactions', {
@@ -162,11 +166,12 @@ export function Message({
162
166
  return (
163
167
  <Pressable
164
168
  onLongPress={handleMessageLongPress}
165
- onPress={() => setShowMessageMetaToggle(!showMessageMetaToggle)}
169
+ onPress={handleMessagePress}
166
170
  onPressIn={handleMessagePressIn}
167
171
  onPressOut={handleMessagePressOut}
168
172
  android_ripple={{ color: colors.androidRippleNeutral, borderless: false, foreground: true }}
169
173
  accessibilityHint="Long press to view message actions like reacting and copying."
174
+ disabled={isDeletedReplyRootMessage}
170
175
  >
171
176
  <Animated.View style={[styles.message, animatedBackgroundColor]}>
172
177
  {!message.mine && (
@@ -190,7 +195,7 @@ export function Message({
190
195
  </View>
191
196
  )}
192
197
  <View style={[styles.messageContent, { marginBottom: messageBottomMargin }]}>
193
- {renderAuthor && (
198
+ {renderAuthor && !isDeletedReplyRootMessage && (
194
199
  <Text variant="footnote" style={styles.authorName}>
195
200
  {message.author.name}
196
201
  </Text>
@@ -199,18 +204,26 @@ export function Message({
199
204
  style={styles.messageBubble}
200
205
  onLayout={e => setMessageBubbleHeight(e.nativeEvent.layout.height)}
201
206
  >
202
- <ErrorBoundary>
203
- <MessageAttachments
204
- attachments={message.attachments}
205
- metaProps={metaProps}
206
- onMessageAttachmentLongPress={handleMessageAttachmentLongPress}
207
- onMessageLongPress={handleMessageLongPress}
208
- />
209
- </ErrorBoundary>
210
- {messageText && (
207
+ {isDeletedReplyRootMessage ? (
211
208
  <View style={styles.messageText}>
212
- <MessageMarkdown text={messageText} />
209
+ <Text style={styles.replyRootDeletedText}>Message deleted</Text>
213
210
  </View>
211
+ ) : (
212
+ <>
213
+ <ErrorBoundary>
214
+ <MessageAttachments
215
+ attachments={message.attachments}
216
+ metaProps={metaProps}
217
+ onMessageAttachmentLongPress={handleMessageAttachmentLongPress}
218
+ onMessageLongPress={handleMessageLongPress}
219
+ />
220
+ </ErrorBoundary>
221
+ {text && (
222
+ <View style={styles.messageText}>
223
+ <MessageMarkdown text={text} />
224
+ </View>
225
+ )}
226
+ </>
214
227
  )}
215
228
  </View>
216
229
  {showReplyCountButton && (
@@ -224,7 +237,7 @@ export function Message({
224
237
  {replyCountText}
225
238
  </TextButton>
226
239
  )}
227
- {hasReactions && (
240
+ {hasReactions && !isDeletedReplyRootMessage && (
228
241
  <View style={styles.messageReactions}>
229
242
  {reactionCounts.map(reaction => (
230
243
  <MessageReaction
@@ -237,7 +250,7 @@ export function Message({
237
250
  ))}
238
251
  </View>
239
252
  )}
240
- {showMessageMeta && (
253
+ {showMessageMeta && !isDeletedReplyRootMessage && (
241
254
  <View style={styles.messageMeta}>
242
255
  {message.mine && !pending && !error && (
243
256
  <MessageReadReceipts
@@ -365,5 +378,9 @@ const useMessageStyles = ({ mine }: MessageResource) => {
365
378
  errorText: {
366
379
  color: colors.statusErrorText,
367
380
  },
381
+ replyRootDeletedText: {
382
+ color: colors.textColorDefaultSecondary,
383
+ fontStyle: 'italic',
384
+ },
368
385
  })
369
386
  }
@@ -1,9 +1,4 @@
1
- import {
2
- RouteProp,
3
- useNavigation,
4
- useTheme as useNavigationTheme,
5
- useRoute,
6
- } from '@react-navigation/native'
1
+ import { useNavigation, useTheme as useNavigationTheme, useRoute } from '@react-navigation/native'
7
2
  import React, { useCallback, useContext, useEffect, useState } from 'react'
8
3
  import {
9
4
  Platform,
@@ -319,9 +314,7 @@ function MessageFormInput() {
319
314
  React.useContext(MessageFormContext)
320
315
  const attachmentError = attachmentUploader?.errorMessage
321
316
 
322
- const route = useRoute<RouteProp<ConversationScreenProps['route']>>()
323
- const conversationId = route.params.conversation_id
324
- const broadcastTypingStatus = useBroadcastTypingStatus(conversationId)
317
+ const broadcastTypingStatus = useBroadcastTypingStatus()
325
318
 
326
319
  const handleTextChange = (newText: string) => {
327
320
  setText(newText)
@@ -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
+ }
@@ -41,16 +41,12 @@ const TypingDots = () => {
41
41
  )
42
42
  }
43
43
 
44
- interface TypingIndicatorProps {
45
- conversationId: number
46
- }
47
-
48
44
  /**
49
45
  * Component to display typing indicators in a conversation
50
46
  * Shows "X is typing..." with animated dots
51
47
  */
52
- export const TypingIndicator = ({ conversationId }: TypingIndicatorProps) => {
53
- const typingPeople = useTypingIndicators(conversationId)
48
+ export const TypingIndicator = () => {
49
+ const typingPeople = useTypingIndicators()
54
50
  const styles = useStyles()
55
51
  const enabled = typingPeople.length > 0
56
52
 
@@ -0,0 +1,34 @@
1
+ import React, { createContext, PropsWithChildren, useContext, useMemo } from 'react'
2
+
3
+ interface ConversationContextValue {
4
+ conversationId: number
5
+ currentPageReplyRootId: string | null
6
+ }
7
+
8
+ interface ConversationContextProviderProps extends PropsWithChildren {
9
+ conversationId: number
10
+ currentPageReplyRootId: string | null
11
+ }
12
+
13
+ const ConversationContext = createContext<ConversationContextValue>({
14
+ conversationId: 0,
15
+ currentPageReplyRootId: null,
16
+ })
17
+
18
+ export const ConversationContextProvider = ({
19
+ children,
20
+ conversationId,
21
+ currentPageReplyRootId,
22
+ }: ConversationContextProviderProps) => {
23
+ const value = useMemo(
24
+ () => ({
25
+ conversationId,
26
+ currentPageReplyRootId,
27
+ }),
28
+ [conversationId, currentPageReplyRootId]
29
+ )
30
+
31
+ return <ConversationContext.Provider value={value}>{children}</ConversationContext.Provider>
32
+ }
33
+
34
+ export const useConversationContext = () => useContext(ConversationContext)
@@ -1,5 +1,6 @@
1
1
  import { useCallback, useRef } from 'react'
2
2
  import { useApiClient } from './use_api_client'
3
+ import { useConversationContext } from '../contexts/conversation_context'
3
4
 
4
5
  const THROTTLE_INTERVAL = 3000 // 3 seconds
5
6
 
@@ -10,7 +11,8 @@ const THROTTLE_INTERVAL = 3000 // 3 seconds
10
11
  * after receiving a typing event. This is how we can show a steady typing indicator even
11
12
  * if the user types once every 2.9 seconds.
12
13
  */
13
- export const useBroadcastTypingStatus = (conversationId: string | number) => {
14
+ export const useBroadcastTypingStatus = () => {
15
+ const { conversationId, currentPageReplyRootId } = useConversationContext()
14
16
  const apiClient = useApiClient()
15
17
  const lastBroadcastTime = useRef<number>(0)
16
18
 
@@ -26,12 +28,14 @@ export const useBroadcastTypingStatus = (conversationId: string | number) => {
26
28
  apiClient.chat
27
29
  .post({
28
30
  url: `/me/conversations/${conversationId}/broadcast_typing_status`,
29
- data: { data: { type: 'TypingStatus', attributes: {} } },
31
+ data: {
32
+ data: { type: 'TypingStatus', attributes: { reply_root_id: currentPageReplyRootId } },
33
+ },
30
34
  })
31
35
  .catch(error => {
32
36
  console.error('Failed to broadcast typing status:', error)
33
37
  })
34
- }, [apiClient, conversationId])
38
+ }, [apiClient.chat, conversationId, currentPageReplyRootId])
35
39
 
36
40
  return broadcastTypingStatus
37
41
  }
@@ -2,6 +2,7 @@ import { useQuery } from '@tanstack/react-query'
2
2
  import { useMemo } from 'react'
3
3
  import { PersonTyping } from './use_typing_status_cache'
4
4
  import { useCurrentPerson } from './use_current_person'
5
+ import { useConversationContext } from '../contexts/conversation_context'
5
6
 
6
7
  /**
7
8
  * Hook for getting people currently typing in a conversation
@@ -9,9 +10,12 @@ import { useCurrentPerson } from './use_current_person'
9
10
  * The query function itself doesn't do anything, but we add to the cache
10
11
  * from useTypingStatusCache when we receive a typing event.
11
12
  */
12
- export const useTypingIndicators = (conversationId: number) => {
13
+ export const useTypingIndicators = () => {
14
+ const { conversationId, currentPageReplyRootId } = useConversationContext()
13
15
  const cacheKey = useMemo(() => ['conversationTyping', String(conversationId)], [conversationId])
14
16
  const currentPerson = useCurrentPerson()
17
+ const isCurrentPerson = (authorId: number) => authorId === currentPerson?.id
18
+ const inMainConversationView = !currentPageReplyRootId
15
19
  const now = Date.now()
16
20
  const { data } = useQuery({
17
21
  queryKey: cacheKey,
@@ -19,8 +23,16 @@ export const useTypingIndicators = (conversationId: number) => {
19
23
  initialData: stableArray,
20
24
  })
21
25
 
22
- // Filter out expired entries and the current user
23
- return data.filter(person => person.expires > now && person.author_id !== currentPerson?.id)
26
+ return data.filter(({ author_id, expires, reply_root_id }) => {
27
+ if (isCurrentPerson(author_id)) return false
28
+ if (now > expires) return false
29
+
30
+ // If you are in the main conversation view, you will see any message sent
31
+ if (inMainConversationView) return true
32
+
33
+ // If you are in a reply view, you will only see messages sent in this reply thread
34
+ return reply_root_id === currentPageReplyRootId
35
+ })
24
36
  }
25
37
 
26
38
  /**
@@ -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'
@@ -36,6 +36,7 @@ import { useConversationJoltEvents } from '../hooks/use_conversation_jolt_events
36
36
  import { JumpToBottomButton } from '../components/conversation/jump_to_bottom_button'
37
37
  import { ReplyShadowMessage } from '../components/conversation/reply_shadow_message'
38
38
  import { availableFeatures, useFeatures } from '../hooks/use_features'
39
+ import { ConversationContextProvider } from '../contexts/conversation_context'
39
40
 
40
41
  export type ConversationRouteProps = {
41
42
  conversation_id: number
@@ -53,6 +54,19 @@ export type ConversationRouteProps = {
53
54
  export type ConversationScreenProps = StaticScreenProps<ConversationRouteProps>
54
55
 
55
56
  export function ConversationScreen({ route }: ConversationScreenProps) {
57
+ const { conversation_id, reply_root_id } = route.params
58
+
59
+ return (
60
+ <ConversationContextProvider
61
+ conversationId={conversation_id}
62
+ currentPageReplyRootId={reply_root_id ?? null}
63
+ >
64
+ <ConversationScreenContent route={route} />
65
+ </ConversationContextProvider>
66
+ )
67
+ }
68
+
69
+ function ConversationScreenContent({ route }: ConversationScreenProps) {
56
70
  const styles = useStyles()
57
71
  const navigation = useNavigation()
58
72
  const { conversation_id, editing_message_id, reply_root_id, reply_root_author_name } =
@@ -179,8 +193,8 @@ export function ConversationScreen({ route }: ConversationScreenProps) {
179
193
  />
180
194
  )}
181
195
  <JumpToBottomButton onPress={handleReturnToBottom} visible={showJumpToBottomButton} />
182
- {!noMessages && <TypingIndicator conversationId={conversation_id} />}
183
- {showLeaderDisabledReplyBanner && <LeaderDisabledRepliesBanner />}
196
+ {!noMessages && <TypingIndicator />}
197
+ {showLeaderDisabledReplyBanner && <LeaderMessagesDisabledBanner />}
184
198
  {canReply ? (
185
199
  <MessageForm.Root
186
200
  replyRootAuthorFirstName={replyRootAuthorFirstName}
@@ -201,7 +215,7 @@ export function ConversationScreen({ route }: ConversationScreenProps) {
201
215
  <MessageForm.SubmitButton />
202
216
  </MessageForm.Root>
203
217
  ) : (
204
- <MemberDisabledRepliesBanner />
218
+ <MemberMessagesDisabledBanner />
205
219
  )}
206
220
  </KeyboardView>
207
221
  </View>
@@ -13,4 +13,5 @@ export interface TypingBroadcastDataAttributes {
13
13
  author_id: number
14
14
  author_name: string
15
15
  id: string
16
+ reply_root_id: string | null
16
17
  }
@@ -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
- }