@planningcenter/chat-react-native 3.7.1-rc.0 → 3.7.1-rc.2

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 (44) hide show
  1. package/build/components/primitive/form_sheet.d.ts +4 -2
  2. package/build/components/primitive/form_sheet.d.ts.map +1 -1
  3. package/build/components/primitive/form_sheet.js +3 -3
  4. package/build/components/primitive/form_sheet.js.map +1 -1
  5. package/build/navigation/index.d.ts +2 -2
  6. package/build/screens/conversation_filter_recipients/components/checkbox_row.d.ts +3 -2
  7. package/build/screens/conversation_filter_recipients/components/checkbox_row.d.ts.map +1 -1
  8. package/build/screens/conversation_filter_recipients/components/checkbox_row.js +1 -3
  9. package/build/screens/conversation_filter_recipients/components/checkbox_row.js.map +1 -1
  10. package/build/screens/conversation_filter_recipients/components/header_row.d.ts +3 -2
  11. package/build/screens/conversation_filter_recipients/components/header_row.d.ts.map +1 -1
  12. package/build/screens/conversation_filter_recipients/components/header_row.js +1 -3
  13. package/build/screens/conversation_filter_recipients/components/header_row.js.map +1 -1
  14. package/build/screens/conversation_filter_recipients/conversation_filter_recipients_screen.d.ts +2 -3
  15. package/build/screens/conversation_filter_recipients/conversation_filter_recipients_screen.d.ts.map +1 -1
  16. package/build/screens/conversation_filter_recipients/conversation_filter_recipients_screen.js +40 -39
  17. package/build/screens/conversation_filter_recipients/conversation_filter_recipients_screen.js.map +1 -1
  18. package/build/screens/conversation_filter_recipients/types.d.ts +3 -0
  19. package/build/screens/conversation_filter_recipients/types.d.ts.map +1 -1
  20. package/build/screens/conversation_filter_recipients/types.js.map +1 -1
  21. package/build/screens/message_actions_screen.js +3 -2
  22. package/build/screens/message_actions_screen.js.map +1 -1
  23. package/build/screens/reactions_screen.d.ts +1 -2
  24. package/build/screens/reactions_screen.d.ts.map +1 -1
  25. package/build/screens/reactions_screen.js +51 -37
  26. package/build/screens/reactions_screen.js.map +1 -1
  27. package/package.json +2 -2
  28. package/src/components/primitive/form_sheet.tsx +7 -3
  29. package/src/screens/conversation_filter_recipients/components/checkbox_row.tsx +8 -4
  30. package/src/screens/conversation_filter_recipients/components/header_row.tsx +7 -4
  31. package/src/screens/conversation_filter_recipients/conversation_filter_recipients_screen.tsx +97 -70
  32. package/src/screens/conversation_filter_recipients/types.tsx +2 -0
  33. package/src/screens/message_actions_screen.tsx +3 -2
  34. package/src/screens/reactions_screen.tsx +59 -41
  35. package/build/screens/conversation_filter_recipients/components/navigation_header.d.ts +0 -5
  36. package/build/screens/conversation_filter_recipients/components/navigation_header.d.ts.map +0 -1
  37. package/build/screens/conversation_filter_recipients/components/navigation_header.js +0 -46
  38. package/build/screens/conversation_filter_recipients/components/navigation_header.js.map +0 -1
  39. package/build/screens/conversation_filter_recipients/context/conversation_filter_recipients_context.d.ts +0 -17
  40. package/build/screens/conversation_filter_recipients/context/conversation_filter_recipients_context.d.ts.map +0 -1
  41. package/build/screens/conversation_filter_recipients/context/conversation_filter_recipients_context.js +0 -37
  42. package/build/screens/conversation_filter_recipients/context/conversation_filter_recipients_context.js.map +0 -1
  43. package/src/screens/conversation_filter_recipients/components/navigation_header.tsx +0 -68
  44. package/src/screens/conversation_filter_recipients/context/conversation_filter_recipients_context.tsx +0 -53
@@ -1,19 +1,22 @@
1
- import React from 'react';
2
- import { StyleSheet, useWindowDimensions, View } from 'react-native';
1
+ import React, { memo } from 'react';
2
+ import { Platform, StyleSheet, View } from 'react-native';
3
+ import { FlatList } from 'react-native-gesture-handler';
3
4
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
4
5
  import { Avatar, Text } from '../components';
5
- import { REACTION_EMOJIS, useReactionStyles } from '../components/conversation/message_reaction';
6
+ import { REACTION_EMOJIS } from '../components/conversation/message_reaction';
6
7
  import { Tabs } from '../components/display/tabs';
