@planningcenter/chat-react-native 3.39.0-rc.6 → 3.39.0-rc.8

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 (90) hide show
  1. package/build/hooks/groups/use_group_chat_conversation_payload.d.ts.map +1 -1
  2. package/build/hooks/groups/use_group_chat_conversation_payload.js +2 -1
  3. package/build/hooks/groups/use_group_chat_conversation_payload.js.map +1 -1
  4. package/build/hooks/index.d.ts +1 -0
  5. package/build/hooks/index.d.ts.map +1 -1
  6. package/build/hooks/index.js +1 -0
  7. package/build/hooks/index.js.map +1 -1
  8. package/build/hooks/services/use_services_chat_conversation_payload.d.ts.map +1 -1
  9. package/build/hooks/services/use_services_chat_conversation_payload.js +2 -1
  10. package/build/hooks/services/use_services_chat_conversation_payload.js.map +1 -1
  11. package/build/hooks/use_api.d.ts +5 -1
  12. package/build/hooks/use_api.d.ts.map +1 -1
  13. package/build/hooks/use_api.js +2 -1
  14. package/build/hooks/use_api.js.map +1 -1
  15. package/build/hooks/use_chat_configuration.d.ts.map +1 -1
  16. package/build/hooks/use_chat_configuration.js +2 -1
  17. package/build/hooks/use_chat_configuration.js.map +1 -1
  18. package/build/hooks/use_chat_permissions.d.ts.map +1 -1
  19. package/build/hooks/use_chat_permissions.js +4 -1
  20. package/build/hooks/use_chat_permissions.js.map +1 -1
  21. package/build/hooks/use_current_person.d.ts.map +1 -1
  22. package/build/hooks/use_current_person.js +3 -2
  23. package/build/hooks/use_current_person.js.map +1 -1
  24. package/build/hooks/use_features.d.ts.map +1 -1
  25. package/build/hooks/use_features.js +2 -1
  26. package/build/hooks/use_features.js.map +1 -1
  27. package/build/hooks/use_groups.d.ts.map +1 -1
  28. package/build/hooks/use_groups.js +2 -1
  29. package/build/hooks/use_groups.js.map +1 -1
  30. package/build/hooks/use_groups_groups.d.ts.map +1 -1
  31. package/build/hooks/use_groups_groups.js +2 -1
  32. package/build/hooks/use_groups_groups.js.map +1 -1
  33. package/build/hooks/use_has_direct_messages.d.ts.map +1 -1
  34. package/build/hooks/use_has_direct_messages.js +3 -1
  35. package/build/hooks/use_has_direct_messages.js.map +1 -1
  36. package/build/hooks/use_jolt.d.ts.map +1 -1
  37. package/build/hooks/use_jolt.js +2 -1
  38. package/build/hooks/use_jolt.js.map +1 -1
  39. package/build/hooks/use_organization.d.ts.map +1 -1
  40. package/build/hooks/use_organization.js +4 -1
  41. package/build/hooks/use_organization.js.map +1 -1
  42. package/build/screens/conversation_filters/components/conversation_filters.d.ts.map +1 -1
  43. package/build/screens/conversation_filters/components/conversation_filters.js +20 -5
  44. package/build/screens/conversation_filters/components/conversation_filters.js.map +1 -1
  45. package/build/screens/conversation_filters/components/rows.d.ts +2 -1
  46. package/build/screens/conversation_filters/components/rows.d.ts.map +1 -1
  47. package/build/screens/conversation_filters/components/rows.js +2 -2
  48. package/build/screens/conversation_filters/components/rows.js.map +1 -1
  49. package/build/screens/conversation_filters/context/conversation_filter_context.d.ts.map +1 -1
  50. package/build/screens/conversation_filters/context/conversation_filter_context.js +4 -0
  51. package/build/screens/conversation_filters/context/conversation_filter_context.js.map +1 -1
  52. package/build/screens/conversation_filters/filter_types.d.ts +1 -0
  53. package/build/screens/conversation_filters/filter_types.d.ts.map +1 -1
  54. package/build/screens/conversation_filters/filter_types.js +1 -0
  55. package/build/screens/conversation_filters/filter_types.js.map +1 -1
  56. package/build/screens/conversations/components/list_header_component.d.ts.map +1 -1
  57. package/build/screens/conversations/components/list_header_component.js +3 -6
  58. package/build/screens/conversations/components/list_header_component.js.map +1 -1
  59. package/build/screens/get_help_screen.d.ts.map +1 -1
  60. package/build/screens/get_help_screen.js +2 -18
  61. package/build/screens/get_help_screen.js.map +1 -1
  62. package/build/types/resources/organization.d.ts +1 -0
  63. package/build/types/resources/organization.d.ts.map +1 -1
  64. package/build/types/resources/organization.js.map +1 -1
  65. package/build/utils/time.d.ts +8 -0
  66. package/build/utils/time.d.ts.map +1 -0
  67. package/build/utils/time.js +15 -0
  68. package/build/utils/time.js.map +1 -0
  69. package/package.json +2 -2
  70. package/src/hooks/groups/use_group_chat_conversation_payload.ts +2 -1
  71. package/src/hooks/index.ts +1 -0
  72. package/src/hooks/services/use_services_chat_conversation_payload.ts +2 -1
  73. package/src/hooks/use_api.ts +10 -1
  74. package/src/hooks/use_chat_configuration.ts +2 -1
  75. package/src/hooks/use_chat_permissions.ts +4 -1
  76. package/src/hooks/use_current_person.ts +3 -2
  77. package/src/hooks/use_features.ts +2 -1
  78. package/src/hooks/use_groups.ts +16 -12
  79. package/src/hooks/use_groups_groups.ts +19 -15
  80. package/src/hooks/use_has_direct_messages.ts +3 -1
  81. package/src/hooks/use_jolt.ts +2 -1
  82. package/src/hooks/use_organization.ts +4 -1
  83. package/src/screens/conversation_filters/components/conversation_filters.tsx +25 -5
  84. package/src/screens/conversation_filters/components/rows.tsx +16 -3
  85. package/src/screens/conversation_filters/context/conversation_filter_context.tsx +4 -0
  86. package/src/screens/conversation_filters/filter_types.ts +1 -0
  87. package/src/screens/conversations/components/list_header_component.tsx +11 -6
  88. package/src/screens/get_help_screen.tsx +2 -29
  89. package/src/types/resources/organization.ts +1 -0
  90. package/src/utils/time.ts +17 -0
