@planningcenter/chat-react-native 3.22.0 → 3.23.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.
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import type { PressableProps } from 'react-native';
3
+ import { type IconString } from '../../../components/display/icon';
4
+ interface ListHeaderActionButtonProps extends PressableProps {
5
+ /**
6
+ * Provides context to screen readers about what the button does.
7
+ */
8
+ accessibilityLabel: string;
9
+ /**
10
+ * Specifies the maximum size a font can reach when allowFontScaling is enabled.
11
+ */
12
+ maxFontSizeMultiplier?: number;
13
+ /**
14
+ * Generates an icon from `@planningcenter/icons`
15
+ */
16
+ name: IconString;
17
+ }
18
+ export declare function ListHeaderActionButton({ accessibilityLabel, maxFontSizeMultiplier, name, ...props }: ListHeaderActionButtonProps): React.JSX.Element;
19
+ export {};
20
+ //# sourceMappingURL=list_header_action_button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list_header_action_button.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversations/components/list_header_action_button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,kCAAkC,CAAA;AAKxE,UAAU,2BAA4B,SAAQ,cAAc;IAC1D;;OAEG;IACH,kBAAkB,EAAE,MAAM,CAAA;IAC1B;;OAEG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B;;OAEG;IACH,IAAI,EAAE,UAAU,CAAA;CACjB;AAED,wBAAgB,sBAAsB,CAAC,EACrC,kBAAkB,EAClB,qBAAqB,EACrB,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,2BAA2B,qBAsB7B"}
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+ import { Pressable, StyleSheet } from 'react-native';
3
+ import { Icon } from '../../../components/display/icon';
4
+ import { useTheme, useFontScale, useCreateAndroidRippleColor } from '../../../hooks';
5
+ import { platformPressedOpacityStyle } from '../../../utils';
6
+ import { tokens } from '../../../vendor/tapestry/tokens';
7
+ export function ListHeaderActionButton({ accessibilityLabel, maxFontSizeMultiplier, name, ...props }) {
8
+ const styles = useStyles({ maxFontSizeMultiplier });
9
+ const { colors } = useTheme();
10
+ const androidRippleColor = useCreateAndroidRippleColor({
11
+ color: colors.iconColorDefaultSecondary,
12
+ });
13
+ return (<Pressable style={({ pressed }) => [styles.pressable, pressed && platformPressedOpacityStyle]} accessibilityRole="button" accessibilityLabel={accessibilityLabel} android_ripple={{
14
+ color: androidRippleColor,
15
+ borderless: false,
16
+ foreground: true,
17
+ }} {...props}>
18
+ <Icon name={name} style={styles.icon} maxFontSizeMultiplier={maxFontSizeMultiplier}/>
19
+ </Pressable>);
20
+ }
21
+ const useStyles = ({ maxFontSizeMultiplier }) => {
22
+ const { colors, button } = useTheme();
23
+ const fontScale = useFontScale({ maxFontSizeMultiplier });
24
+ return StyleSheet.create({
25
+ pressable: {
26
+ borderRadius: button.borderRadius * fontScale,
27
+ borderWidth: 1,
28
+ borderColor: colors.borderColorDefaultBase,
29
+ backgroundColor: 'transparent',
30
+ paddingHorizontal: 16 * fontScale,
31
+ flexDirection: 'row',
32
+ alignItems: 'center',
33
+ justifyContent: 'center',
34
+ height: 32 * fontScale,
35
+ gap: 6 * fontScale,
36
+ overflow: 'hidden',
37
+ },
38
+ icon: {
39
+ fontSize: tokens.fontSizeSm * fontScale,
40
+ color: colors.iconColorDefaultSecondary,
41
+ },
42
+ });
43
+ };
44
+ //# sourceMappingURL=list_header_action_button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list_header_action_button.js","sourceRoot":"","sources":["../../../../src/screens/conversations/components/list_header_action_button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEpD,OAAO,EAAE,IAAI,EAAmB,MAAM,kCAAkC,CAAA;AACxE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAA;AACpF,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAA;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAA;AAiBxD,MAAM,UAAU,sBAAsB,CAAC,EACrC,kBAAkB,EAClB,qBAAqB,EACrB,IAAI,EACJ,GAAG,KAAK,EACoB;IAC5B,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,qBAAqB,EAAE,CAAC,CAAA;IACnD,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAC7B,MAAM,kBAAkB,GAAG,2BAA2B,CAAC;QACrD,KAAK,EAAE,MAAM,CAAC,yBAAyB;KACxC,CAAC,CAAA;IAEF,OAAO,CACL,CAAC,SAAS,CACR,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,IAAI,2BAA2B,CAAC,CAAC,CACnF,iBAAiB,CAAC,QAAQ,CAC1B,kBAAkB,CAAC,CAAC,kBAAkB,CAAC,CACvC,cAAc,CAAC,CAAC;YACd,KAAK,EAAE,kBAAkB;YACzB,UAAU,EAAE,KAAK;YACjB,UAAU,EAAE,IAAI;SACjB,CAAC,CACF,IAAI,KAAK,CAAC,CAEV;MAAA,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,qBAAqB,CAAC,CAAC,qBAAqB,CAAC,EACrF;IAAA,EAAE,SAAS,CAAC,CACb,CAAA;AACH,CAAC;AAED,MAAM,SAAS,GAAG,CAAC,EAAE,qBAAqB,EAAwC,EAAE,EAAE;IACpF,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IACrC,MAAM,SAAS,GAAG,YAAY,CAAC,EAAE,qBAAqB,EAAE,CAAC,CAAA;IAEzD,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE;YACT,YAAY,EAAE,MAAM,CAAC,YAAY,GAAG,SAAS;YAC7C,WAAW,EAAE,CAAC;YACd,WAAW,EAAE,MAAM,CAAC,sBAAsB;YAC1C,eAAe,EAAE,aAAa;YAC9B,iBAAiB,EAAE,EAAE,GAAG,SAAS;YACjC,aAAa,EAAE,KAAK;YACpB,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,QAAQ;YACxB,MAAM,EAAE,EAAE,GAAG,SAAS;YACtB,GAAG,EAAE,CAAC,GAAG,SAAS;YAClB,QAAQ,EAAE,QAAQ;SACnB;QACD,IAAI,EAAE;YACJ,QAAQ,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS;YACvC,KAAK,EAAE,MAAM,CAAC,yBAAyB;SACxC;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import React from 'react'\nimport { Pressable, StyleSheet } from 'react-native'\nimport type { PressableProps } from 'react-native'\nimport { Icon, type IconString } from '../../../components/display/icon'\nimport { useTheme, useFontScale, useCreateAndroidRippleColor } from '../../../hooks'\nimport { platformPressedOpacityStyle } from '../../../utils'\nimport { tokens } from '../../../vendor/tapestry/tokens'\n\ninterface ListHeaderActionButtonProps extends PressableProps {\n /**\n * Provides context to screen readers about what the button does.\n */\n accessibilityLabel: string\n /**\n * Specifies the maximum size a font can reach when allowFontScaling is enabled.\n */\n maxFontSizeMultiplier?: number\n /**\n * Generates an icon from `@planningcenter/icons`\n */\n name: IconString\n}\n\nexport function ListHeaderActionButton({\n accessibilityLabel,\n maxFontSizeMultiplier,\n name,\n ...props\n}: ListHeaderActionButtonProps) {\n const styles = useStyles({ maxFontSizeMultiplier })\n const { colors } = useTheme()\n const androidRippleColor = useCreateAndroidRippleColor({\n color: colors.iconColorDefaultSecondary,\n })\n\n return (\n <Pressable\n style={({ pressed }) => [styles.pressable, pressed && platformPressedOpacityStyle]}\n accessibilityRole=\"button\"\n accessibilityLabel={accessibilityLabel}\n android_ripple={{\n color: androidRippleColor,\n borderless: false,\n foreground: true,\n }}\n {...props}\n >\n <Icon name={name} style={styles.icon} maxFontSizeMultiplier={maxFontSizeMultiplier} />\n </Pressable>\n )\n}\n\nconst useStyles = ({ maxFontSizeMultiplier }: Partial<ListHeaderActionButtonProps>) => {\n const { colors, button } = useTheme()\n const fontScale = useFontScale({ maxFontSizeMultiplier })\n\n return StyleSheet.create({\n pressable: {\n borderRadius: button.borderRadius * fontScale,\n borderWidth: 1,\n borderColor: colors.borderColorDefaultBase,\n backgroundColor: 'transparent',\n paddingHorizontal: 16 * fontScale,\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n height: 32 * fontScale,\n gap: 6 * fontScale,\n overflow: 'hidden',\n },\n icon: {\n fontSize: tokens.fontSizeSm * fontScale,\n color: colors.iconColorDefaultSecondary,\n },\n })\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"list_header_component.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversations/components/list_header_component.tsx"],"names":[],"mappings":"AACA,OAAO,KAA+B,MAAM,OAAO,CAAA;AAoBnD,eAAO,MAAM,mBAAmB,yBAmH/B,CAAA"}
1
+ {"version":3,"file":"list_header_component.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversations/components/list_header_component.tsx"],"names":[],"mappings":"AACA,OAAO,KAA+B,MAAM,OAAO,CAAA;AAuBnD,eAAO,MAAM,mBAAmB,yBAuJ/B,CAAA"}
@@ -5,9 +5,12 @@ import { Heading, TextButton, ToggleButton } from '../../../components';
5
5
  import { useAtFontScaleBreakpoint, useCurrentPersonCache, useTheme } from '../../../hooks';