7
8
  import { useSuspenseGet, useTheme } from '../hooks';
8
9
  import { useConversationMessages } from '../hooks/use_conversation_messages';
9
- import { FlashList } from '@shopify/flash-list';
10
- export const ReactionsScreenOptions = {
11
- presentation: 'formSheet',
12
- headerShown: false,
13
- sheetAllowedDetents: [0.5],
14
- sheetGrabberVisible: true,
15
- sheetCornerRadius: 16,
16
- };
10
+ import FormSheet, { getFormSheetScreenOptions } from '../components/primitive/form_sheet';
11
+ import { platformFontWeightMedium } from '../utils';
12
+ import { useFontScale } from '../hooks/use_font_scale';
13
+ export const ReactionsScreenOptions = getFormSheetScreenOptions({
14
+ sheetAllowedDetents: Platform.select({
15
+ android: [0.5, 0.94], // Going straight to full 0.94 preserves height of screen on Android
16
+ default: [0.5, 1],
17
+ }),
18
+ headerTitle: 'Reactions',
19
+ });
17
20
  export function ReactionsScreen({ route }) {
18
21
  const { conversation_id, message_id, reaction_value } = route.params;
19
22
  const styles = useStyles();
@@ -38,54 +41,65 @@ export function ReactionsScreen({ route }) {
38
41
  }
39
42
  const authorIds = reactionCount.authorIds;
40
43
  const authors = members.filter(member => authorIds.includes(member.id));
41
- return (<View style={styles.container}>
44
+ return (<FormSheet.Root contentStyle={styles.formSheetContent}>
42
45
  <Tabs data={reactionCounts} activeTab={reactionCount} onTabPress={item => {
43
46
  setReactionCountValue(item.value);
44
47
  }} renderItem={({ item }) => (<Reaction active={reactionCount.id === item.id} reaction={item} onPress={() => setReactionCountValue(item.value)}/>)} style={styles.actions}/>
45
- <FlashList data={authors} keyExtractor={item => item.id.toString()} renderItem={({ item: author }) => (<View style={styles.authorList}>
46
- <Avatar size={'md'} sourceUri={author.avatar}/>
47
- <Text key={author.id}>{author.name}</Text>
48
- </View>)}/>
49
- </View>);
48
+ <FlatList data={authors} contentContainerStyle={styles.contentContainer} keyExtractor={item => item.id.toString()} renderItem={({ item: author }) => <Author author={author} key={author.id}/>}/>
49
+ </FormSheet.Root>);
50
50
  }
51
51
  const Reaction = ({ reaction, }) => {
52
52
  const styles = useStyles();
53
- const reactionStyles = useReactionStyles({ mine: reaction.mine ? 1 : 0 });
54
53
  return (<View key={reaction.value} style={styles.reaction}>
55
- <Text style={reactionStyles.reactionEmoji}>{REACTION_EMOJIS[reaction.value]}</Text>
56
- <Text style={reactionStyles.reactionEmoji}>{reaction.count}</Text>
54
+ <Text style={styles.reactionContent}>{REACTION_EMOJIS[reaction.value]}</Text>
55
+ <Text style={styles.reactionContent}>{reaction.count}</Text>
57
56
  </View>);
58
57
  };