@@ -0,0 +1,15 @@
1
+ export function toMs(value, unit) {
2
+ switch (unit) {
3
+ case 'hours':
4
+ return value * 60 * 60 * 1000;
5
+ case 'minutes':
6
+ return value * 60 * 1000;
7
+ case 'seconds':
8
+ return value * 1000;
9
+ }
10
+ }
11
+ export const FIVE_SECONDS = toMs(5, 'seconds');
12
+ export const FIVE_MINUTES = toMs(5, 'minutes');
13
+ export const THIRTY_MINUTES = toMs(30, 'minutes');
14
+ export const ONE_HOUR = toMs(1, 'hours');
15
+ //# sourceMappingURL=time.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.js","sourceRoot":"","sources":["../../src/utils/time.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,IAAI,CAAC,KAAa,EAAE,IAAc;IAChD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO;YACV,OAAO,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;QAC/B,KAAK,SAAS;YACZ,OAAO,KAAK,GAAG,EAAE,GAAG,IAAI,CAAA;QAC1B,KAAK,SAAS;YACZ,OAAO,KAAK,GAAG,IAAI,CAAA;IACvB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;AAC9C,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;AAC9C,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC,CAAA;AACjD,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA","sourcesContent":["type TimeUnit = 'hours' | 'minutes' | 'seconds'\n\nexport function toMs(value: number, unit: TimeUnit): number {\n switch (unit) {\n case 'hours':\n return value * 60 * 60 * 1000\n case 'minutes':\n return value * 60 * 1000\n case 'seconds':\n return value * 1000\n }\n}\n\nexport const FIVE_SECONDS = toMs(5, 'seconds')\nexport const FIVE_MINUTES = toMs(5, 'minutes')\nexport const THIRTY_MINUTES = toMs(30, 'minutes')\nexport const ONE_HOUR = toMs(1, 'hours')\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planningcenter/chat-react-native",
3
- "version": "3.39.0-rc.6",
3
+ "version": "3.39.0-rc.8",
4
4
  "description": "",