6
6
  import { useMarkAllRead } from '../../../hooks/use_conversations_actions';
7
7
  import { useCanDisplayGroups } from '../../../hooks/use_groups';
8
+ import { useCanCreateConversations } from '../../../hooks';
9
+ import { useAppName } from '../../../hooks/use_app_name';
8
10
  import { ChatGroupBadge } from './chat_group_badge';
9
11
  import { Haptic } from '../../../utils/native_adapters';
10
12
  import { MAX_FONT_SIZE_MULTIPLIER_LANDMARK } from '../../../utils';
13
+ import { ListHeaderActionButton } from './list_header_action_button';
11
14
  const ROW_PADDING_HORIZONTAL = 16;
12
15
  var FilterTypes;
13
16
  (function (FilterTypes) {
@@ -25,6 +28,8 @@ export const ListHeaderComponent = () => {
25
28
  const { chat_group_graph_id, group_source_app_name = '' } = route.params || {};
26
29
  const currentPersonCache = useCurrentPersonCache();
27
30
  const { markAllRead, isPending } = useMarkAllRead();
31
+ const canCreateConversations = useCanCreateConversations();
32
+ const appName = useAppName();
28
33
  const active = useMemo(() => {
29
34
  if (chat_group_graph_id) {
30
35
  return FilterTypes.More;
@@ -37,6 +42,17 @@ export const ListHeaderComponent = () => {
37
42
  }
38
43
  return FilterTypes.All;
39
44
  }, [chat_group_graph_id, group_source_app_name]);
45
+ const handleNewConversationNavigation = useCallback(() => {
46
+ return navigation.navigate('New', {
47
+ screen: 'ConversationSelectRecipients',
48
+ params: {
49
+ ...route.params,
50
+ },
51
+ });
52
+ }, [navigation, route.params]);
53
+ const handleGetHelp = useCallback(() => {
54
+ navigation.navigate('GetHelp', { type: 'chat' });
55
+ }, [navigation]);
40
56
  const handleMarkAllRead = useCallback(() => {
41
57
  currentPersonCache.update({ unreadCount: 0 });
42
58
  Haptic.notificationSuccess();
@@ -52,13 +68,19 @@ export const ListHeaderComponent = () => {
52
68
  }, [active, handleMarkAllRead]);
53
69
  const showAppFilters = canFilterByGroups && canFilterByTeams;
54
70
  return (<View style={styles.listHeader}>
55
- <View style={styles.titleRow}>
56
- <Heading numberOfLines={1} variant="h2">
57
- Conversations
58
- </Heading>
59
- <TextButton onPress={alertMarkAllRead} disabled={isPending} maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK} accessibilityShowsLargeContentViewer accessibilityLargeContentTitle="Mark all read">
60
- Mark all read
61
- </TextButton>
71
+ <View style={styles.headingRow}>
72
+ <View style={styles.titleContainer}>
73
+ <Heading numberOfLines={1} variant="h2">
74
+ Conversations
75
+ </Heading>
76
+ <TextButton onPress={alertMarkAllRead} disabled={isPending} maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK} accessibilityShowsLargeContentViewer accessibilityLargeContentTitle="Mark all read">
77
+ Mark all read
78
+ </TextButton>
79
+ </View>
80
+ <View style={styles.actionsContainer}>
81
+ {canCreateConversations && (<ListHeaderActionButton name="churchCenter.signups" onPress={handleNewConversationNavigation} accessibilityLabel="New conversation" testID="conversations-new-conversation-button" maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}/>)}
82
+ {appName !== 'services' && (<ListHeaderActionButton name="general.outlinedInfoCircle" onPress={handleGetHelp} accessibilityLabel="Get help" maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}/>)}
83
+ </View>
62
84
  </View>
63
85
  <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.filterRow} accessibilityRole="toolbar">
64
86
  {showAppFilters && (<>
@@ -92,19 +114,27 @@ const useStyles = () => {
92
114
  borderBottomWidth: 1,
93
115
  borderBottomColor: theme.colors.fillColorNeutral050Base,
94
116
  paddingBottom: 16,
95
- gap: 12,
117
+ gap: 16,
96
118
  },
97
- titleRow: {
119
+ headingRow: {
120
+ gap: 12,
98
121
  flexDirection: atFontScaleBreakpoint ? 'column' : 'row',
99
- justifyContent: 'space-between',
100
122
  alignItems: atFontScaleBreakpoint ? 'flex-start' : 'center',
101
- flexWrap: 'wrap',
102
- rowGap: 8,
103
- columnGap: 16,
104
- paddingTop: 8,
123
+ justifyContent: 'space-between',
105
124
  paddingBottom: atFontScaleBreakpoint ? 4 : 0,
106
125
  paddingHorizontal: ROW_PADDING_HORIZONTAL,
107
126
  },
127
+ titleContainer: {
128
+ gap: 8,
129
+ },
130
+ actionsContainer: {
131
+ flexDirection: 'row',
132
+ gap: 8,
133
+ alignItems: 'center',
134
+ },
135
+ markAllReadRow: {
136
+ paddingBottom: 4,
137
+ },
108
138
  filterRow: {
109
139
  flexDirection: 'row',
110
140
  justifyContent: 'flex-start',
@@ -1 +1 @@
1
- {"version":3,"file":"list_header_component.js","sourceRoot":"","sources":["../../../../src/screens/conversations/components/list_header_component.tsx"],"names":[],"mappings":"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","sourcesContent":["import { RouteProp, useNavigation, useRoute } from '@react-navigation/native'\nimport React, { useCallback, useMemo } from 'react'\nimport { Alert, ScrollView, StyleSheet, View } from 'react-native'\nimport { Heading, TextButton, ToggleButton } from '../../../components'\nimport { useAtFontScaleBreakpoint, useCurrentPersonCache, useTheme } from '../../../hooks'\nimport { useMarkAllRead } from '../../../hooks/use_conversations_actions'\nimport { useCanDisplayGroups } from '../../../hooks/use_groups'\nimport { ConversationsScreenProps } from '../conversations_screen'\nimport { ChatGroupBadge } from './chat_group_badge'\nimport { Haptic } from '../../../utils/native_adapters'\nimport { MAX_FONT_SIZE_MULTIPLIER_LANDMARK } from '../../../utils'\n\nconst ROW_PADDING_HORIZONTAL = 16\n\nenum FilterTypes {\n All = 'All',\n Groups = 'Groups',\n Teams = 'Teams',\n More = 'More',\n}\n\nexport const ListHeaderComponent = () => {\n const styles = useStyles()\n const navigation = useNavigation()\n const canFilterByTeams = useCanDisplayGroups({ source_app_name: 'Services', source_type: 'Team' })\n const canFilterByGroups = useCanDisplayGroups({ source_app_name: 'Groups', source_type: 'Group' })\n const route = useRoute<RouteProp<ConversationsScreenProps['route']>>()\n const { chat_group_graph_id, group_source_app_name = '' } = route.params || {}\n const currentPersonCache = useCurrentPersonCache()\n const { markAllRead, isPending } = useMarkAllRead()\n\n const active: FilterTypes = useMemo(() => {\n if (chat_group_graph_id) {\n return FilterTypes.More\n } else if (/groups/i.test(group_source_app_name)) {\n return FilterTypes.Groups\n } else if (/services/i.test(group_source_app_name)) {\n return FilterTypes.Teams\n }\n\n return FilterTypes.All\n }, [chat_group_graph_id, group_source_app_name])\n\n const handleMarkAllRead = useCallback(() => {\n currentPersonCache.update({ unreadCount: 0 })\n Haptic.notificationSuccess()\n markAllRead()\n }, [currentPersonCache, markAllRead])\n\n const alertMarkAllRead = useCallback(() => {\n if (active === FilterTypes.All) return handleMarkAllRead()\n\n Alert.alert('Mark all read', 'This includes conversations not shown by the current filter.', [\n { text: 'Cancel' },\n { text: 'OK', onPress: () => handleMarkAllRead() },\n ])\n }, [active, handleMarkAllRead])\n\n const showAppFilters = canFilterByGroups && canFilterByTeams\n\n return (\n <View style={styles.listHeader}>\n <View style={styles.titleRow}>\n <Heading numberOfLines={1} variant=\"h2\">\n Conversations\n </Heading>\n <TextButton\n onPress={alertMarkAllRead}\n disabled={isPending}\n maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}\n accessibilityShowsLargeContentViewer\n accessibilityLargeContentTitle=\"Mark all read\"\n >\n Mark all read\n </TextButton>\n </View>\n <ScrollView\n horizontal\n showsHorizontalScrollIndicator={false}\n contentContainerStyle={styles.filterRow}\n accessibilityRole=\"toolbar\"\n >\n {showAppFilters && (\n <>\n <ToggleButton\n title={FilterTypes.All}\n active={active === FilterTypes.All}\n onPress={() =>\n navigation.setParams({\n chat_group_graph_id: undefined,\n group_source_app_name: undefined,\n })\n }\n accessibilityLabel=\"Show all conversations\"\n />\n <ToggleButton\n title={FilterTypes.Groups}\n active={active === FilterTypes.Groups}\n onPress={() =>\n navigation.setParams({\n chat_group_graph_id: undefined,\n group_source_app_name: 'Groups',\n })\n }\n accessibilityLabel=\"Filter to group conversations\"\n />\n\n <ToggleButton\n title={FilterTypes.Teams}\n active={active === FilterTypes.Teams}\n onPress={() =>\n navigation.setParams({\n chat_group_graph_id: undefined,\n group_source_app_name: 'Services',\n })\n }\n accessibilityLabel=\"Filter to team conversations\"\n />\n </>\n )}\n <ToggleButton\n title={showAppFilters ? FilterTypes.More : 'Filter'}\n onPress={() =>\n navigation.navigate('ConversationFilters', {\n chat_group_graph_id,\n group_source_app_name,\n })\n }\n active={active === FilterTypes.More}\n iconNameRight=\"general.threeReducingHorizontalBars\"\n accessibilityLabel={showAppFilters ? 'View all filters' : 'View more filters'}\n />\n </ScrollView>\n <ChatGroupBadge rowPaddingHorizontal={ROW_PADDING_HORIZONTAL} />\n </View>\n )\n}\n\nconst useStyles = () => {\n const theme = useTheme()\n const atFontScaleBreakpoint = useAtFontScaleBreakpoint()\n\n return StyleSheet.create({\n listHeader: {\n borderBottomWidth: 1,\n borderBottomColor: theme.colors.fillColorNeutral050Base,\n paddingBottom: 16,\n gap: 12,\n },\n titleRow: {\n flexDirection: atFontScaleBreakpoint ? 'column' : 'row',\n justifyContent: 'space-between',\n alignItems: atFontScaleBreakpoint ? 'flex-start' : 'center',\n flexWrap: 'wrap',\n rowGap: 8,\n columnGap: 16,\n paddingTop: 8,\n paddingBottom: atFontScaleBreakpoint ? 4 : 0,\n paddingHorizontal: ROW_PADDING_HORIZONTAL,\n },\n filterRow: {\n flexDirection: 'row',\n justifyContent: 'flex-start',\n gap: 8,\n paddingHorizontal: ROW_PADDING_HORIZONTAL,\n },\n })\n}\n"]}
1
+ {"version":3,"file":"list_header_component.js","sourceRoot":"","sources":["../../../../src/screens/conversations/components/list_header_component.tsx"],"names":[],"mappings":"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","sourcesContent":["import { RouteProp, useNavigation, useRoute } from '@react-navigation/native'\nimport React, { useCallback, useMemo } from 'react'\nimport { Alert, ScrollView, StyleSheet, View } from 'react-native'\nimport { Heading, TextButton, ToggleButton } from '../../../components'\nimport { useAtFontScaleBreakpoint, useCurrentPersonCache, useTheme } from '../../../hooks'\nimport { useMarkAllRead } from '../../../hooks/use_conversations_actions'\nimport { useCanDisplayGroups } from '../../../hooks/use_groups'\nimport { useCanCreateConversations } from '../../../hooks'\nimport { useAppName } from '../../../hooks/use_app_name'\nimport { ConversationsScreenProps } from '../conversations_screen'\nimport { ChatGroupBadge } from './chat_group_badge'\nimport { Haptic } from '../../../utils/native_adapters'\nimport { MAX_FONT_SIZE_MULTIPLIER_LANDMARK } from '../../../utils'\nimport { ListHeaderActionButton } from './list_header_action_button'\n\nconst ROW_PADDING_HORIZONTAL = 16\n\nenum FilterTypes {\n All = 'All',\n Groups = 'Groups',\n Teams = 'Teams',\n More = 'More',\n}\n\nexport const ListHeaderComponent = () => {\n const styles = useStyles()\n const navigation = useNavigation()\n const canFilterByTeams = useCanDisplayGroups({ source_app_name: 'Services', source_type: 'Team' })\n const canFilterByGroups = useCanDisplayGroups({ source_app_name: 'Groups', source_type: 'Group' })\n const route = useRoute<RouteProp<ConversationsScreenProps['route']>>()\n const { chat_group_graph_id, group_source_app_name = '' } = route.params || {}\n const currentPersonCache = useCurrentPersonCache()\n const { markAllRead, isPending } = useMarkAllRead()\n const canCreateConversations = useCanCreateConversations()\n const appName = useAppName()\n\n const active: FilterTypes = useMemo(() => {\n if (chat_group_graph_id) {\n return FilterTypes.More\n } else if (/groups/i.test(group_source_app_name)) {\n return FilterTypes.Groups\n } else if (/services/i.test(group_source_app_name)) {\n return FilterTypes.Teams\n }\n\n return FilterTypes.All\n }, [chat_group_graph_id, group_source_app_name])\n\n const handleNewConversationNavigation = useCallback(() => {\n return navigation.navigate('New', {\n screen: 'ConversationSelectRecipients',\n params: {\n ...route.params,\n },\n })\n }, [navigation, route.params])\n\n const handleGetHelp = useCallback(() => {\n navigation.navigate('GetHelp', { type: 'chat' })\n }, [navigation])\n\n const handleMarkAllRead = useCallback(() => {\n currentPersonCache.update({ unreadCount: 0 })\n Haptic.notificationSuccess()\n markAllRead()\n }, [currentPersonCache, markAllRead])\n\n const alertMarkAllRead = useCallback(() => {\n if (active === FilterTypes.All) return handleMarkAllRead()\n\n Alert.alert('Mark all read', 'This includes conversations not shown by the current filter.', [\n { text: 'Cancel' },\n { text: 'OK', onPress: () => handleMarkAllRead() },\n ])\n }, [active, handleMarkAllRead])\n\n const showAppFilters = canFilterByGroups && canFilterByTeams\n\n return (\n <View style={styles.listHeader}>\n <View style={styles.headingRow}>\n <View style={styles.titleContainer}>\n <Heading numberOfLines={1} variant=\"h2\">\n Conversations\n </Heading>\n <TextButton\n onPress={alertMarkAllRead}\n disabled={isPending}\n maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}\n accessibilityShowsLargeContentViewer\n accessibilityLargeContentTitle=\"Mark all read\"\n >\n Mark all read\n </TextButton>\n </View>\n <View style={styles.actionsContainer}>\n {canCreateConversations && (\n <ListHeaderActionButton\n name=\"churchCenter.signups\"\n onPress={handleNewConversationNavigation}\n accessibilityLabel=\"New conversation\"\n testID=\"conversations-new-conversation-button\"\n maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}\n />\n )}\n {appName !== 'services' && (\n <ListHeaderActionButton\n name=\"general.outlinedInfoCircle\"\n onPress={handleGetHelp}\n accessibilityLabel=\"Get help\"\n maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}\n />\n )}\n </View>\n </View>\n <ScrollView\n horizontal\n showsHorizontalScrollIndicator={false}\n contentContainerStyle={styles.filterRow}\n accessibilityRole=\"toolbar\"\n >\n {showAppFilters && (\n <>\n <ToggleButton\n title={FilterTypes.All}\n active={active === FilterTypes.All}\n onPress={() =>\n navigation.setParams({\n chat_group_graph_id: undefined,\n group_source_app_name: undefined,\n })\n }\n accessibilityLabel=\"Show all conversations\"\n />\n <ToggleButton\n title={FilterTypes.Groups}\n active={active === FilterTypes.Groups}\n onPress={() =>\n navigation.setParams({\n chat_group_graph_id: undefined,\n group_source_app_name: 'Groups',\n })\n }\n accessibilityLabel=\"Filter to group conversations\"\n />\n\n <ToggleButton\n title={FilterTypes.Teams}\n active={active === FilterTypes.Teams}\n onPress={() =>\n navigation.setParams({\n chat_group_graph_id: undefined,\n group_source_app_name: 'Services',\n })\n }\n accessibilityLabel=\"Filter to team conversations\"\n />\n </>\n )}\n <ToggleButton\n title={showAppFilters ? FilterTypes.More : 'Filter'}\n onPress={() =>\n navigation.navigate('ConversationFilters', {\n chat_group_graph_id,\n group_source_app_name,\n })\n }\n active={active === FilterTypes.More}\n iconNameRight=\"general.threeReducingHorizontalBars\"\n accessibilityLabel={showAppFilters ? 'View all filters' : 'View more filters'}\n />\n </ScrollView>\n <ChatGroupBadge rowPaddingHorizontal={ROW_PADDING_HORIZONTAL} />\n </View>\n )\n}\n\nconst useStyles = () => {\n const theme = useTheme()\n const atFontScaleBreakpoint = useAtFontScaleBreakpoint()\n\n return StyleSheet.create({\n listHeader: {\n borderBottomWidth: 1,\n borderBottomColor: theme.colors.fillColorNeutral050Base,\n paddingBottom: 16,\n gap: 16,\n },\n headingRow: {\n gap: 12,\n flexDirection: atFontScaleBreakpoint ? 'column' : 'row',\n alignItems: atFontScaleBreakpoint ? 'flex-start' : 'center',\n justifyContent: 'space-between',\n paddingBottom: atFontScaleBreakpoint ? 4 : 0,\n paddingHorizontal: ROW_PADDING_HORIZONTAL,\n },\n titleContainer: {\n gap: 8,\n },\n actionsContainer: {\n flexDirection: 'row',\n gap: 8,\n alignItems: 'center',\n },\n markAllReadRow: {\n paddingBottom: 4,\n },\n filterRow: {\n flexDirection: 'row',\n justifyContent: 'flex-start',\n gap: 8,\n paddingHorizontal: ROW_PADDING_HORIZONTAL,\n },\n })\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"conversations_screen.d.ts","sourceRoot":"","sources":["../../../src/screens/conversations/conversations_screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAiB,MAAM,0BAA0B,CAAA;AAC3E,OAAO,KAAsB,MAAM,OAAO,CAAA;AAM1C,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAA;AAK9D,MAAM,MAAM,wBAAwB,GAAG,iBAAiB,CAAC;IACvD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAChC,CAAC,CAAA;AAEF,wBAAgB,mBAAmB,CAAC,EAAE,KAAK,EAAE,EAAE,wBAAwB,qBA2DtE"}
1
+ {"version":3,"file":"conversations_screen.d.ts","sourceRoot":"","sources":["../../../src/screens/conversations/conversations_screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAA;AAG9D,MAAM,MAAM,wBAAwB,GAAG,iBAAiB,CAAC;IACvD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAChC,CAAC,CAAA;AAEF,wBAAgB,mBAAmB,CAAC,EAAE,KAAK,EAAE,EAAE,wBAAwB,qBAYtE"}
@@ -1,64 +1,18 @@
1
- import { useNavigation } from '@react-navigation/native';
2
- import React, { useCallback } from 'react';
1
+ import React from 'react';
3
2
  import { StyleSheet, View } from 'react-native';
4
- import { Conversations, TextButton } from '../../components';
5
- import { ActionButton } from '../../components/display/action_button';
3
+ import { Conversations } from '../../components';
6
4
  import { ConversationsContextProvider } from '../../contexts/conversations_context';
7
- import { useCanCreateConversations, usePublishProductAnalyticsEvent } from '../../hooks';
8
- import { destructureChatGroupGraphId, MAX_FONT_SIZE_MULTIPLIER_LANDMARK } from '../../utils';
5
+ import { usePublishProductAnalyticsEvent } from '../../hooks';
9
6
  import { ListHeaderComponent } from './components/list_header_component';
10
- import { useAppName } from '../../hooks/use_app_name';
11
7
  export function ConversationsScreen({ route }) {
12
- const navigation = useNavigation();
13
- const canCreateConversations = useCanCreateConversations();
14
8
  const styles = useStyles();
15
- const appName = useAppName();
16
- const { chat_group_graph_id } = route.params || {};
17
- const { sourceAppName, sourceId } = destructureChatGroupGraphId(chat_group_graph_id);
18
- const handleNewConversationNavigation = () => {
19
- if (sourceAppName === 'Services') {
20
- return navigation.navigate('New', {
21
- screen: 'ConversationNew',
22
- params: {
23
- team_ids: sourceId ? [sourceId] : [],
24
- source_app_name: sourceAppName,
25
- ...route.params,
26
- },
27
- });
28
- }
29
- if (sourceAppName === 'Groups') {
30
- return navigation.navigate('New', {
31
- screen: 'ConversationNew',
32
- params: {
33
- group_id: sourceId,
34
- source_app_name: sourceAppName,
35
- ...route.params,
36
- },
37
- });
38
- }
39
- return navigation.navigate('New', {
40
- screen: 'ConversationSelectRecipients',
41
- params: {
42
- ...route.params,
43
- },
44
- });
45
- };
46
- const handleGetHelp = useCallback(() => {
47
- navigation.navigate('GetHelp', { type: 'chat' });
48
- }, [navigation]);
49
9
  usePublishProductAnalyticsEvent('chat.mobile.conversations.index.opened');
50
10
  return (<View style={styles.container}>
51
11
  <ConversationsContextProvider args={route.params}>
52
12
  <Conversations ListHeaderComponent={ListHeaderComponent}/>
53
13
  </ConversationsContextProvider>
54
- <ActionButton visible={canCreateConversations} title="New conversation" onPress={handleNewConversationNavigation} buttonIconNameLeft="churchCenter.signups" secondaryButton={appName === 'services' ? null : <GetHelpButton onPress={handleGetHelp}/>}/>
55
14
  </View>);
56
15
  }
57
- const GetHelpButton = ({ onPress }) => {
58
- return (<TextButton variant="tertiary" onPress={onPress} maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK} accessibilityShowsLargeContentViewer accessibilityLargeContentTitle="Get help">
59
- Get help
60
- </TextButton>);
61
- };
62
16
  const useStyles = () => {
63
17
  return StyleSheet.create({
64
18
  container: {
@@ -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, { useCallback } 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, usePublishProductAnalyticsEvent } from '../../hooks'\nimport { AppName } from '../../types/resources/app_name'\nimport { GraphId } from '../../types/resources/group_resource'\nimport { destructureChatGroupGraphId, MAX_FONT_SIZE_MULTIPLIER_LANDMARK } from '../../utils'\nimport { ListHeaderComponent } from './components/list_header_component'\nimport { useAppName } from '../../hooks/use_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 const appName = useAppName()\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 handleGetHelp = useCallback(() => {\n navigation.navigate('GetHelp', { type: 'chat' })\n }, [navigation])\n\n usePublishProductAnalyticsEvent('chat.mobile.conversations.index.opened')\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={appName === 'services' ? null : <GetHelpButton onPress={handleGetHelp} />}\n />\n </View>\n )\n}\n\nconst GetHelpButton = ({ onPress }: { onPress: () => void }) => {\n return (\n <TextButton\n variant=\"tertiary\"\n onPress={onPress}\n maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}\n accessibilityShowsLargeContentViewer\n accessibilityLargeContentTitle=\"Get help\"\n >\n Get help\n </TextButton>\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":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAA;AACnF,OAAO,EAAE,+BAA+B,EAAE,MAAM,aAAa,CAAA;AAG7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAA;AAQxE,MAAM,UAAU,mBAAmB,CAAC,EAAE,KAAK,EAA4B;IACrE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,+BAA+B,CAAC,wCAAwC,CAAC,CAAA;IAEzE,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAC5B;MAAA,CAAC,4BAA4B,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAC/C;QAAA,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC,mBAAmB,CAAC,EAC1D;MAAA,EAAE,4BAA4B,CAChC;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE;YACT,IAAI,EAAE,CAAC;YACP,cAAc,EAAE,QAAQ;SACzB;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import { StaticScreenProps } from '@react-navigation/native'\nimport React from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { Conversations } from '../../components'\nimport { ConversationsContextProvider } from '../../contexts/conversations_context'\nimport { usePublishProductAnalyticsEvent } from '../../hooks'\nimport { AppName } from '../../types/resources/app_name'\nimport { GraphId } from '../../types/resources/group_resource'\nimport { ListHeaderComponent } from './components/list_header_component'\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 styles = useStyles()\n\n usePublishProductAnalyticsEvent('chat.mobile.conversations.index.opened')\n\n return (\n <View style={styles.container}>\n <ConversationsContextProvider args={route.params}>\n <Conversations ListHeaderComponent={ListHeaderComponent} />\n </ConversationsContextProvider>\n </View>\n )\n}\n\nconst useStyles = () => {\n return StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n },\n })\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planningcenter/chat-react-native",
3
- "version": "3.22.0",
3
+ "version": "3.23.0-rc.0",
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": "e3f6bdda7bac0715b030e841280ac34e3dabf7e5"
61
+ "gitHead": "f605c9a6427e283a34ef21e39b41849832b0d0cb"
62
62
  }
@@ -0,0 +1,76 @@
1
+ import React from 'react'
2
+ import { Pressable, StyleSheet } from 'react-native'
3
+ import type { PressableProps } from 'react-native'
4
+ import { Icon, type IconString } from '../../../components/display/icon'
5
+ import { useTheme, useFontScale, useCreateAndroidRippleColor } from '../../../hooks'
6
+ import { platformPressedOpacityStyle } from '../../../utils'
7
+ import { tokens } from '../../../vendor/tapestry/tokens'
8
+
9
+ interface ListHeaderActionButtonProps extends PressableProps {
10
+ /**
11
+ * Provides context to screen readers about what the button does.
12
+ */
13
+ accessibilityLabel: string
14
+ /**
15
+ * Specifies the maximum size a font can reach when allowFontScaling is enabled.
16
+ */
17
+ maxFontSizeMultiplier?: number
18
+ /**
19
+ * Generates an icon from `@planningcenter/icons`
20
+ */
21
+ name: IconString
22
+ }
23
+
24
+ export function ListHeaderActionButton({
25
+ accessibilityLabel,
26
+ maxFontSizeMultiplier,
27
+ name,
28
+ ...props
29
+ }: ListHeaderActionButtonProps) {
30
+ const styles = useStyles({ maxFontSizeMultiplier })
31
+ const { colors } = useTheme()
32
+ const androidRippleColor = useCreateAndroidRippleColor({
33
+ color: colors.iconColorDefaultSecondary,
34
+ })
35
+
36
+ return (
37
+ <Pressable
38
+ style={({ pressed }) => [styles.pressable, pressed && platformPressedOpacityStyle]}
39
+ accessibilityRole="button"
40
+ accessibilityLabel={accessibilityLabel}
41
+ android_ripple={{
42
+ color: androidRippleColor,
43
+ borderless: false,
44
+ foreground: true,
45
+ }}
46
+ {...props}
47
+ >
48
+ <Icon name={name} style={styles.icon} maxFontSizeMultiplier={maxFontSizeMultiplier} />
49
+ </Pressable>
50
+ )
51
+ }
52
+
53
+ const useStyles = ({ maxFontSizeMultiplier }: Partial<ListHeaderActionButtonProps>) => {
54
+ const { colors, button } = useTheme()
55
+ const fontScale = useFontScale({ maxFontSizeMultiplier })
56
+
57
+ return StyleSheet.create({
58
+ pressable: {
59
+ borderRadius: button.borderRadius * fontScale,
60
+ borderWidth: 1,
61
+ borderColor: colors.borderColorDefaultBase,
62
+ backgroundColor: 'transparent',
63
+ paddingHorizontal: 16 * fontScale,
64
+ flexDirection: 'row',
65
+ alignItems: 'center',
66
+ justifyContent: 'center',
67
+ height: 32 * fontScale,
68
+ gap: 6 * fontScale,
69
+ overflow: 'hidden',
70
+ },
71
+ icon: {
72
+ fontSize: tokens.fontSizeSm * fontScale,
73
+ color: colors.iconColorDefaultSecondary,
74
+ },
75
+ })
76
+ }
@@ -5,10 +5,13 @@ import { Heading, TextButton, ToggleButton } from '../../../components'
5
5
  import { useAtFontScaleBreakpoint, useCurrentPersonCache, useTheme } from '../../../hooks'
6
6
  import { useMarkAllRead } from '../../../hooks/use_conversations_actions'
7
7
  import { useCanDisplayGroups } from '../../../hooks/use_groups'
8
+ import { useCanCreateConversations } from '../../../hooks'
9
+ import { useAppName } from '../../../hooks/use_app_name'
8
10
  import { ConversationsScreenProps } from '../conversations_screen'
9
11
  import { ChatGroupBadge } from './chat_group_badge'
10
12
  import { Haptic } from '../../../utils/native_adapters'
11
13
  import { MAX_FONT_SIZE_MULTIPLIER_LANDMARK } from '../../../utils'
14
+ import { ListHeaderActionButton } from './list_header_action_button'
12
15
 
13
16
  const ROW_PADDING_HORIZONTAL = 16
14
17
 
@@ -28,6 +31,8 @@ export const ListHeaderComponent = () => {
28
31
  const { chat_group_graph_id, group_source_app_name = '' } = route.params || {}
29
32
  const currentPersonCache = useCurrentPersonCache()
30
33
  const { markAllRead, isPending } = useMarkAllRead()
34
+ const canCreateConversations = useCanCreateConversations()
35
+ const appName = useAppName()
31
36
 
32
37
  const active: FilterTypes = useMemo(() => {
33
38
  if (chat_group_graph_id) {
@@ -41,6 +46,19 @@ export const ListHeaderComponent = () => {
41
46
  return FilterTypes.All
42
47
  }, [chat_group_graph_id, group_source_app_name])
43
48
 
49
+ const handleNewConversationNavigation = useCallback(() => {
50
+ return navigation.navigate('New', {
51
+ screen: 'ConversationSelectRecipients',
52
+ params: {
53
+ ...route.params,
54
+ },
55
+ })
56
+ }, [navigation, route.params])
57
+
58
+ const handleGetHelp = useCallback(() => {
59
+ navigation.navigate('GetHelp', { type: 'chat' })
60
+ }, [navigation])
61
+
44
62
  const handleMarkAllRead = useCallback(() => {
45
63
  currentPersonCache.update({ unreadCount: 0 })
46
64
  Haptic.notificationSuccess()
@@ -60,19 +78,40 @@ export const ListHeaderComponent = () => {
60
78
 
61
79
  return (
62
80
  <View style={styles.listHeader}>
63
- <View style={styles.titleRow}>
64
- <Heading numberOfLines={1} variant="h2">
65
- Conversations
66
- </Heading>
67
- <TextButton
68
- onPress={alertMarkAllRead}
69
- disabled={isPending}
70
- maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}
71
- accessibilityShowsLargeContentViewer
72
- accessibilityLargeContentTitle="Mark all read"
73
- >
74
- Mark all read
75
- </TextButton>
81
+ <View style={styles.headingRow}>
82
+ <View style={styles.titleContainer}>
83
+ <Heading numberOfLines={1} variant="h2">
84
+ Conversations
85
+ </Heading>
86
+ <TextButton
87
+ onPress={alertMarkAllRead}
88
+ disabled={isPending}
89
+ maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}
90
+ accessibilityShowsLargeContentViewer
91
+ accessibilityLargeContentTitle="Mark all read"
92
+ >
93
+ Mark all read
94
+ </TextButton>
95
+ </View>
96
+ <View style={styles.actionsContainer}>
97
+ {canCreateConversations && (
98
+ <ListHeaderActionButton
99
+ name="churchCenter.signups"
100
+ onPress={handleNewConversationNavigation}
101
+ accessibilityLabel="New conversation"
102
+ testID="conversations-new-conversation-button"
103
+ maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}
104
+ />
105
+ )}
106
+ {appName !== 'services' && (
107
+ <ListHeaderActionButton
108
+ name="general.outlinedInfoCircle"
109
+ onPress={handleGetHelp}
110
+ accessibilityLabel="Get help"
111
+ maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}
112
+ />
113
+ )}
114
+ </View>
76
115
  </View>
77
116
  <ScrollView
78
117
  horizontal
@@ -145,19 +184,27 @@ const useStyles = () => {
145
184
  borderBottomWidth: 1,
146
185
  borderBottomColor: theme.colors.fillColorNeutral050Base,
147
186
  paddingBottom: 16,
148
- gap: 12,
187
+ gap: 16,
149
188
  },
150
- titleRow: {
189
+ headingRow: {
190
+ gap: 12,
151
191
  flexDirection: atFontScaleBreakpoint ? 'column' : 'row',
152
- justifyContent: 'space-between',
153
192
  alignItems: atFontScaleBreakpoint ? 'flex-start' : 'center',
154
- flexWrap: 'wrap',
155
- rowGap: 8,
156
- columnGap: 16,
157
- paddingTop: 8,
193
+ justifyContent: 'space-between',
158
194
  paddingBottom: atFontScaleBreakpoint ? 4 : 0,
159
195
  paddingHorizontal: ROW_PADDING_HORIZONTAL,
160
196
  },
197
+ titleContainer: {
198
+ gap: 8,
199
+ },
200
+ actionsContainer: {
201
+ flexDirection: 'row',
202
+ gap: 8,
203
+ alignItems: 'center',
204
+ },
205
+ markAllReadRow: {
206
+ paddingBottom: 4,
207
+ },
161
208
  filterRow: {
162
209
  flexDirection: 'row',
163
210
  justifyContent: 'flex-start',
@@ -1,15 +1,12 @@
1
- import { StaticScreenProps, useNavigation } from '@react-navigation/native'
2
- import React, { useCallback } from 'react'
1
+ import { StaticScreenProps } from '@react-navigation/native'
2
+ import React from 'react'
3
3
  import { StyleSheet, View } from 'react-native'
4
- import { Conversations, TextButton } from '../../components'
5
- import { ActionButton } from '../../components/display/action_button'
4
+ import { Conversations } from '../../components'
6
5
  import { ConversationsContextProvider } from '../../contexts/conversations_context'
7
- import { useCanCreateConversations, usePublishProductAnalyticsEvent } from '../../hooks'
6
+ import { usePublishProductAnalyticsEvent } from '../../hooks'
8
7
  import { AppName } from '../../types/resources/app_name'
9
8
  import { GraphId } from '../../types/resources/group_resource'
10
- import { destructureChatGroupGraphId, MAX_FONT_SIZE_MULTIPLIER_LANDMARK } from '../../utils'
11
9
  import { ListHeaderComponent } from './components/list_header_component'
12
- import { useAppName } from '../../hooks/use_app_name'
13
10
 
14
11
  export type ConversationsScreenProps = StaticScreenProps<{
15
12
  title?: string
@@ -18,47 +15,7 @@ export type ConversationsScreenProps = StaticScreenProps<{
18
15
  }>
19
16
 
20
17
  export function ConversationsScreen({ route }: ConversationsScreenProps) {
21
- const navigation = useNavigation()
22
- const canCreateConversations = useCanCreateConversations()
23
18
  const styles = useStyles()
24
- const appName = useAppName()
25
-
26
- const { chat_group_graph_id } = route.params || {}
27
- const { sourceAppName, sourceId } = destructureChatGroupGraphId(chat_group_graph_id)
28
-
29
- const handleNewConversationNavigation = () => {
30
- if (sourceAppName === 'Services') {
31
- return navigation.navigate('New', {
32
- screen: 'ConversationNew',
33
- params: {
34
- team_ids: sourceId ? [sourceId] : [],
35
- source_app_name: sourceAppName,
36
- ...route.params,
37
- },
38
- })
39
- }
40
- if (sourceAppName === 'Groups') {
41
- return navigation.navigate('New', {
42
- screen: 'ConversationNew',
43
- params: {
44
- group_id: sourceId,
45
- source_app_name: sourceAppName,
46
- ...route.params,
47
- },
48
- })
49
- }
50
-
51
- return navigation.navigate('New', {
52
- screen: 'ConversationSelectRecipients',
53
- params: {
54
- ...route.params,
55
- },
56
- })
57
- }
58
-
59
- const handleGetHelp = useCallback(() => {
60
- navigation.navigate('GetHelp', { type: 'chat' })
61
- }, [navigation])
62
19
 
63
20
  usePublishProductAnalyticsEvent('chat.mobile.conversations.index.opened')
64
21
 
@@ -67,31 +24,10 @@ export function ConversationsScreen({ route }: ConversationsScreenProps) {
67
24
  <ConversationsContextProvider args={route.params}>
68
25
  <Conversations ListHeaderComponent={ListHeaderComponent} />
69
26
  </ConversationsContextProvider>
70
- <ActionButton
71
- visible={canCreateConversations}
72
- title="New conversation"
73
- onPress={handleNewConversationNavigation}
74
- buttonIconNameLeft="churchCenter.signups"
75
- secondaryButton={appName === 'services' ? null : <GetHelpButton onPress={handleGetHelp} />}
76
- />
77
27
  </View>
78
28
  )
79
29
  }
80
30
 
81
- const GetHelpButton = ({ onPress }: { onPress: () => void }) => {
82
- return (
83
- <TextButton
84
- variant="tertiary"
85
- onPress={onPress}
86
- maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}
87
- accessibilityShowsLargeContentViewer
88
- accessibilityLargeContentTitle="Get help"
89
- >
90
- Get help
91
- </TextButton>
92
- )
93
- }
94
-
95
31
  const useStyles = () => {
96
32
  return StyleSheet.create({
97
33
  container: {