58
+ const Author = memo(({ author }) => {
59
+ const styles = useStyles();
60
+ return (<View style={styles.authorRow}>
61
+ <Avatar sourceUri={author.avatar} size="sm"/>
62
+ <Text variant="tertiary" numberOfLines={2} style={styles.authorName}>
63
+ {author.name}
64
+ </Text>
65
+ </View>);
66
+ });
59
67
  const useStyles = () => {
60
- const theme = useTheme();
61
- const { height } = useWindowDimensions();
68
+ const { colors } = useTheme();
62
69
  const { bottom } = useSafeAreaInsets();
70
+ const fontScale = useFontScale({ maxFontSizeMultiplier: 1.3 });
63
71
  return StyleSheet.create({
64
- container: {
65
- justifyContent: 'flex-start',
66
- paddingTop: 12,
67
- paddingBottom: bottom,
68
- width: '100%',
69
- backgroundColor: theme.colors.fillColorNeutral100Inverted,
70
- height,
71
- gap: 8,
72
+ formSheetContent: {
73
+ paddingTop: Platform.select({ android: 4, default: 16 }),
72
74
  },
73
- authorList: {
75
+ contentContainer: {
76
+ paddingTop: 8,
77
+ paddingBottom: bottom + Platform.select({ android: 24, default: 16 }),
78
+ },
79
+ authorRow: {
74
80
  flexDirection: 'row',
75
81
  alignItems: 'center',
76
82
  gap: 8,
77
- paddingHorizontal: 12,
78
- paddingVertical: 12,
83
+ paddingVertical: 8,
84
+ paddingHorizontal: 16,
85
+ flex: 1,
86
+ },
87
+ authorName: {
88
+ flex: 1,
79
89
  },
80
90
  reaction: {
81
- paddingVertical: 12,
82
- paddingHorizontal: 12,
91
+ paddingHorizontal: 8,
92
+ paddingVertical: 16,
83
93
  flexDirection: 'row',
84
94
  gap: 4,
85
95
  },
96
+ reactionContent: {
97
+ fontSize: 18,
98
+ fontWeight: platformFontWeightMedium,
99
+ },
86
100
  actions: {
87
- minHeight: 48,
88
- borderBottomColor: theme.colors.fillColorNeutral040,
101
+ minHeight: 68 * fontScale,
102
+ borderBottomColor: colors.borderColorDefaultBase,
89
103
  borderBottomWidth: 1,
90
104
  },
91
105
  errorContainer: {
@@ -1 +1 @@
1
- {"version":3,"file":"reactions_screen.js","sourceRoot":"","sources":["../../src/screens/reactions_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { StaticScreenProps } from '@react-navigation/native'\nimport { NativeStackNavigationOptions } from '@react-navigation/native-stack'\nimport React from 'react'\nimport { StyleSheet, useWindowDimensions, View } from 'react-native'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { Avatar, Text } from '../components'\nimport { REACTION_EMOJIS, useReactionStyles } from '../components/conversation/message_reaction'\nimport { Tabs } from '../components/display/tabs'\nimport { useSuspenseGet, useTheme } from '../hooks'\nimport { useConversationMessages } from '../hooks/use_conversation_messages'\nimport { MemberResource } from '../types'\nimport { ReactionCountResource } from '../types/resources/reaction'\nimport { FlashList } from '@shopify/flash-list'\n\nexport const ReactionsScreenOptions: NativeStackNavigationOptions = {\n presentation: 'formSheet',\n headerShown: false,\n sheetAllowedDetents: [0.5],\n sheetGrabberVisible: true,\n sheetCornerRadius: 16,\n}\n\nexport type ReactionScreenProps = StaticScreenProps<{\n message_id: string\n conversation_id: number\n reaction_value?: string\n}>\n\nexport function ReactionsScreen({ route }: ReactionScreenProps) {\n const { conversation_id, message_id, reaction_value } = route.params\n const styles = useStyles()\n\n const { messages } = useConversationMessages({ conversation_id }, { refetchOnMount: false })\n const { data: members } = useSuspenseGet<MemberResource[]>({\n url: `/me/conversations/${conversation_id}/members`,\n data: {\n fields: {\n Member: ['id', 'name', 'avatar', 'badges', 'child', 'role'],\n },\n },\n })\n const message = messages.find(m => m.id === message_id)\n const reactionCounts = message?.reactionCounts || []\n const initialReactionCount =\n reactionCounts.find(r => r.value === reaction_value) || reactionCounts[0]\n const [reactionCountValue, setReactionCountValue] = React.useState<\n ReactionCountResource['value']\n >(initialReactionCount.value)\n const reactionCount = reactionCounts.find(r => r.value === reactionCountValue)\n\n if (!reactionCount) {\n return (\n <View style={styles.errorContainer}>\n <Text>No reactions found for this message.</Text>\n </View>\n )\n }\n\n const authorIds = reactionCount.authorIds\n const authors = members.filter(member => authorIds.includes(member.id))\n\n return (\n <View style={styles.container}>\n <Tabs\n data={reactionCounts}\n activeTab={reactionCount}\n onTabPress={item => {\n setReactionCountValue(item.value)\n }}\n renderItem={({ item }) => (\n <Reaction\n active={reactionCount.id === item.id}\n reaction={item}\n onPress={() => setReactionCountValue(item.value)}\n />\n )}\n style={styles.actions}\n />\n <FlashList\n data={authors}\n keyExtractor={item => item.id.toString()}\n renderItem={({ item: author }) => (\n <View style={styles.authorList}>\n <Avatar size={'md'} sourceUri={author.avatar} />\n <Text key={author.id}>{author.name}</Text>\n </View>\n )}\n />\n </View>\n )\n}\n\nconst Reaction = ({\n reaction,\n}: {\n active: boolean\n reaction: ReactionCountResource\n onPress: () => void\n}) => {\n const styles = useStyles()\n const reactionStyles = useReactionStyles({ mine: reaction.mine ? 1 : 0 })\n\n return (\n <View key={reaction.value} style={styles.reaction}>\n <Text style={reactionStyles.reactionEmoji}>{REACTION_EMOJIS[reaction.value]}</Text>\n <Text style={reactionStyles.reactionEmoji}>{reaction.count}</Text>\n </View>\n )\n}\n\nconst useStyles = () => {\n const theme = useTheme()\n const { height } = useWindowDimensions()\n const { bottom } = useSafeAreaInsets()\n\n return StyleSheet.create({\n container: {\n justifyContent: 'flex-start',\n paddingTop: 12,\n paddingBottom: bottom,\n width: '100%',\n backgroundColor: theme.colors.fillColorNeutral100Inverted,\n height,\n gap: 8,\n },\n authorList: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 8,\n paddingHorizontal: 12,\n paddingVertical: 12,\n },\n reaction: {\n paddingVertical: 12,\n paddingHorizontal: 12,\n flexDirection: 'row',\n gap: 4,\n },\n actions: {\n minHeight: 48,\n borderBottomColor: theme.colors.fillColorNeutral040,\n borderBottomWidth: 1,\n },\n errorContainer: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n padding: 16,\n marginTop: 30,\n },\n })\n}\n"]}
1
+ {"version":3,"file":"reactions_screen.js","sourceRoot":"","sources":["../../src/screens/reactions_screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import { StaticScreenProps } from '@react-navigation/native'\nimport React, { memo } from 'react'\nimport { Platform, StyleSheet, View } from 'react-native'\nimport { FlatList } from 'react-native-gesture-handler'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { Avatar, Text } from '../components'\nimport { REACTION_EMOJIS } from '../components/conversation/message_reaction'\nimport { Tabs } from '../components/display/tabs'\nimport { useSuspenseGet, useTheme } from '../hooks'\nimport { useConversationMessages } from '../hooks/use_conversation_messages'\nimport { MemberResource } from '../types'\nimport { ReactionCountResource } from '../types/resources/reaction'\nimport FormSheet, { getFormSheetScreenOptions } from '../components/primitive/form_sheet'\nimport { platformFontWeightMedium } from '../utils'\nimport { useFontScale } from '../hooks/use_font_scale'\n\nexport const ReactionsScreenOptions = getFormSheetScreenOptions({\n sheetAllowedDetents: Platform.select({\n android: [0.5, 0.94], // Going straight to full 0.94 preserves height of screen on Android\n default: [0.5, 1],\n }),\n headerTitle: 'Reactions',\n})\n\nexport type ReactionScreenProps = StaticScreenProps<{\n message_id: string\n conversation_id: number\n reaction_value?: string\n}>\n\nexport function ReactionsScreen({ route }: ReactionScreenProps) {\n const { conversation_id, message_id, reaction_value } = route.params\n const styles = useStyles()\n\n const { messages } = useConversationMessages({ conversation_id }, { refetchOnMount: false })\n const { data: members } = useSuspenseGet<MemberResource[]>({\n url: `/me/conversations/${conversation_id}/members`,\n data: {\n fields: {\n Member: ['id', 'name', 'avatar', 'badges', 'child', 'role'],\n },\n },\n })\n const message = messages.find(m => m.id === message_id)\n const reactionCounts = message?.reactionCounts || []\n const initialReactionCount =\n reactionCounts.find(r => r.value === reaction_value) || reactionCounts[0]\n const [reactionCountValue, setReactionCountValue] = React.useState<\n ReactionCountResource['value']\n >(initialReactionCount.value)\n const reactionCount = reactionCounts.find(r => r.value === reactionCountValue)\n\n if (!reactionCount) {\n return (\n <View style={styles.errorContainer}>\n <Text>No reactions found for this message.</Text>\n </View>\n )\n }\n\n const authorIds = reactionCount.authorIds\n const authors = members.filter(member => authorIds.includes(member.id))\n\n return (\n <FormSheet.Root contentStyle={styles.formSheetContent}>\n <Tabs\n data={reactionCounts}\n activeTab={reactionCount}\n onTabPress={item => {\n setReactionCountValue(item.value)\n }}\n renderItem={({ item }) => (\n <Reaction\n active={reactionCount.id === item.id}\n reaction={item}\n onPress={() => setReactionCountValue(item.value)}\n />\n )}\n style={styles.actions}\n />\n <FlatList\n data={authors}\n contentContainerStyle={styles.contentContainer}\n keyExtractor={item => item.id.toString()}\n renderItem={({ item: author }) => <Author author={author} key={author.id} />}\n />\n </FormSheet.Root>\n )\n}\n\nconst Reaction = ({\n reaction,\n}: {\n active: boolean\n reaction: ReactionCountResource\n onPress: () => void\n}) => {\n const styles = useStyles()\n\n return (\n <View key={reaction.value} style={styles.reaction}>\n <Text style={styles.reactionContent}>{REACTION_EMOJIS[reaction.value]}</Text>\n <Text style={styles.reactionContent}>{reaction.count}</Text>\n </View>\n )\n}\n\ntype AuthorProps = Pick<MemberResource, 'id' | 'name' | 'avatar'>\n\nconst Author = memo(({ author }: { author: AuthorProps }) => {\n const styles = useStyles()\n\n return (\n <View style={styles.authorRow}>\n <Avatar sourceUri={author.avatar} size=\"sm\" />\n <Text variant=\"tertiary\" numberOfLines={2} style={styles.authorName}>\n {author.name}\n </Text>\n </View>\n )\n})\n\nconst useStyles = () => {\n const { colors } = useTheme()\n const { bottom } = useSafeAreaInsets()\n const fontScale = useFontScale({ maxFontSizeMultiplier: 1.3 })\n\n return StyleSheet.create({\n formSheetContent: {\n paddingTop: Platform.select({ android: 4, default: 16 }),\n },\n contentContainer: {\n paddingTop: 8,\n paddingBottom: bottom + Platform.select({ android: 24, default: 16 }),\n },\n authorRow: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 8,\n paddingVertical: 8,\n paddingHorizontal: 16,\n flex: 1,\n },\n authorName: {\n flex: 1,\n },\n reaction: {\n paddingHorizontal: 8,\n paddingVertical: 16,\n flexDirection: 'row',\n gap: 4,\n },\n reactionContent: {\n fontSize: 18,\n fontWeight: platformFontWeightMedium,\n },\n actions: {\n minHeight: 68 * fontScale,\n borderBottomColor: colors.borderColorDefaultBase,\n borderBottomWidth: 1,\n },\n errorContainer: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n padding: 16,\n marginTop: 30,\n },\n })\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planningcenter/chat-react-native",
3
- "version": "3.7.1-rc.0",
3
+ "version": "3.7.1-rc.2",
4
4
  "description": "",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -55,5 +55,5 @@
55
55
  "prettier": "^3.4.2",
56
56
  "typescript": "<5.6.0"
57
57
  },
58
- "gitHead": "5cf4db13bcc0470ed9bc5f8489b3c2f1ae9493af"
58
+ "gitHead": "77bc347b971eb160e5f56a026899e1633e3113d1"
59
59
  }
@@ -6,6 +6,8 @@ import {
6
6
  View,
7
7
  useWindowDimensions,
8
8
  type AccessibilityRole,
9
+ type StyleProp,
10
+ type ViewStyle,
9
11
  } from 'react-native'
10
12
  import { useSafeAreaInsets } from 'react-native-safe-area-context'
11
13
  import { useTheme } from '../../hooks'
@@ -58,15 +60,17 @@ export type { FormSheetRootProps, FormSheetActionProps, FormSheetHeaderProps }
58
60
 
59
61
  interface FormSheetRootProps {
60
62
  children: ReactNode
63
+ style?: StyleProp<ViewStyle>
64
+ contentStyle?: StyleProp<ViewStyle>
61
65
  }
62
66
 
63
- export function FormSheetRoot({ children }: FormSheetRootProps) {
67
+ export function FormSheetRoot({ children, style, contentStyle }: FormSheetRootProps) {
64
68
  const styles = useStyles()
65
69
 
66
70
  return (
67
- <View style={styles.container} collapsable={false}>
71
+ <View style={[styles.container, style]} collapsable={false}>
68
72
  <AndroidSheetGrabber />
69
- <View style={styles.content}>{children}</View>
73
+ <View style={[styles.content, contentStyle]}>{children}</View>
70
74
  </View>
71
75
  )
72
76
  }
@@ -2,20 +2,24 @@ import { Pressable, View, StyleSheet, type ViewStyle } from 'react-native'
2
2
  import { useTheme } from '../../../hooks'
3
3
  import { Icon, Text } from '../../../components'
4
4
  import { tokens } from '../../../vendor/tapestry/tokens'
5
- import { ConversationFilterRecipientsScreenProps, TeamProps } from '../types'
5
+ import { ConversationFilterRecipientsScreenProps, SetTeamFilters, TeamProps } from '../types'
6
6
  import { type RouteProp, useRoute } from '@react-navigation/native'
7
- import { useFilterRecipientsContext } from '../context/conversation_filter_recipients_context'
8
7
 
9
8
  interface TeamRowProps {
10
9
  data: TeamProps
11
10
  style?: ViewStyle
12
11
  accessibilityLabelledBy: string
12
+ setTeamFilters: SetTeamFilters
13
13
  }
14
14
 
15
- export const CheckboxRow = ({ data, style, accessibilityLabelledBy }: TeamRowProps) => {
15
+ export const CheckboxRow = ({
16
+ data,
17
+ style,
18
+ accessibilityLabelledBy,
19
+ setTeamFilters,
20
+ }: TeamRowProps) => {
16
21
  const styles = useStyles()
17
22
  const route = useRoute<RouteProp<ConversationFilterRecipientsScreenProps['route']>>()
18
- const { setTeamFilters } = useFilterRecipientsContext()
19
23
 
20
24
  const { teamId, teamName } = data
21
25
  const { team_ids: currentTeamIds } = route.params
@@ -1,11 +1,14 @@
1
1
  import { View, StyleSheet, type ViewStyle } from 'react-native'
2
2
  import { useTheme } from '../../../hooks'
3
3
  import { Icon, Heading, TextButton } from '../../../components'
4
- import type { ConversationFilterRecipientsScreenProps, ServiceTypeProps } from '../types'
4
+ import type {
5
+ ConversationFilterRecipientsScreenProps,
6
+ ServiceTypeProps,
7
+ SetTeamFilters,
8
+ } from '../types'
5
9
  import { tokens } from '../../../vendor/tapestry/tokens'
6
10
  import { pluralize } from '../../../utils'
7
11
  import { useRoute, type RouteProp } from '@react-navigation/native'
8
- import { useFilterRecipientsContext } from '../context/conversation_filter_recipients_context'
9
12
 
10
13
  const BULK_SELECT_LIMIT = 10
11
14
 
@@ -13,11 +16,11 @@ interface HeaderRowProps {
13
16
  data: ServiceTypeProps
14
17
  nativeID: string
15
18
  style?: ViewStyle
19
+ setTeamFilters: SetTeamFilters
16
20
  }
17
21
 
18
- export const HeaderRow = ({ data, nativeID, style }: HeaderRowProps) => {
22
+ export const HeaderRow = ({ data, nativeID, style, setTeamFilters }: HeaderRowProps) => {
19
23
  const styles = useStyles()
20
- const { setTeamFilters } = useFilterRecipientsContext()
21
24
  const route = useRoute<RouteProp<ConversationFilterRecipientsScreenProps['route']>>()
22
25
 
23
26
  const { serviceTypeName, teamIdsForServiceType } = data
@@ -1,38 +1,35 @@
1
- import { NativeStackNavigationOptions } from '@react-navigation/native-stack'
2
- import React from 'react'
3
- import { Platform, StyleSheet, useWindowDimensions, View } from 'react-native'
1
+ import { NativeStackNavigationProp } from '@react-navigation/native-stack'
2
+ import React, { useCallback } from 'react'
3
+ import { Platform, StyleSheet } from 'react-native'
4
4
  import { useSafeAreaInsets } from 'react-native-safe-area-context'
5
- import { FlashList } from '@shopify/flash-list'
6
- import { Heading } from '../../components'
5
+ import { FlatList } from 'react-native-gesture-handler'
6
+ import { Button, Heading, TextButton } from '../../components'
7
7
  import { useTheme } from '../../hooks'
8
8
  import { useFlattenedArrayOfServiceTypesWithTeams } from './hooks/use_flattened_array_of_service_types_with_teams'
9
9
  import { ConversationFilterRecipientsScreenProps, SectionTypes } from './types'
10
10
  import { HeaderRow } from './components/header_row'
11
11
  import { tokens } from '../../vendor/tapestry/tokens'
12
12
  import { CheckboxRow } from './components/checkbox_row'
13
- import { useHeaderHeight } from '@react-navigation/elements'
14
- import { FilterRecipientsProvider } from './context/conversation_filter_recipients_context'
15
- import { HeaderRightWithContext, FilterHeaderTitle } from './components/navigation_header'
16
13
  import { useServiceTypesWithTeams } from './hooks/use_service_types_with_teams'
14
+ import { StackActions, useNavigation } from '@react-navigation/native'
15
+ import FormSheet, { getFormSheetScreenOptions } from '../../components/primitive/form_sheet'
17
16
 
18
17
  const SERVICE_TYPE_LABELLED_BY_PREFIX = 'header-'
19
18
 
20
- export const ConversationFilterReceipientsScreenOptions: NativeStackNavigationOptions = {
21
- presentation: Platform.select({ android: 'modal', ios: 'formSheet' }),
19
+ export const ConversationFilterReceipientsScreenOptions = getFormSheetScreenOptions({
22
20
  sheetAllowedDetents: Platform.select({
23
21
  android: [0.75, 0.94],
24
22
  default: [0.75, 1],
25
23
  }),
26
- sheetGrabberVisible: true,
27
- headerBackVisible: false,
28
- headerRight: HeaderRightWithContext,
29
- headerTitle: FilterHeaderTitle,
30
- headerTitleAlign: 'left',
31
- sheetCornerRadius: 16,
32
- }
24
+ headerTitle: 'Teams I lead',
25
+ })
33
26
 
34
- export const ConversationFilterRecipientsScreen = ({}: ConversationFilterRecipientsScreenProps) => {
27
+ export const ConversationFilterRecipientsScreen = ({
28
+ route,
29
+ }: ConversationFilterRecipientsScreenProps) => {
35
30
  const styles = useStyles()
31
+ const navigation =
32
+ useNavigation<NativeStackNavigationProp<ConversationFilterRecipientsScreenProps>>()
36
33
 
37
34
  const { serviceTypes } = useServiceTypesWithTeams()
38
35
  const data = useFlattenedArrayOfServiceTypesWithTeams({
@@ -41,69 +38,99 @@ export const ConversationFilterRecipientsScreen = ({}: ConversationFilterRecipie
41
38
  lastRowStyle: styles.lastRow,
42
39
  })
43
40
 
41
+ const { params } = route
42
+ const noTeamsSelected = params.team_ids?.length === 0 || !params.team_ids
43
+ const applyButtonAccessibilityHint = noTeamsSelected
44
+ ? 'Select at least one team to navigate to the final step in creating your conversation.'
45
+ : 'Saves selected teams and navigates to the final step to create your conversation.'
46
+
47
+ const setTeamFilters = useCallback(
48
+ ({ team_ids }: { team_ids: number[] }) => {
49
+ navigation.setParams({
50
+ team_ids,
51
+ })
52
+ },
53
+ [navigation]
54
+ )
55
+
56
+ const resetTeamFilters = useCallback(() => {
57
+ navigation.goBack()
58
+ }, [navigation])
59
+
60
+ const applyTeamFilters = useCallback(() => {
61
+ navigation.dispatch(StackActions.popTo('ConversationNew', params))
62
+ }, [navigation, params])
63
+
44
64
  return (
45
- <FilterRecipientsProvider>
46
- <View style={styles.listWrapper}>
47
- <FlashList
48
- data={data}
49
- ListHeaderComponent={
50
- <Heading variant="h3" style={styles.listHeader}>
51
- Service Types
52
- </Heading>
65
+ <FormSheet.Root>
66
+ <FormSheet.Header
67
+ title="Teams I lead"
68
+ secondaryButton={
69
+ <TextButton
70
+ onPress={resetTeamFilters}
71
+ accessibilityHint="Cancels any selected teams and closes this modal."
72
+ >
73
+ Cancel
74
+ </TextButton>
75
+ }
76
+ primaryButton={
77
+ <Button
78
+ title="Apply"
79
+ accessibilityHint={applyButtonAccessibilityHint}
80
+ onPress={applyTeamFilters}
81
+ disabled={noTeamsSelected}
82
+ />
83
+ }
84
+ />
85
+ <FlatList
86
+ data={data}
87
+ ListHeaderComponent={
88
+ <Heading variant="h3" style={styles.listHeader}>
89
+ Service Types
90
+ </Heading>
91
+ }
92
+ contentContainerStyle={styles.listContentContainer}
93
+ keyExtractor={item =>
94
+ `${item.type === SectionTypes.header ? item.data.serviceTypeId : item.data.teamId}`
95
+ }
96
+ renderItem={({ item }) => {
97
+ switch (item.type) {
98
+ case SectionTypes.header:
99
+ return (
100
+ <HeaderRow
101
+ data={item.data}
102
+ style={item.sectionStyle}
103
+ nativeID={`${SERVICE_TYPE_LABELLED_BY_PREFIX}${item.data.serviceTypeId}`}
104
+ setTeamFilters={setTeamFilters}
105
+ />
106
+ )
107
+ case SectionTypes.team:
108
+ return (
109
+ <CheckboxRow
110
+ data={item.data}
111
+ style={item.sectionStyle}
112
+ accessibilityLabelledBy={`${SERVICE_TYPE_LABELLED_BY_PREFIX}${item.data.serviceTypeId}`}
113
+ setTeamFilters={setTeamFilters}
114
+ />
115
+ )
116
+ default:
117
+ return null
53
118
  }
54
- estimatedItemSize={50}
55
- contentContainerStyle={styles.listContentContainer}
56
- keyExtractor={item =>
57
- `${item.type === SectionTypes.header ? item.data.serviceTypeId : item.data.teamId}`
58
- }
59
- renderItem={({ item }) => {
60
- switch (item.type) {
61
- case SectionTypes.header:
62
- return (
63
- <HeaderRow
64
- data={item.data}
65
- style={item.sectionStyle}
66
- nativeID={`${SERVICE_TYPE_LABELLED_BY_PREFIX}${item.data.serviceTypeId}`}
67
- />
68
- )
69
- case SectionTypes.team:
70
- return (
71
- <CheckboxRow
72
- data={item.data}
73
- style={item.sectionStyle}
74
- accessibilityLabelledBy={`${SERVICE_TYPE_LABELLED_BY_PREFIX}${item.data.serviceTypeId}`}
75
- />
76
- )
77
- default:
78
- return null
79
- }
80
- }}
81
- />
82
- </View>
83
- </FilterRecipientsProvider>
119
+ }}
120
+ />
121
+ </FormSheet.Root>
84
122
  )
85
123
  }
86
124
 
87
125
  const useStyles = () => {
88
126
  const { colors } = useTheme()
89
- const { top, bottom } = useSafeAreaInsets()
90
- const { height } = useWindowDimensions()
91
- const headerHeight = useHeaderHeight()
92
-
93
- const containerHeight = Platform.select({
94
- android: height,
95
- ios: height - top - headerHeight,
96
- })
127
+ const { bottom } = useSafeAreaInsets()
97
128
 
98
129
  return StyleSheet.create({
99
- listWrapper: {
100
- flex: 1,
101
- height: containerHeight,
102
- backgroundColor: colors.surfaceColor080,
103
- },
104
130
  listContentContainer: {
131
+ backgroundColor: colors.surfaceColor080,
105
132
  padding: 16,
106
- paddingBottom: bottom,
133
+ paddingBottom: bottom + Platform.select({ android: 24, default: 16 }),
107
134
  },
108
135
  listHeader: {
109
136
  paddingBottom: 16,
@@ -45,3 +45,5 @@ export type ConversationFilterRecipientsParams = {
45
45
 
46
46
  export type ConversationFilterRecipientsScreenProps =
47
47
  StaticScreenProps<ConversationFilterRecipientsParams>
48
+
49
+ export type SetTeamFilters = ({ team_ids }: { team_ids: number[] }) => void
@@ -5,7 +5,7 @@ import React, { useCallback } from 'react'
5
5
  import { Alert, Platform, StyleSheet, View } from 'react-native'
6
6
  import { Text } from '../components'
7
7
  import { REACTION_EMOJIS, useReactionStyles } from '../components/conversation/message_reaction'
8
- import { useCreateAndroidRippleColor, useTheme } from '../hooks'
8
+ import { useCreateAndroidRippleColor, useFontScale, useTheme } from '../hooks'
9
9
  import { useApiClient } from '../hooks/use_api_client'
10
10
  import { useConversationMessages } from '../hooks/use_conversation_messages'
11
11
  import { useMessageReactionToggle } from '../hooks/use_message_reaction_toggle'
@@ -203,9 +203,10 @@ const Reaction = ({
203
203
 
204
204
  const useStyles = () => {
205
205
  const { colors } = useTheme()
206
+ const fontScale = useFontScale({ maxFontSizeMultiplier: 1.3 })
206
207
 
207
208
  const btnBorderWidth = 1
208
- const baseSize = 44
209
+ const baseSize = 44 * fontScale
209
210
  const reactionBtnSize = Platform.select({
210
211
  ios: baseSize,
211
212
  android: baseSize + btnBorderWidth * 2,