@planningcenter/chat-react-native 3.14.0-rc.5 → 3.15.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 (81) hide show
  1. package/build/components/conversations/conversation_preview.d.ts.map +1 -1
  2. package/build/components/conversations/conversation_preview.js +18 -12
  3. package/build/components/conversations/conversation_preview.js.map +1 -1
  4. package/build/components/display/action_button.d.ts.map +1 -1
  5. package/build/components/display/action_button.js +3 -2
  6. package/build/components/display/action_button.js.map +1 -1
  7. package/build/components/display/badge.js +5 -5
  8. package/build/components/display/badge.js.map +1 -1
  9. package/build/components/display/platform_modal_header_buttons.d.ts +4 -4
  10. package/build/components/display/platform_modal_header_buttons.d.ts.map +1 -1
  11. package/build/components/display/platform_modal_header_buttons.js +2 -2
  12. package/build/components/display/platform_modal_header_buttons.js.map +1 -1
  13. package/build/components/display/text.d.ts +10 -2
  14. package/build/components/display/text.d.ts.map +1 -1
  15. package/build/components/display/text.js +0 -3
  16. package/build/components/display/text.js.map +1 -1
  17. package/build/components/display/toggle_button.d.ts.map +1 -1
  18. package/build/components/display/toggle_button.js +2 -2
  19. package/build/components/display/toggle_button.js.map +1 -1
  20. package/build/components/page/error_boundary.d.ts.map +1 -1
  21. package/build/components/page/error_boundary.js +11 -46
  22. package/build/components/page/error_boundary.js.map +1 -1
  23. package/build/components/primitive/avatar_primitive.d.ts.map +1 -1
  24. package/build/components/primitive/avatar_primitive.js +14 -6
  25. package/build/components/primitive/avatar_primitive.js.map +1 -1
  26. package/build/components/primitive/blank_state_primitive.d.ts +5 -2
  27. package/build/components/primitive/blank_state_primitive.d.ts.map +1 -1
  28. package/build/components/primitive/blank_state_primitive.js +6 -1
  29. package/build/components/primitive/blank_state_primitive.js.map +1 -1
  30. package/build/hooks/index.d.ts +1 -0
  31. package/build/hooks/index.d.ts.map +1 -1
  32. package/build/hooks/index.js +1 -0
  33. package/build/hooks/index.js.map +1 -1
  34. package/build/hooks/use_at_font_scale_breakpoint.d.ts +2 -0
  35. package/build/hooks/use_at_font_scale_breakpoint.d.ts.map +1 -0
  36. package/build/hooks/use_at_font_scale_breakpoint.js +9 -0
  37. package/build/hooks/use_at_font_scale_breakpoint.js.map +1 -0
  38. package/build/navigation/index.d.ts.map +1 -1
  39. package/build/navigation/index.js +6 -6
  40. package/build/navigation/index.js.map +1 -1
  41. package/build/screens/bug_report_screen.js +4 -4
  42. package/build/screens/bug_report_screen.js.map +1 -1
  43. package/build/screens/conversation_details_screen.d.ts.map +1 -1
  44. package/build/screens/conversation_details_screen.js +3 -3
  45. package/build/screens/conversation_details_screen.js.map +1 -1
  46. package/build/screens/conversation_new/components/filter_by_plan.js +2 -2
  47. package/build/screens/conversation_new/components/filter_by_plan.js.map +1 -1
  48. package/build/screens/conversations/components/list_header_component.d.ts.map +1 -1
  49. package/build/screens/conversations/components/list_header_component.js +10 -3
  50. package/build/screens/conversations/components/list_header_component.js.map +1 -1
  51. package/build/screens/conversations/conversations_screen.d.ts.map +1 -1
  52. package/build/screens/conversations/conversations_screen.js +2 -2
  53. package/build/screens/conversations/conversations_screen.js.map +1 -1
  54. package/build/utils/styles.d.ts +1 -0
  55. package/build/utils/styles.d.ts.map +1 -1
  56. package/build/utils/styles.js +1 -0
  57. package/build/utils/styles.js.map +1 -1
  58. package/package.json +2 -2
  59. package/src/components/conversations/conversation_preview.tsx +19 -11
  60. package/src/components/display/action_button.tsx +3 -1
  61. package/src/components/display/badge.tsx +5 -5
  62. package/src/components/display/platform_modal_header_buttons.tsx +6 -6
  63. package/src/components/display/text.tsx +30 -2
  64. package/src/components/display/toggle_button.tsx +6 -2
  65. package/src/components/page/error_boundary.tsx +16 -47
  66. package/src/components/primitive/avatar_primitive.tsx +14 -6
  67. package/src/components/primitive/blank_state_primitive.tsx +17 -0
  68. package/src/hooks/index.ts +1 -0
  69. package/src/hooks/use_at_font_scale_breakpoint.ts +11 -0
  70. package/src/navigation/index.tsx +6 -6
  71. package/src/screens/bug_report_screen.tsx +5 -5
  72. package/src/screens/conversation_details_screen.tsx +13 -4
  73. package/src/screens/conversation_new/components/filter_by_plan.tsx +2 -2
  74. package/src/screens/conversations/components/list_header_component.tsx +15 -3
  75. package/src/screens/conversations/conversations_screen.tsx +6 -2
  76. package/src/utils/styles.ts +1 -0
  77. package/build/navigation/header.d.ts +0 -10
  78. package/build/navigation/header.d.ts.map +0 -1
  79. package/build/navigation/header.js +0 -16
  80. package/build/navigation/header.js.map +0 -1
  81. package/src/navigation/header.tsx +0 -24