5
5
  "main": "build/index.js",
6
6
  "react-native": "./src/index.tsx",
@@ -72,5 +72,5 @@
72
72
  "react-native-url-polyfill": "^2.0.0",
73
73
  "typescript": "~5.9.2"
74
74
  },
75
- "gitHead": "97b3ea13cfe44860e2e72f30edcb1500bd77e515"
75
+ "gitHead": "bf556bbbbd9e7c6720dd5ce466fca2947caf420a"
76
76
  }
@@ -1,8 +1,9 @@
1
1
  import { useQuery } from '@tanstack/react-query'
2
2
  import { ApiResource, ResourceObject } from '../../types'
3
+ import { toMs } from '../../utils/time'
3
4
  import { useApiClient } from '../use_api_client'
4
5
 
5
- const STALE_TIME_MS = 25 * 60 * 1000 // under Groups' 30-min server-side expiry
6
+ const STALE_TIME_MS = toMs(25, 'minutes') // under Groups' 30-min server-side expiry
6
7
 
7
8
  interface Props {
8
9
  groupId: number
@@ -10,6 +10,7 @@ export * from './use_current_person'
10
10
  export * from './use_deleting_ids'
11
11
  export * from './use_direct_messages_enabled'
12
12
  export * from './use_font_scale'
13
+ export * from './use_has_direct_messages'
13
14
  export * from './use_groups_groups'
14
15
  export * from './use_groups'
15
16
  export * from './use_interaction_ghost_color'
@@ -1,8 +1,9 @@
1
1
  import { useQuery } from '@tanstack/react-query'
2
+ import { toMs } from '../../utils/time'
2
3
  import { useApiClient } from '../use_api_client'
3
4
  import { getServicesChatConversationPayload } from './use_find_or_create_services_conversation'
4
5
 
5
- const STALE_TIME_MS = 55 * 60 * 1000 // under Services' 1-hour server-side expiry
6
+ const STALE_TIME_MS = toMs(55, 'minutes') // under Services' 1-hour server-side expiry
6
7
 
7
8
  interface Props {
8
9
  teamIds: number[]
@@ -17,7 +17,15 @@ interface ApiGetOptions extends GetRequest {
17
17
  enabled?: boolean
18
18
  }
19
19
 
20
- export const useApiGet = <T extends ResourceObject | ResourceObject[]>(args: ApiGetOptions) => {
20
+ type UseApiGetOptions = {
21
+ staleTime?: number
22
+ gcTime?: number
23
+ }
24
+
25
+ export const useApiGet = <T extends ResourceObject | ResourceObject[]>(
26
+ args: ApiGetOptions,
27
+ opts?: UseApiGetOptions
28
+ ) => {
21
29
  type Resource = ApiResource<T>
22
30
  const { session } = useContext(ChatContext)
23
31
  const apiClient = useApiClient()
@@ -32,6 +40,7 @@ export const useApiGet = <T extends ResourceObject | ResourceObject[]>(args: Api
32
40
  return apiClient[app].get({ url, data: d, headers }) as Promise<Resource>
33
41
  },
34
42
  enabled,
43
+ ...opts,
35
44
  })
36
45
 
37
46
  return { ...data, ...query }
@@ -5,6 +5,7 @@ import {
5
5
  getChatConfigurationRequestArgs,
6
6
  getChatConfigurationQueryKey,
7
7
  } from '../utils/request/get_chat_configuration'
8
+ import { ONE_HOUR } from '../utils/time'
8
9
  import {
9
10
  FALLBACK_ALLOWED_FILE_EXTENSIONS,
10
11
  FALLBACK_ALLOWED_MIME_TYPES,
@@ -28,7 +29,7 @@ export function useChatConfiguration() {
28
29
  .get<ApiResource<ChatConfigurationResource>>(requestArgs)
29
30
  .catch(() => stableFallbackConfiguration)
30
31
  },
31
- staleTime: 1000 * 60 * 60, // 1 hour — this rarely changes
32
+ staleTime: ONE_HOUR,
32
33
  })
33
34
 
34
35
  const attrs = data.data
@@ -1,4 +1,5 @@
1
1
  import { AppGrantsResource } from '../types'
2
+ import { FIVE_MINUTES } from '../utils/time'
2
3
  import { useApiGet } from './use_api'
3
4
  import { App } from './use_api_client'
4
5
 
@@ -13,7 +14,9 @@ export const appGrantsRequestArgs = {
13
14
  }
14
15
 
15
16
  export function useAppGrants() {
16
- return useApiGet<AppGrantsResource[]>(appGrantsRequestArgs)
17
+ return useApiGet<AppGrantsResource[]>(appGrantsRequestArgs, {
18
+ staleTime: FIVE_MINUTES,
19
+ })
17
20
  }
18
21
 
19
22
  export function useCanCreateConversations(): boolean {
@@ -1,6 +1,7 @@
1
1
  import { useQueryClient } from '@tanstack/react-query'
2
2
  import { CurrentPersonResource } from '../types'
3
3
  import { ApiResource } from '../types/api_primitives'
4
+ import { FIVE_MINUTES, THIRTY_MINUTES } from '../utils/time'
4
5
  import { getRequestQueryKey, useSuspenseGet } from './use_suspense_api'
5
6
 
6
7
  export const currentPersonRequestArgs = {
@@ -24,8 +25,8 @@ export const currentPersonQueryKey = getRequestQueryKey(currentPersonRequestArgs
24
25
 
25
26
  export const useCurrentPerson = () => {
26
27
  const { data: person } = useSuspenseGet<CurrentPersonResource>(currentPersonRequestArgs, {
27
- staleTime: 5 * 60 * 1000, // 5 minutes - data stays fresh for 5 minutes
28
- gcTime: 30 * 60 * 1000, // 30 minutes - data stays in cache for 30 minutes when not in use
28
+ staleTime: FIVE_MINUTES,
29
+ gcTime: THIRTY_MINUTES,
29
30
  })
30
31
 
31
32
  return person
@@ -3,6 +3,7 @@ import { useCallback } from 'react'
3
3
  import { ApiCollection } from '../types'
4
4
  import type { FeatureResource } from '../types/resources/feature_resource'
5
5
  import { getFeaturesRequestArgs, getFeaturesQueryKey } from '../utils/request/get_features'
6
+ import { FIVE_MINUTES } from '../utils/time'
6
7
  import { useApiClient } from './use_api_client'
7
8
 
8
9
  type FeatureName = (typeof availableFeatures)[keyof typeof availableFeatures]
@@ -18,7 +19,7 @@ export function useFeatures() {
18
19
  .get<ApiCollection<FeatureResource>>(requestArgs)
19
20
  .catch(() => stableEmptyFeatures)
20
21
  },
21
- staleTime: 1000 * 60 * 5, // 5 minutes
22
+ staleTime: FIVE_MINUTES,
22
23
  })
23
24
 
24
25
  const features = data.data
@@ -1,5 +1,6 @@
1
1
  import { AppName } from '../types/resources/app_name'
2
2
  import { GroupResource, SourceType } from '../types/resources/group_resource'
3
+ import { FIVE_MINUTES } from '../utils/time'
3
4
  import { useApiPaginator } from './use_api'
4
5
 
5
6
  type UseGroupsProps = {
@@ -8,20 +9,23 @@ type UseGroupsProps = {
8
9
  }
9
10
 
10
11
  export const useGroups = ({ source_app_name, source_type }: UseGroupsProps) => {
11
- return useApiPaginator<GroupResource>({
12
- url: '/me/groups',
13
- data: {
14
- fields: {
15
- Group: [],
12
+ return useApiPaginator<GroupResource>(
13
+ {
14
+ url: '/me/groups',
15
+ data: {
16
+ fields: {
17
+ Group: [],
18
+ },
19
+ where: {
20
+ source_app_name,
21
+ source_type,
22
+ },
23
+ perPage: 100,
16
24
  },
17
- where: {
18
- source_app_name,
19
- source_type,
20
- },
21
- perPage: 100,
25
+ app: 'chat',
22
26
  },
23
- app: 'chat',
24
- })
27
+ { staleTime: FIVE_MINUTES }
28
+ )
25
29
  }
26
30
 
27
31
  export const useCanDisplayGroups = (props: UseGroupsProps) => {
@@ -1,24 +1,28 @@
1
1
  import { GroupsGroupResource } from '../types'
2
+ import { FIVE_MINUTES } from '../utils/time'
2
3
  import { useApiPaginator } from './use_api'
3
4
 
4
5
  export const useGroupsGroups = () => {
5
- return useApiPaginator<GroupsGroupResource>({
6
- url: '/me/groups',
7
- data: {
8
- perPage: 100,
9
- fields: {
10
- Group: [
11
- 'can_create_conversation',
12
- 'can_create_conversation_reason_code',
13
- 'name',
14
- 'header_image',
15
- 'memberships_count',
16
- ],
6
+ return useApiPaginator<GroupsGroupResource>(
7
+ {
8
+ url: '/me/groups',
9
+ data: {
10
+ perPage: 100,
11
+ fields: {
12
+ Group: [
13
+ 'can_create_conversation',
14
+ 'can_create_conversation_reason_code',
15
+ 'name',
16
+ 'header_image',
17
+ 'memberships_count',
18
+ ],
19
+ },
20
+ order: 'name',
17
21
  },
18
- order: 'name',
22
+ app: 'groups',
19
23
  },
20
- app: 'groups',
21
- })
24
+ { staleTime: FIVE_MINUTES }
25
+ )
22
26
  }
23
27
 
24
28
  export const useCanDisplayGroupsGroups = () => {
@@ -5,7 +5,7 @@ import { useApiClient } from './use_api_client'
5
5
  export function useHasDirectMessages(): boolean {
6
6
  const apiClient = useApiClient()
7
7
 
8
- const { data } = useQuery<ApiCollection<ConversationResource>>({
8
+ const { data, isFetched } = useQuery<ApiCollection<ConversationResource>>({
9
9
  queryKey: ['chat', '/me/conversations', 'direct_message', 'has_any'],
10
10
  queryFn: () =>
11
11
  apiClient.chat.get({
@@ -15,5 +15,7 @@ export function useHasDirectMessages(): boolean {
15
15
  staleTime: 1000 * 60 * 5,
16
16
  })
17
17
 
18
+ if (!isFetched) return false
19
+
18
20
  return (data?.data.length ?? 0) > 0
19
21
  }
@@ -13,6 +13,7 @@ import { useChatContext } from '../contexts/chat_context'
13
13
  import { ApiResource } from '../types'
14
14
  import type { JoltSubscriptionPattern } from '../types/jolt_events'
15
15
  import { Client, Uri } from '../utils'
16
+ import { FIVE_SECONDS } from '../utils/time'
16
17
 
17
18
  interface JoltResponse {
18
19
  type: 'JoltToken'
@@ -49,7 +50,7 @@ export const useJoltClient = (): JoltClient | undefined => {
49
50
  },
50
51
  })
51
52
  },
52
- staleTime: 5000, // 5 seconds
53
+ staleTime: FIVE_SECONDS,
53
54
  })
54
55
  }
55
56
 
@@ -1,4 +1,5 @@
1
1
  import { OrganizationResource } from '../types'
2
+ import { ONE_HOUR } from '../utils/time'
2
3
  import { App } from './use_api_client'
3
4
  import { useSuspenseGet } from './use_suspense_api'
4
5
 
@@ -13,5 +14,7 @@ export const organizationRequestArgs = {
13
14
  }
14
15
 
15
16
  export function useOrganization() {
16
- return useSuspenseGet<OrganizationResource>(organizationRequestArgs)
17
+ return useSuspenseGet<OrganizationResource>(organizationRequestArgs, {
18
+ staleTime: ONE_HOUR,
19
+ })
17
20
  }
@@ -2,7 +2,12 @@ import React, { useContext, useMemo } from 'react'
2
2
  import { StyleSheet, View, ViewStyle } from 'react-native'
3
3
  import { FlatList } from 'react-native-gesture-handler'
4
4
  import { Heading } from '../../../components'
5
- import { useAtFontScaleBreakpoint, useTheme } from '../../../hooks'
5
+ import {
6
+ useAtFontScaleBreakpoint,
7
+ useDirectMessagesEnabled,
8
+ useHasDirectMessages,
9
+ useTheme,
10
+ } from '../../../hooks'
6
11
  import { FilterContext, useFilterContext } from '../context/conversation_filter_context'
7
12
  import { FilterTypes } from '../filter_types'
8
13
  import { useGroupsToFilter, useTeamsToFilter } from '../hooks/filters'
@@ -52,7 +57,11 @@ interface DataItem<T, TName extends SectionTypes> {
52
57
  export const ConversationFilters = () => {
53
58
  const styles = useStyles()
54
59
  const { setScrollOffset, params } = useContext(FilterContext)
55
- const { chat_group_graph_id, group_source_app_name = '' } = params
60
+ const { chat_group_graph_id, group_source_app_name = '', show_direct_messages } = params
61
+
62
+ const directMessagesEnabled = useDirectMessagesEnabled()
63
+ const hasDirectMessages = useHasDirectMessages()
64
+ const canFilterByDMs = directMessagesEnabled && hasDirectMessages
56
65
 
57
66
  const activeFilter: FilterTypes = useMemo(() => {
58
67
  if (chat_group_graph_id) {
@@ -61,10 +70,12 @@ export const ConversationFilters = () => {
61
70
  return FilterTypes.Groups
62
71
  } else if (/services/i.test(group_source_app_name)) {
63
72
  return FilterTypes.Teams
73
+ } else if (show_direct_messages) {
74
+ return FilterTypes.DirectMessages
64
75
  }
65
76
 
66
77
  return FilterTypes.All
67
- }, [chat_group_graph_id, group_source_app_name])
78
+ }, [chat_group_graph_id, group_source_app_name, show_direct_messages])
68
79
 
69
80
  const { groups = [] } = useGroupsToFilter()
70
81
  const { teams = [] } = useTeamsToFilter()
@@ -91,14 +102,15 @@ export const ConversationFilters = () => {
91
102
  const teamItemData = selectActiveWithFirst(5)(teamItems)
92
103
 
93
104
  const hideAppFilters = groupItems.length < 1 || teamItems.length < 1
105
+ const showGeneralFilters = !hideAppFilters || canFilterByDMs
94
106
 
95
107
  const listData: SectionListData = [
96
108
  {
97
- type: hideAppFilters ? SectionTypes.hidden : SectionTypes.header,
109
+ type: showGeneralFilters ? SectionTypes.header : SectionTypes.hidden,
98
110
  data: { title: 'General Filters' },
99
111
  },
100
112
  {
101
- type: hideAppFilters ? SectionTypes.hidden : SectionTypes.filter,
113
+ type: showGeneralFilters ? SectionTypes.filter : SectionTypes.hidden,
102
114
  data: { filter: FilterTypes.All, isActive: activeFilter === FilterTypes.All },
103
115
  },
104
116
  {
@@ -117,6 +129,14 @@ export const ConversationFilters = () => {
117
129
  isActive: activeFilter === FilterTypes.Teams,
118
130
  },
119
131
  },
132
+ {
133
+ type: canFilterByDMs ? SectionTypes.filter : SectionTypes.hidden,
134
+ data: {
135
+ filter: FilterTypes.DirectMessages,
136
+ show_direct_messages: true,
137
+ isActive: activeFilter === FilterTypes.DirectMessages,
138
+ },
139
+ },
120
140
  {
121
141
  type: groupItems.length ? SectionTypes.header : SectionTypes.hidden,
122
142
  data: { title: 'Groups', style: styles.extraHeaderScalableSpace },
@@ -17,13 +17,26 @@ import { FilterTypes } from '../filter_types'
17
17
  import { FilteredGroup } from '../hooks/filters'
18
18
  import { ConversationFilterStackParamList } from '../screen_props'
19
19
 
20
- export type FilterProps = { group_source_app_name?: string; isActive: boolean; filter: FilterTypes }
20
+ export type FilterProps = {
21
+ group_source_app_name?: string
22
+ show_direct_messages?: boolean
23
+ isActive: boolean
24
+ filter: FilterTypes
25
+ }
21
26
 
22
- export const FilterRow = ({ group_source_app_name, isActive, filter }: FilterProps) => {
27
+ export const FilterRow = ({
28
+ group_source_app_name,
29
+ show_direct_messages,
30
+ isActive,
31
+ filter,
32
+ }: FilterProps) => {
23
33
  const { setAppFilter } = useContext(FilterContext)
24
34
 
25
35
  return (
26
- <PressableRow onPress={() => setAppFilter({ group_source_app_name })} isActive={isActive}>
36
+ <PressableRow
37
+ onPress={() => setAppFilter({ group_source_app_name, show_direct_messages })}
38
+ isActive={isActive}
39
+ >
27
40
  <Text>{filter}</Text>
28
41
  </PressableRow>
29
42
  )
@@ -21,6 +21,7 @@ export const FilterContext = createContext<{
21
21
  params: {
22
22
  chat_group_graph_id: undefined,
23
23
  group_source_app_name: undefined,
24
+ show_direct_messages: undefined,
24
25
  },
25
26
  scrollOffset: 0,
26
27
  setScrollOffset: () => {},
@@ -55,6 +56,7 @@ export const FilterProvider = ({ children }: PropsWithChildren) => {
55
56
  StackActions.popTo('Conversations', {
56
57
  chat_group_graph_id: undefined,
57
58
  group_source_app_name: undefined,
59
+ show_direct_messages: undefined,
58
60
  })
59
61
  )
60
62
  },
@@ -62,12 +64,14 @@ export const FilterProvider = ({ children }: PropsWithChildren) => {
62
64
  navigation.setParams({
63
65
  chat_group_graph_id: params.chat_group_graph_id,
64
66
  group_source_app_name: undefined,
67
+ show_direct_messages: undefined,
65
68
  })
66
69
  },
67
70
  setAppFilter: (params: Omit<ConversationFiltersParams, 'chat_group_graph_id'>) => {
68
71
  navigation.setParams({
69
72
  chat_group_graph_id: undefined,
70
73
  group_source_app_name: params.group_source_app_name,
74
+ show_direct_messages: params.show_direct_messages,
71
75
  })
72
76
  },
73
77
  applyFilters: (params: ConversationFiltersParams) => {
@@ -1,5 +1,6 @@
1
1
  export enum FilterTypes {
2
2
  All = 'All conversations',
3
+ DirectMessages = 'Direct messages',
3
4
  Groups = 'All my groups',
4
5
  Teams = 'All my teams and plans',
5
6
  More = 'More',
@@ -2,14 +2,18 @@ import { RouteProp, useNavigation, useRoute } from '@react-navigation/native'
2
2
  import React, { useCallback, useMemo } from 'react'
3
3
  import { Alert, ScrollView, StyleSheet, View } from 'react-native'
4
4
  import { Heading, TextButton, ToggleButton } from '../../../components'
5
- import { useAtFontScaleBreakpoint, useCurrentPersonCache, useTheme } from '../../../hooks'
6
- import { useCanCreateConversations } from '../../../hooks'
5
+ import {
6
+ useAtFontScaleBreakpoint,
7
+ useCanCreateConversations,
8
+ useCurrentPersonCache,
9
+ useDirectMessagesEnabled,
10
+ useHasDirectMessages,
11
+ useNewConversationEntry,
12
+ useTheme,
13
+ } from '../../../hooks'
7
14
  import { useAppName } from '../../../hooks/use_app_name'
8
15
  import { useMarkAllRead } from '../../../hooks/use_conversations_actions'
9
- import { useDirectMessagesEnabled } from '../../../hooks/use_direct_messages_enabled'
10
16
  import { useCanDisplayGroups } from '../../../hooks/use_groups'
11
- import { useHasDirectMessages } from '../../../hooks/use_has_direct_messages'
12
- import { useNewConversationEntry } from '../../../hooks/use_new_conversation_entry'
13
17
  import { useNewConversationFromFilter } from '../../../hooks/use_new_conversation_from_filter'
14
18
  import { GraphId } from '../../../types/resources/group_resource'
15
19
  import { MAX_FONT_SIZE_MULTIPLIER_LANDMARK } from '../../../utils'
@@ -95,8 +99,9 @@ export const ListHeaderComponent = () => {
95
99
  navigation.navigate('ConversationFilters', {
96
100
  chat_group_graph_id,
97
101
  group_source_app_name,
102
+ show_direct_messages,
98
103
  })
99
- }, [navigation, chat_group_graph_id, group_source_app_name])
104
+ }, [navigation, chat_group_graph_id, group_source_app_name, show_direct_messages])
100
105
 
101
106
  const handleMarkAllRead = useCallback(() => {
102
107
  currentPersonCache.update({ unreadCount: 0 })
@@ -4,6 +4,7 @@ import { Alert, Linking, StyleSheet, View } from 'react-native'
4
4
  import { Heading, PressableRow, Text, TextInlineButton } from '../components'
5
5
  import { useApiGet, useTheme } from '../hooks'
6
6
  import { useAppName } from '../hooks/use_app_name'
7
+ import { useOrganization } from '../hooks/use_organization'
7
8
  import { ResourceObject } from '../types'
8
9
  import { Clipboard } from '../utils'
9
10
 
@@ -13,34 +14,6 @@ type GetHelpScreenRouteProps = {
13
14
 
14
15
  type GetHelpScreenProps = StaticScreenProps<GetHelpScreenRouteProps>
15
16
 
16
- interface OrganizationResource extends ResourceObject {
17
- id: number
18
- name: string
19
- contactEmail: string
20
- contactPhoneNumber: string
21
- churchCenterChatHelpUrl: string
22
- servicesChatHelpUrl: string
23
- }
24
-
25
- const useOrganization = () => {
26
- const { data: organization } = useApiGet<OrganizationResource>({
27
- url: '/',
28
- data: {
29
- fields: {
30
- Organization: [
31
- 'contact_phone_number',
32
- 'contact_email',
33
- 'name',
34
- 'church_center_chat_help_url',
35
- 'services_chat_help_url',
36
- ],
37
- },
38
- },
39
- })
40
-
41
- return organization
42
- }
43
-
44
17
  interface HelpUrlResource extends ResourceObject {
45
18
  id: number
46
19
  link: string
@@ -67,7 +40,7 @@ export const GetHelpScreen = ({ route }: GetHelpScreenProps) => {
67
40
  const styles = useStyles()
68
41
  const appName = useAppName()
69
42
  const navigation = useNavigation()
70
- const organization = useOrganization()
43
+ const { data: organization } = useOrganization()
71
44
  const contactPresent = organization?.contactEmail || organization?.contactPhoneNumber
72
45
  const helpUrls = useHelpUrls()
73
46
  const appSpecificHelpUrls = useMemo(
@@ -3,5 +3,6 @@ import { ResourceObject } from '../api_primitives'
3
3
  export interface OrganizationResource extends ResourceObject {
4
4
  type: 'Organization'
5
5
  contactEmail?: string
6
+ contactPhoneNumber?: string
6
7
  name?: string
7
8
  }
@@ -0,0 +1,17 @@
1
+ type TimeUnit = 'hours' | 'minutes' | 'seconds'
2
+
3
+ export function toMs(value: number, unit: TimeUnit): number {
4
+ switch (unit) {
5
+ case 'hours':
6
+ return value * 60 * 60 * 1000
7
+ case 'minutes':
8
+ return value * 60 * 1000
9
+ case 'seconds':
10
+ return value * 1000
11
+ }
12
+ }
13
+
14
+ export const FIVE_SECONDS = toMs(5, 'seconds')
15
+ export const FIVE_MINUTES = toMs(5, 'minutes')
16
+ export const THIRTY_MINUTES = toMs(30, 'minutes')
17
+ export const ONE_HOUR = toMs(1, 'hours')