@@ -5,7 +5,7 @@ import { Conversations, TextButton } from '../../components';
5
5
  import { ActionButton } from '../../components/display/action_button';
6
6
  import { ConversationsContextProvider } from '../../contexts/conversations_context';
7
7
  import { useCanCreateConversations } from '../../hooks';
8
- import { destructureChatGroupGraphId } from '../../utils';
8
+ import { destructureChatGroupGraphId, MAX_FONT_SIZE_MULTIPLIER_LANDMARK } from '../../utils';
9
9
  import { ListHeaderComponent } from './components/list_header_component';
10
10
  export function ConversationsScreen({ route }) {
11
11
  const navigation = useNavigation();
@@ -48,7 +48,7 @@ export function ConversationsScreen({ route }) {
48
48
  <ConversationsContextProvider args={route.params}>
49
49
  <Conversations ListHeaderComponent={ListHeaderComponent}/>
50
50
  </ConversationsContextProvider>
51
- <ActionButton visible={canCreateConversations} title="New conversation" onPress={handleNewConversationNavigation} buttonIconNameLeft="churchCenter.signups" secondaryButton={<TextButton variant="tertiary" onPress={reportABug}>
51
+ <ActionButton visible={canCreateConversations} title="New conversation" onPress={handleNewConversationNavigation} buttonIconNameLeft="churchCenter.signups" secondaryButton={<TextButton variant="tertiary" onPress={reportABug} maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}>
52
52
  Report a bug
53
53
  </TextButton>}/>
54
54
  </View>);
@@ -1 +1 @@
1
- {"version":3,"file":"conversations_screen.js","sourceRoot":"","sources":["../../../src/screens/conversations/conversations_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { StaticScreenProps, useNavigation } from '@react-navigation/native'\nimport React from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { Conversations, TextButton } from '../../components'\nimport { ActionButton } from '../../components/display/action_button'\nimport { ConversationsContextProvider } from '../../contexts/conversations_context'\nimport { useCanCreateConversations } from '../../hooks'\nimport { GraphId } from '../../types/resources/group_resource'\nimport { destructureChatGroupGraphId } from '../../utils'\nimport { ListHeaderComponent } from './components/list_header_component'\nimport { AppName } from '../../types/resources/app_name'\n\nexport type ConversationsScreenProps = StaticScreenProps<{\n title?: string\n chat_group_graph_id?: GraphId\n group_source_app_name?: AppName\n}>\n\nexport function ConversationsScreen({ route }: ConversationsScreenProps) {\n const navigation = useNavigation()\n const canCreateConversations = useCanCreateConversations()\n const styles = useStyles()\n\n const { chat_group_graph_id } = route.params || {}\n const { sourceAppName, sourceId } = destructureChatGroupGraphId(chat_group_graph_id)\n\n const handleNewConversationNavigation = () => {\n if (sourceAppName === 'Services') {\n return navigation.navigate('New', {\n screen: 'ConversationNew',\n params: {\n team_ids: sourceId ? [sourceId] : [],\n source_app_name: sourceAppName,\n ...route.params,\n },\n })\n }\n if (sourceAppName === 'Groups') {\n return navigation.navigate('New', {\n screen: 'ConversationNew',\n params: {\n group_id: sourceId,\n source_app_name: sourceAppName,\n ...route.params,\n },\n })\n }\n\n return navigation.navigate('New', {\n screen: 'ConversationSelectRecipients',\n params: {\n ...route.params,\n },\n })\n }\n\n const reportABug = () => {\n return navigation.navigate('BugReport')\n }\n\n return (\n <View style={styles.container}>\n <ConversationsContextProvider args={route.params}>\n <Conversations ListHeaderComponent={ListHeaderComponent} />\n </ConversationsContextProvider>\n <ActionButton\n visible={canCreateConversations}\n title=\"New conversation\"\n onPress={handleNewConversationNavigation}\n buttonIconNameLeft=\"churchCenter.signups\"\n secondaryButton={\n <TextButton variant=\"tertiary\" onPress={reportABug}>\n Report a bug\n </TextButton>\n }\n />\n </View>\n )\n}\n\nconst useStyles = () => {\n return StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n },\n })\n}\n"]}
1
+ {"version":3,"file":"conversations_screen.js","sourceRoot":"","sources":["../../../src/screens/conversations/conversations_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { StaticScreenProps, useNavigation } from '@react-navigation/native'\nimport React from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { Conversations, TextButton } from '../../components'\nimport { ActionButton } from '../../components/display/action_button'\nimport { ConversationsContextProvider } from '../../contexts/conversations_context'\nimport { useCanCreateConversations } from '../../hooks'\nimport { GraphId } from '../../types/resources/group_resource'\nimport { destructureChatGroupGraphId, MAX_FONT_SIZE_MULTIPLIER_LANDMARK } from '../../utils'\nimport { ListHeaderComponent } from './components/list_header_component'\nimport { AppName } from '../../types/resources/app_name'\n\nexport type ConversationsScreenProps = StaticScreenProps<{\n title?: string\n chat_group_graph_id?: GraphId\n group_source_app_name?: AppName\n}>\n\nexport function ConversationsScreen({ route }: ConversationsScreenProps) {\n const navigation = useNavigation()\n const canCreateConversations = useCanCreateConversations()\n const styles = useStyles()\n\n const { chat_group_graph_id } = route.params || {}\n const { sourceAppName, sourceId } = destructureChatGroupGraphId(chat_group_graph_id)\n\n const handleNewConversationNavigation = () => {\n if (sourceAppName === 'Services') {\n return navigation.navigate('New', {\n screen: 'ConversationNew',\n params: {\n team_ids: sourceId ? [sourceId] : [],\n source_app_name: sourceAppName,\n ...route.params,\n },\n })\n }\n if (sourceAppName === 'Groups') {\n return navigation.navigate('New', {\n screen: 'ConversationNew',\n params: {\n group_id: sourceId,\n source_app_name: sourceAppName,\n ...route.params,\n },\n })\n }\n\n return navigation.navigate('New', {\n screen: 'ConversationSelectRecipients',\n params: {\n ...route.params,\n },\n })\n }\n\n const reportABug = () => {\n return navigation.navigate('BugReport')\n }\n\n return (\n <View style={styles.container}>\n <ConversationsContextProvider args={route.params}>\n <Conversations ListHeaderComponent={ListHeaderComponent} />\n </ConversationsContextProvider>\n <ActionButton\n visible={canCreateConversations}\n title=\"New conversation\"\n onPress={handleNewConversationNavigation}\n buttonIconNameLeft=\"churchCenter.signups\"\n secondaryButton={\n <TextButton\n variant=\"tertiary\"\n onPress={reportABug}\n maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}\n >\n Report a bug\n </TextButton>\n }\n />\n </View>\n )\n}\n\nconst useStyles = () => {\n return StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n },\n })\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  export declare const MAX_FONT_SIZE_MULTIPLIER = 1.5;
2
+ export declare const MAX_FONT_SIZE_MULTIPLIER_LANDMARK = 1.3;
2
3
  export declare const CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL = 16;
3
4
  export declare const platformFontWeightMedium: "500" | "700" | undefined;
4
5
  export declare const platformFontWeightBold: "600" | "700" | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/utils/styles.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,wBAAwB,MAAM,CAAA;AAE3C,eAAO,MAAM,4CAA4C,KAAK,CAAA;AAE9D,eAAO,MAAM,wBAAwB,2BAGnC,CAAA;AAEF,eAAO,MAAM,sBAAsB,2BAGjC,CAAA;AAEF,eAAO,MAAM,2BAA2B;;aAGtC,CAAA"}
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/utils/styles.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,wBAAwB,MAAM,CAAA;AAC3C,eAAO,MAAM,iCAAiC,MAAM,CAAA;AAEpD,eAAO,MAAM,4CAA4C,KAAK,CAAA;AAE9D,eAAO,MAAM,wBAAwB,2BAGnC,CAAA;AAEF,eAAO,MAAM,sBAAsB,2BAGjC,CAAA;AAEF,eAAO,MAAM,2BAA2B;;aAGtC,CAAA"}
@@ -1,6 +1,7 @@
1
1
  import { Platform } from 'react-native';
2
2
  import { tokens } from '../vendor/tapestry/tokens';
3
3
  export const MAX_FONT_SIZE_MULTIPLIER = 1.5;
4
+ export const MAX_FONT_SIZE_MULTIPLIER_LANDMARK = 1.3; // Use in headers, footers, toolbars, etc.
4
5
  export const CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL = 16; // TODO: move to `screens/conversation/utils/styles` when `/screens/conversation` is created
5
6
  export const platformFontWeightMedium = Platform.select({
6
7
  ios: tokens.fontWeightMedium,
@@ -1 +1 @@
1
- {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../src/utils/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAElD,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAA;AAE3C,MAAM,CAAC,MAAM,4CAA4C,GAAG,EAAE,CAAA,CAAC,4FAA4F;AAE3J,MAAM,CAAC,MAAM,wBAAwB,GAAG,QAAQ,CAAC,MAAM,CAAC;IACtD,GAAG,EAAE,MAAM,CAAC,gBAAgB;IAC5B,OAAO,EAAE,MAAM,CAAC,cAAc;CAC/B,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG,QAAQ,CAAC,MAAM,CAAC;IACpD,GAAG,EAAE,MAAM,CAAC,kBAAkB;IAC9B,OAAO,EAAE,MAAM,CAAC,cAAc;CAC/B,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG,QAAQ,CAAC,MAAM,CAAC;IACzD,GAAG,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE;IACrB,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE;CACxB,CAAC,CAAA","sourcesContent":["import { Platform } from 'react-native'\nimport { tokens } from '../vendor/tapestry/tokens'\n\nexport const MAX_FONT_SIZE_MULTIPLIER = 1.5\n\nexport const CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL = 16 // TODO: move to `screens/conversation/utils/styles` when `/screens/conversation` is created\n\nexport const platformFontWeightMedium = Platform.select({\n ios: tokens.fontWeightMedium,\n android: tokens.fontWeightBold,\n})\n\nexport const platformFontWeightBold = Platform.select({\n ios: tokens.fontWeightSemiBold,\n android: tokens.fontWeightBold,\n})\n\nexport const platformPressedOpacityStyle = Platform.select({\n ios: { opacity: 0.5 },\n android: { opacity: 1 },\n})\n"]}
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../src/utils/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAElD,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,CAAA;AAC3C,MAAM,CAAC,MAAM,iCAAiC,GAAG,GAAG,CAAA,CAAC,0CAA0C;AAE/F,MAAM,CAAC,MAAM,4CAA4C,GAAG,EAAE,CAAA,CAAC,4FAA4F;AAE3J,MAAM,CAAC,MAAM,wBAAwB,GAAG,QAAQ,CAAC,MAAM,CAAC;IACtD,GAAG,EAAE,MAAM,CAAC,gBAAgB;IAC5B,OAAO,EAAE,MAAM,CAAC,cAAc;CAC/B,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG,QAAQ,CAAC,MAAM,CAAC;IACpD,GAAG,EAAE,MAAM,CAAC,kBAAkB;IAC9B,OAAO,EAAE,MAAM,CAAC,cAAc;CAC/B,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG,QAAQ,CAAC,MAAM,CAAC;IACzD,GAAG,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE;IACrB,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE;CACxB,CAAC,CAAA","sourcesContent":["import { Platform } from 'react-native'\nimport { tokens } from '../vendor/tapestry/tokens'\n\nexport const MAX_FONT_SIZE_MULTIPLIER = 1.5\nexport const MAX_FONT_SIZE_MULTIPLIER_LANDMARK = 1.3 // Use in headers, footers, toolbars, etc.\n\nexport const CONVERSATION_MESSAGE_LIST_PADDING_HORIZONTAL = 16 // TODO: move to `screens/conversation/utils/styles` when `/screens/conversation` is created\n\nexport const platformFontWeightMedium = Platform.select({\n ios: tokens.fontWeightMedium,\n android: tokens.fontWeightBold,\n})\n\nexport const platformFontWeightBold = Platform.select({\n ios: tokens.fontWeightSemiBold,\n android: tokens.fontWeightBold,\n})\n\nexport const platformPressedOpacityStyle = Platform.select({\n ios: { opacity: 0.5 },\n android: { opacity: 1 },\n})\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planningcenter/chat-react-native",
3
- "version": "3.14.0-rc.5",
3
+ "version": "3.15.0-rc.0",
4
4
  "description": "",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -55,5 +55,5 @@
55
55
  "react-native-url-polyfill": "^2.0.0",
56
56
  "typescript": "<5.6.0"
57
57
  },
58
- "gitHead": "9ff44909158b5a0d22c6cd6ba729b85b5b782040"
58
+ "gitHead": "dc18b2159bfddbee7a105fc0b975ac2d371293c0"
59
59
  }
@@ -3,7 +3,7 @@ import { StyleSheet, View, ViewStyle } from 'react-native'
3
3
  import { ConversationResource } from '../../types'
4
4
  import { AvatarGroup, Heading, Text, Badge, type BadgeProps } from '../display'
5
5
  import { formatDatePreview } from '../../utils/date'
6
- import { useTheme } from '../../hooks'
6
+ import { useTheme, useAtFontScaleBreakpoint } from '../../hooks'
7
7
  import { UnreadCountBadge } from './unread_count_badge'
8
8
  import { ConversationActions } from './conversation_actions'
9
9
  import { MuteIndicator } from './mute_indicator'
@@ -39,6 +39,7 @@ export const ConversationPreview = ({
39
39
  const hasAvatarUrls = previewAvatarUrls && previewAvatarUrls.length > 0
40
40
  const shouldShowFallback = emptyConversation || !hasAvatarUrls
41
41
  const fallbackIconName = emptyConversation ? 'people.noTextMessage' : 'general.person'
42
+ const hasMetaContent = lastMessageCreatedAt || unreadCount > 0 || muted
42
43
 
43
44
  const conversationPreviewText = lastMessageTextPreview
44
45
  ? `${lastMessageAuthorName}: ${lastMessageTextPreview}`
@@ -75,13 +76,15 @@ export const ConversationPreview = ({
75
76
  </Text>
76
77
  <ConversationBadges visible={showBadges} badges={badges} />
77
78
  </View>
78
- <View style={styles.metaContainer}>
79
- <Text variant="tertiary">{formatDatePreview(lastMessageCreatedAt)}</Text>
80
- <View style={styles.statusContainer}>
81
- <UnreadCountBadge count={unreadCount} showDot={muted} />
82
- <MuteIndicator muted={muted} />
79
+ {hasMetaContent && (
80
+ <View style={styles.metaContainer}>
81
+ <Text variant="tertiary">{formatDatePreview(lastMessageCreatedAt)}</Text>
82
+ <View style={styles.statusContainer}>
83
+ <UnreadCountBadge count={unreadCount} showDot={muted} />
84
+ <MuteIndicator muted={muted} />
85
+ </View>
83
86
  </View>
84
- </View>
87
+ )}
85
88
  </ConversationActions>
86
89
  )
87
90
  }
@@ -179,13 +182,16 @@ const getConversationAccessibilityLabel = ({
179
182
 
180
183
  const useStyles = () => {
181
184
  const { colors } = useTheme()
185
+ const atFontScaleBreakpoint = useAtFontScaleBreakpoint()
182
186
 
183
187
  return StyleSheet.create({
184
188
  previewRow: {
185
- flexDirection: 'row',
189
+ flexDirection: atFontScaleBreakpoint ? 'column' : 'row',
186
190
  gap: 8,
187
191
  borderBottomWidth: 1,
188
- borderBottomColor: colors.borderColorDefaultDim,
192
+ borderBottomColor: atFontScaleBreakpoint
193
+ ? colors.borderColorDefaultDark
194
+ : colors.borderColorDefaultDim,
189
195
  paddingTop: 12,
190
196
  paddingBottom: 12,
191
197
  paddingHorizontal: 16,
@@ -214,8 +220,10 @@ const useStyles = () => {
214
220
  borderRadius: 4,
215
221
  },
216
222
  metaContainer: {
217
- rowGap: 4,
218
- alignItems: 'flex-end',
223
+ gap: 4,
224
+ alignItems: atFontScaleBreakpoint ? 'center' : 'flex-end',
225
+ justifyContent: atFontScaleBreakpoint ? 'space-between' : 'flex-start',
226
+ flexDirection: atFontScaleBreakpoint ? 'row' : 'column',
219
227
  },
220
228
  dateLoading: {
221
229
  width: 60,
@@ -6,6 +6,7 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context'
6
6
  import { useTheme } from '../../hooks'
7
7
  import { Text } from './text'
8
8
  import { IconString } from './icon'
9
+ import { MAX_FONT_SIZE_MULTIPLIER_LANDMARK } from '../../utils'
9
10
 
10
11
  export const ActionButton = ({
11
12
  visible = true,
@@ -56,13 +57,14 @@ export const ActionButton = ({
56
57
  style={secondaryButton ? null : styles.fullWidthButton}
57
58
  iconNameLeft={buttonIconNameLeft}
58
59
  loading={loading}
60
+ maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}
59
61
  />
60
62
  </View>
61
63
  </Animated.View>
62
64
  )
63
65
  }
64
66
 
65
- const SCALE_THAT_BUTTONS_WRAP = 1.2
67
+ const SCALE_THAT_BUTTONS_WRAP = 1.15
66
68
 
67
69
  const useStyles = () => {
68
70
  const { fontScale } = useWindowDimensions()
@@ -175,9 +175,9 @@ const useStyles = ({
175
175
 
176
176
  const statusColorMap = useStatusColorAppearanceMap()
177
177
 
178
- const badgePaddingHorizontal = 8 * fontScale
179
- const badgePaddingVertical = 4 * fontScale
180
178
  const badgeGap = 4 * fontScale
179
+ const badgePaddingHorizontal = 8
180
+ const badgePaddingVertical = 4
181
181
  const badgeFontSize = 12
182
182
 
183
183
  const variantStylesMap: VariantStyles = {
@@ -188,7 +188,7 @@ const useStyles = ({
188
188
  paddingHorizontal: badgePaddingHorizontal,
189
189
  paddingVertical: badgePaddingVertical,
190
190
  borderWidth: tokens.borderSizeDefault * fontScale,
191
- borderRadius: tokens.borderRadiusMd,
191
+ borderRadius: tokens.borderRadiusMd * fontScale,
192
192
  textColor: statusColorMap[appearance].text,
193
193
  fontWeight: 'normal',
194
194
  },
@@ -199,7 +199,7 @@ const useStyles = ({
199
199
  paddingHorizontal: badgePaddingHorizontal,
200
200
  paddingVertical: badgePaddingVertical,
201
201
  borderWidth: tokens.borderSizeDefault * fontScale,
202
- borderRadius: tokens.borderRadiusMd,
202
+ borderRadius: tokens.borderRadiusMd * fontScale,
203
203
  textColor: statusColorMap[appearance].text,
204
204
  fontWeight: platformFontWeightMedium,
205
205
  },
@@ -219,7 +219,6 @@ const useStyles = ({
219
219
  return StyleSheet.create({
220
220
  badgeWrapper: {
221
221
  flexDirection: 'row',
222
- alignItems: 'center',
223
222
  justifyContent: 'center',
224
223
  alignSelf: 'flex-start',
225
224
  borderRadius: variantStylesMap[variant].borderRadius,
@@ -255,6 +254,7 @@ const useStyles = ({
255
254
  metaLabel: {
256
255
  paddingHorizontal: variantStylesMap[variant].paddingHorizontal,
257
256
  fontSize: badgeFontSize,
257
+ alignSelf: 'center',
258
258
  flexShrink: 1,
259
259
  paddingLeft: variantStylesMap[variant].metaLabelPaddingLeft,
260
260
  },
@@ -4,17 +4,17 @@ import { HeaderButton } from '@react-navigation/elements'
4
4
  import { Icon } from './icon'
5
5
  import { useTheme } from '../../hooks'
6
6
 
7
- interface HeaderSubmitButtonProps {
7
+ interface HeaderTextButtonProps {
8
8
  onPress: () => void
9
9
  title?: string
10
10
  disabled?: boolean
11
11
  }
12
12
 
13
- export const HeaderSubmitButton = ({
13
+ export const HeaderTextButton = ({
14
14
  onPress,
15
15
  title = 'Submit',
16
16
  ...props
17
- }: HeaderSubmitButtonProps) => {
17
+ }: HeaderTextButtonProps) => {
18
18
  const styles = useStyles()
19
19
 
20
20
  return (
@@ -29,18 +29,18 @@ export const HeaderSubmitButton = ({
29
29
  )
30
30
  }
31
31
 
32
- interface HeaderCancelButtonProps {
32
+ interface HeaderDismissButtonProps {
33
33
  onPress: () => void
34
34
  title?: string
35
35
  tintColor?: ColorValue
36
36
  }
37
37
 
38
- export const HeaderCancelButton = ({
38
+ export const HeaderDismissButton = ({
39
39
  onPress,
40
40
  title = 'Cancel',
41
41
  tintColor,
42
42
  ...props
43
- }: HeaderCancelButtonProps) => {
43
+ }: HeaderDismissButtonProps) => {
44
44
  const styles = useStyles()
45
45
 
46
46
  return Platform.select({
@@ -1,13 +1,37 @@
1
1
  import { useTheme } from '../../hooks'
2
2
  import React from 'react'
3
3
  import { StyleSheet, Text as ReactNativeText, Platform } from 'react-native'
4
- import type { TextStyle, TextProps as ReactNativeTextProps } from 'react-native'
4
+ import type {
5
+ TextStyle as ReactNativeTextStyle,
6
+ TextProps as ReactNativeTextProps,
7
+ StyleProp,
8
+ } from 'react-native'
5
9
  import { tokens } from '../../vendor/tapestry/tokens'
6
10
 
7
11
  // =================================
8
12
  // ====== Constants ================
9
13
  // =================================
10
14
 
15
+ // TextStyle extends ViewStyle, which includes border properties.
16
+ // CCA has issues with borders on Text on iOS. (https://github.com/planningcenter/chat-mobile/pull/177)
17
+ // Our pattern is to apply boarders to a parent View instead.
18
+ type BorderKeys =
19
+ | 'borderWidth'
20
+ | 'borderBottomWidth'
21
+ | 'borderLeftWidth'
22
+ | 'borderRightWidth'
23
+ | 'borderTopWidth'
24
+ | 'borderColor'
25
+ | 'borderBottomColor'
26
+ | 'borderLeftColor'
27
+ | 'borderRightColor'
28
+ | 'borderTopColor'
29
+ | 'borderStyle'
30
+
31
+ export type TextStyle = Omit<ReactNativeTextStyle, BorderKeys> & {
32
+ [K in BorderKeys]?: never
33
+ }
34
+
11
35
  const VARIANTS = {
12
36
  plain: 'plain',
13
37
  secondary: 'secondary',
@@ -22,11 +46,15 @@ type VariantStyles = Record<VariantUnion, TextStyle>
22
46
  // ====== Component ================
23
47
  // =================================
24
48
 
25
- export interface TextProps extends ReactNativeTextProps {
49
+ export interface TextProps extends Omit<ReactNativeTextProps, 'style'> {
26
50
  /**
27
51
  * Changes the styles and size of the text.
28
52
  */
29
53
  variant?: VariantUnion
54
+ /**
55
+ * Text styles (border and background properties are not allowed)
56
+ */
57
+ style?: StyleProp<TextStyle>
30
58
  }
31
59
 
32
60
  export function Text({ style, variant = 'plain', children, ...props }: TextProps) {
@@ -8,7 +8,11 @@ import {
8
8
  useCreateAndroidRippleColor,
9
9
  useInteractionGhostBackgroundColor,
10
10
  } from '../../hooks'
11
- import { platformFontWeightBold, platformPressedOpacityStyle } from '../../utils'
11
+ import {
12
+ MAX_FONT_SIZE_MULTIPLIER_LANDMARK,
13
+ platformFontWeightBold,
14
+ platformPressedOpacityStyle,
15
+ } from '../../utils'
12
16
  import { Icon, IconString } from './icon'
13
17
  import { tokens } from '../../vendor/tapestry/tokens'
14
18
  import { Haptic } from '../../utils/native_adapters/configuration'
@@ -66,7 +70,7 @@ export function ToggleButton({
66
70
  allowFontScaling = true,
67
71
  iconNameLeft,
68
72
  iconNameRight,
69
- maxFontSizeMultiplier,
73
+ maxFontSizeMultiplier = MAX_FONT_SIZE_MULTIPLIER_LANDMARK,
70
74
  minimumFontScale,
71
75
  title,
72
76
  style,
@@ -1,11 +1,8 @@
1
1
  import { useNavigation } from '@react-navigation/native'
2
2
  import { useQueryErrorResetBoundary } from '@tanstack/react-query'
3
3
  import React, { PropsWithChildren, useEffect, useMemo } from 'react'
4
- import { StyleSheet, View } from 'react-native'
5
- import { useSafeAreaInsets } from 'react-native-safe-area-context'
6
- import { Button, Heading, Icon, Text, TextButton } from '../display'
7
- import { useTheme } from '../../hooks'
8
4
  import { ResponseError } from '../../utils/response_error'
5
+ import BlankState from '../primitive/blank_state_primitive'
9
6
 
10
7
  type ErrorBoundaryState = {
11
8
  error: ResponseError | Error | TypeError | null
@@ -108,54 +105,26 @@ function ResponseErrorView({ response }: { response: Response; onReset: () => vo
108
105
  }
109
106
 
110
107
  function ErrorContent({ heading, body }: { heading: string; body: string }) {
111
- const styles = useStyles()
112
108
  const navigation = useNavigation()
113
109
 
114
110
  return (
115
- <View style={styles.container}>
116
- <Icon name="general.outlinedTextMessage" size={32} color={styles.icon.color} />
117
- <View style={styles.information}>
118
- <Heading variant="h3" style={styles.heading}>
119
- {heading}
120
- </Heading>
121
- <Text style={styles.body}>{body}</Text>
122
- </View>
123
- <Button variant="outline" onPress={navigation.goBack} title="Go back" size="md" />
124
- <TextButton variant="tertiary" onPress={() => navigation.navigate('BugReport')}>
111
+ <BlankState.Root>
112
+ <BlankState.Imagery name="people.noTextMessage" />
113
+ <BlankState.Content>
114
+ <BlankState.Heading>{heading}</BlankState.Heading>
115
+ <BlankState.Text>{body}</BlankState.Text>
116
+ </BlankState.Content>
117
+ <BlankState.Button
118
+ title="Go back"
119
+ onPress={navigation.goBack}
120
+ size="md"
121
+ accessibilityRole="link"
122
+ />
123
+ <BlankState.TextButton onPress={() => navigation.navigate('BugReport')}>
125
124
  Report a bug
126
- </TextButton>
127
- </View>
125
+ </BlankState.TextButton>
126
+ </BlankState.Root>
128
127
  )
129
128
  }
130
129
 
131
- const useStyles = () => {
132
- const theme = useTheme()
133
- const { bottom } = useSafeAreaInsets()
134
- return StyleSheet.create({
135
- container: {
136
- flex: 1,
137
- justifyContent: 'center',
138
- alignItems: 'center',
139
- gap: 24,
140
- paddingHorizontal: 16,
141
- paddingBottom: bottom,
142
- },
143
- information: {
144
- alignItems: 'center',
145
- gap: 8,
146
- },
147
- heading: {
148
- textAlign: 'center',
149
- lineHeight: 20,
150
- },
151
- body: {
152
- textAlign: 'center',
153
- lineHeight: 20,
154
- },
155
- icon: {
156
- color: theme.colors.iconColorDefaultDisabled,
157
- },
158
- })
159
- }
160
-
161
130
  export default ErrorBoundary
@@ -1,9 +1,10 @@
1
1
  import React, { createContext, useContext, useEffect, useState } from 'react'
2
2
  import { StyleSheet, View, ViewProps } from 'react-native'
3
- import { useTheme } from '../../hooks'
3
+ import { useFontScale, useTheme } from '../../hooks'
4
4
  import { Icon, IconString } from '../display/icon'
5
5
  import { Image, ImageProps } from '../display/image'
6
6
  import { Spinner } from '../display/spinner'
7
+ import { MAX_FONT_SIZE_MULTIPLIER } from '../../utils'
7
8
 
8
9
  // =================================
9
10
  // ====== Exports ==================
@@ -146,8 +147,10 @@ interface AvatarImageProps extends Omit<ImageProps, 'source' | 'alt'> {
146
147
 
147
148
  function AvatarImage({ sourceUri, ...props }: AvatarImageProps) {
148
149
  const { size } = useAvatarContext()
150
+ const fontScale = useFontScale({ maxFontSizeMultiplier: MAX_FONT_SIZE_MULTIPLIER })
151
+ const scaledAvatarSize = AVATAR_PX[size] * fontScale
149
152
 
150
- return <Image source={{ uri: sourceUri }} loaderSize={AVATAR_PX[size]} {...props} alt="" />
153
+ return <Image source={{ uri: sourceUri }} loaderSize={scaledAvatarSize} {...props} alt="" />
151
154
  }
152
155
 
153
156
  AvatarImage.displayName = 'Avatar.Image'
@@ -171,12 +174,14 @@ interface AvatarImageFallbackProps {
171
174
  function AvatarImageFallback({ name = 'general.person' }: AvatarImageFallbackProps) {
172
175
  const { size } = useAvatarContext()
173
176
  const styles = useStyles()
177
+ const fontScale = useFontScale({ maxFontSizeMultiplier: MAX_FONT_SIZE_MULTIPLIER })
178
+ const scaledIconSize = AVATAR_FALLBACK_ICON_PX[size] * fontScale
174
179
 
175
180
  return (
176
181
  <View style={styles.fallbackContainer}>
177
182
  <Icon
178
183
  name={name}
179
- size={AVATAR_FALLBACK_ICON_PX[size]}
184
+ size={scaledIconSize}
180
185
  style={styles.fallbackIcon}
181
186
  accessibilityElementsHidden={true}
182
187
  />
@@ -309,12 +314,14 @@ AvatarGroup.displayName = 'Avatar.Group'
309
314
  function AvatarGroupLoader() {
310
315
  const { size, allImagesLoaded } = useAvatarContext()
311
316
  const styles = useStyles({ size })
317
+ const fontScale = useFontScale({ maxFontSizeMultiplier: MAX_FONT_SIZE_MULTIPLIER })
318
+ const scaledSpinnerSize = AVATAR_PX[size] * fontScale
312
319
 
313
320
  if (allImagesLoaded) return null
314
321
 
315
322
  return (
316
323
  <View style={styles.groupLoader}>
317
- <Spinner size={AVATAR_PX[size]} />
324
+ <Spinner size={scaledSpinnerSize} />
318
325
  </View>
319
326
  )
320
327
  }
@@ -349,12 +356,13 @@ interface Styles {
349
356
 
350
357
  const useStyles = ({ size = 'md', presence = 'offline' }: Styles = {}) => {
351
358
  const { colors } = useTheme()
359
+ const fontScale = useFontScale({ maxFontSizeMultiplier: MAX_FONT_SIZE_MULTIPLIER })
352
360
  const PRESENCE_COLOR = {
353
361
  online: colors.fillColorInteractionOnlineDefault,
354
362
  offline: colors.iconColorDefaultDisabled,
355
363
  }
356
- const presenceDiameter = AVATAR_PRESENCE_PX[size]
357
- const avatarDiameter = AVATAR_PX[size]
364
+ const presenceDiameter = AVATAR_PRESENCE_PX[size] * fontScale
365
+ const avatarDiameter = AVATAR_PX[size] * fontScale
358
366
  const groupGap = 1
359
367
 
360
368
  return StyleSheet.create({
@@ -5,11 +5,13 @@ import {
5
5
  Button,
6
6
  Heading,
7
7
  Icon,
8
+ TextButton,
8
9
  Text,
9
10
  type ButtonProps,
10
11
  type HeadingProps,
11
12
  type IconString,
12
13
  type IconStyle,
14
+ type TextButtonProps,
13
15
  type TextProps,
14
16
  } from '../display'
15
17
 
@@ -24,6 +26,7 @@ const BlankState = {
24
26
  Heading: BlankStateHeading,
25
27
  Text: BlankStateText,
26
28
  Button: BlankStateButton,
29
+ TextButton: BlankStateTextButton,
27
30
  } as const
28
31
 
29
32
  type BlankStateComponents = {
@@ -33,6 +36,7 @@ type BlankStateComponents = {
33
36
  Heading: FC<BlankStateHeadingProps>
34
37
  Text: FC<BlankStateTextProps>
35
38
  Button: FC<BlankStateButtonProps>
39
+ TextButton: FC<BlankStateTextButtonProps>
36
40
  }
37
41
 
38
42
  export default BlankState as BlankStateComponents
@@ -43,6 +47,7 @@ export type {
43
47
  BlankStateHeadingProps,
44
48
  BlankStateTextProps,
45
49
  BlankStateButtonProps,
50
+ BlankStateTextButtonProps,
46
51
  }
47
52
 
48
53
  // ========================================
@@ -159,6 +164,18 @@ function BlankStateButton(props: BlankStateButtonProps) {
159
164
 
160
165
  BlankStateButton.displayName = 'BlankState.Button'
161
166
 
167
+ // ========================================
168
+ // ====== BlankStateTextButton ================
169
+ // ========================================
170
+
171
+ interface BlankStateTextButtonProps extends TextButtonProps {}
172
+
173
+ function BlankStateTextButton(props: BlankStateTextButtonProps) {
174
+ return <TextButton variant="tertiary" {...props} />
175
+ }
176
+
177
+ BlankStateTextButton.displayName = 'BlankState.TextButton'
178
+
162
179
  // ========================================
163
180
  // ====== Styles ==========================
164
181
  // ========================================
@@ -12,3 +12,4 @@ export * from './use_api'
12
12
  export * from './use_api_client'
13
13
  export * from './use_message_reaction_toggle'
14
14
  export * from './use_interaction_ghost_color'
15
+ export * from './use_at_font_scale_breakpoint'
@@ -0,0 +1,11 @@
1
+ import { useFontScale } from './use_font_scale'
2
+
3
+ // Based on iOS's AX1 font scale https://developer.apple.com/design/human-interface-guidelines/typography#iOS-iPadOS-larger-accessibility-type-sizes
4
+ const FONT_SCALE_BREAKPOINT_FALLBACK = 1.78
5
+
6
+ export const useAtFontScaleBreakpoint = (scaleBreakpoint?: number) => {
7
+ const fontScale = useFontScale()
8
+ const breakpoint = scaleBreakpoint ?? FONT_SCALE_BREAKPOINT_FALLBACK
9
+
10
+ return fontScale >= breakpoint
11
+ }
@@ -42,7 +42,7 @@ import {
42
42
  MessageReadReceiptsScreenOptions,
43
43
  } from '../screens/conversation/message_read_receipts_screen'
44
44
  import { Platform } from 'react-native'
45
- import { HeaderSubmitButton } from '../components/display/platform_modal_header_buttons'
45
+ import { HeaderTextButton } from '../components/display/platform_modal_header_buttons'
46
46
  import { TeamConversationScreen } from '../screens/team_conversation_screen'
47
47
  import { CardStyleInterpolators } from '@react-navigation/stack'
48
48
 
@@ -63,7 +63,7 @@ export const NewConversationStack = createNativeStackNavigator({
63
63
  options: ({ navigation }) => ({
64
64
  title: 'New conversation',
65
65
  headerRight: (props: NativeStackHeaderRightProps) => (
66
- <HeaderSubmitButton {...props} onPress={navigation.goBack} title="Cancel" />
66
+ <HeaderTextButton {...props} onPress={navigation.goBack} title="Cancel" />
67
67
  ),
68
68
  headerBackVisible: false,
69
69
  }),
@@ -73,7 +73,7 @@ export const NewConversationStack = createNativeStackNavigator({
73
73
  options: ({ navigation, route }) => ({
74
74
  title: 'New conversation',
75
75
  headerRight: (props: NativeStackHeaderRightProps) => (
76
- <HeaderSubmitButton
76
+ <HeaderTextButton
77
77
  {...props}
78
78
  onPress={() => navigation.popTo('Conversations', route.params)}
79
79
  title="Cancel"
@@ -86,7 +86,7 @@ export const NewConversationStack = createNativeStackNavigator({
86
86
  options: ({ navigation, route }) => ({
87
87
  title: 'New conversation',
88
88
  headerRight: (props: NativeStackHeaderRightProps) => (
89
- <HeaderSubmitButton
89
+ <HeaderTextButton
90
90
  {...props}
91
91
  onPress={() => navigation.popTo('Conversations', route.params)}
92
92
  title="Cancel"
@@ -104,7 +104,7 @@ export const NewConversationStack = createNativeStackNavigator({
104
104
  title: 'New conversation',
105
105
  headerLeft: () => null,
106
106
  headerRight: (props: NativeStackHeaderRightProps) => (
107
- <HeaderSubmitButton
107
+ <HeaderTextButton
108
108
  {...props}
109
109
  onPress={() => navigation.getParent()?.goBack()}
110
110
  title="Cancel"
@@ -195,7 +195,7 @@ export const ChatStack = createNativeStackNavigator({
195
195
  presentation: 'modal',
196
196
  title: 'Conversation details',
197
197
  headerRight: (props: NativeStackHeaderRightProps) => (
198
- <HeaderSubmitButton {...props} onPress={navigation.goBack} title="Done" />
198
+ <HeaderTextButton {...props} onPress={navigation.goBack} title="Done" />
199
199
  ),
200
200
  }),
201
201
  },