@planningcenter/chat-react-native 3.39.0-rc.1 → 3.39.0-rc.11
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.
- package/build/components/conversation/messages_disabled_banners.d.ts +6 -1
- package/build/components/conversation/messages_disabled_banners.d.ts.map +1 -1
- package/build/components/conversation/messages_disabled_banners.js +8 -2
- package/build/components/conversation/messages_disabled_banners.js.map +1 -1
- package/build/components/primitive/form_sheet.d.ts +1 -0
- package/build/components/primitive/form_sheet.d.ts.map +1 -1
- package/build/components/primitive/form_sheet.js +17 -7
- package/build/components/primitive/form_sheet.js.map +1 -1
- package/build/contexts/api_provider.js +2 -1
- package/build/contexts/api_provider.js.map +1 -1
- package/build/contexts/conversations_context.d.ts.map +1 -1
- package/build/contexts/conversations_context.js +6 -2
- package/build/contexts/conversations_context.js.map +1 -1
- package/build/hooks/direct_messages/use_direct_message_candidates.d.ts.map +1 -1
- package/build/hooks/direct_messages/use_direct_message_candidates.js +1 -0
- package/build/hooks/direct_messages/use_direct_message_candidates.js.map +1 -1
- package/build/hooks/groups/use_group_chat_conversation_payload.d.ts.map +1 -1
- package/build/hooks/groups/use_group_chat_conversation_payload.js +2 -1
- package/build/hooks/groups/use_group_chat_conversation_payload.js.map +1 -1
- package/build/hooks/index.d.ts +1 -0
- package/build/hooks/index.d.ts.map +1 -1
- package/build/hooks/index.js +1 -0
- package/build/hooks/index.js.map +1 -1
- package/build/hooks/services/use_services_chat_conversation_payload.d.ts.map +1 -1
- package/build/hooks/services/use_services_chat_conversation_payload.js +2 -1
- package/build/hooks/services/use_services_chat_conversation_payload.js.map +1 -1
- package/build/hooks/use_api.d.ts +5 -1
- package/build/hooks/use_api.d.ts.map +1 -1
- package/build/hooks/use_api.js +2 -1
- package/build/hooks/use_api.js.map +1 -1
- package/build/hooks/use_chat_configuration.d.ts.map +1 -1
- package/build/hooks/use_chat_configuration.js +2 -1
- package/build/hooks/use_chat_configuration.js.map +1 -1
- package/build/hooks/use_chat_permissions.d.ts.map +1 -1
- package/build/hooks/use_chat_permissions.js +4 -1
- package/build/hooks/use_chat_permissions.js.map +1 -1
- package/build/hooks/use_conversation.d.ts.map +1 -1
- package/build/hooks/use_conversation.js +1 -0
- package/build/hooks/use_conversation.js.map +1 -1
- package/build/hooks/use_conversation_jolt_events.d.ts.map +1 -1
- package/build/hooks/use_conversation_jolt_events.js +2 -2
- package/build/hooks/use_conversation_jolt_events.js.map +1 -1
- package/build/hooks/use_current_person.d.ts.map +1 -1
- package/build/hooks/use_current_person.js +4 -2
- package/build/hooks/use_current_person.js.map +1 -1
- package/build/hooks/use_features.d.ts.map +1 -1
- package/build/hooks/use_features.js +2 -1
- package/build/hooks/use_features.js.map +1 -1
- package/build/hooks/use_groups.d.ts.map +1 -1
- package/build/hooks/use_groups.js +2 -1
- package/build/hooks/use_groups.js.map +1 -1
- package/build/hooks/use_groups_groups.d.ts.map +1 -1
- package/build/hooks/use_groups_groups.js +2 -1
- package/build/hooks/use_groups_groups.js.map +1 -1
- package/build/hooks/use_has_direct_messages.d.ts +2 -0
- package/build/hooks/use_has_direct_messages.d.ts.map +1 -0
- package/build/hooks/use_has_direct_messages.js +17 -0
- package/build/hooks/use_has_direct_messages.js.map +1 -0
- package/build/hooks/use_jolt.d.ts.map +1 -1
- package/build/hooks/use_jolt.js +2 -1
- package/build/hooks/use_jolt.js.map +1 -1
- package/build/hooks/use_organization.d.ts.map +1 -1
- package/build/hooks/use_organization.js +4 -1
- package/build/hooks/use_organization.js.map +1 -1
- package/build/hooks/use_person_settings.d.ts +6 -0
- package/build/hooks/use_person_settings.d.ts.map +1 -0
- package/build/hooks/use_person_settings.js +26 -0
- package/build/hooks/use_person_settings.js.map +1 -0
- package/build/navigation/index.d.ts +13 -0
- package/build/navigation/index.d.ts.map +1 -1
- package/build/navigation/index.js +9 -0
- package/build/navigation/index.js.map +1 -1
- package/build/screens/conversation_details_screen.d.ts.map +1 -1
- package/build/screens/conversation_details_screen.js +2 -1
- package/build/screens/conversation_details_screen.js.map +1 -1
- package/build/screens/conversation_filters/components/conversation_filters.d.ts.map +1 -1
- package/build/screens/conversation_filters/components/conversation_filters.js +20 -5
- package/build/screens/conversation_filters/components/conversation_filters.js.map +1 -1
- package/build/screens/conversation_filters/components/rows.d.ts +2 -1
- package/build/screens/conversation_filters/components/rows.d.ts.map +1 -1
- package/build/screens/conversation_filters/components/rows.js +2 -2
- package/build/screens/conversation_filters/components/rows.js.map +1 -1
- package/build/screens/conversation_filters/context/conversation_filter_context.d.ts.map +1 -1
- package/build/screens/conversation_filters/context/conversation_filter_context.js +4 -0
- package/build/screens/conversation_filters/context/conversation_filter_context.js.map +1 -1
- package/build/screens/conversation_filters/filter_types.d.ts +1 -0
- package/build/screens/conversation_filters/filter_types.d.ts.map +1 -1
- package/build/screens/conversation_filters/filter_types.js +1 -0
- package/build/screens/conversation_filters/filter_types.js.map +1 -1
- package/build/screens/conversation_filters/screen_props.d.ts +1 -0
- package/build/screens/conversation_filters/screen_props.d.ts.map +1 -1
- package/build/screens/conversation_filters/screen_props.js.map +1 -1
- package/build/screens/conversation_screen.d.ts.map +1 -1
- package/build/screens/conversation_screen.js +1 -1
- package/build/screens/conversation_screen.js.map +1 -1
- package/build/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.d.ts +1 -2
- package/build/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.d.ts.map +1 -1
- package/build/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.js +319 -10
- package/build/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.js.map +1 -1
- package/build/screens/conversation_select_type_screen.d.ts.map +1 -1
- package/build/screens/conversation_select_type_screen.js +4 -2
- package/build/screens/conversation_select_type_screen.js.map +1 -1
- package/build/screens/conversations/components/list_header_component.d.ts.map +1 -1
- package/build/screens/conversations/components/list_header_component.js +35 -17
- package/build/screens/conversations/components/list_header_component.js.map +1 -1
- package/build/screens/conversations/conversations_screen.d.ts +1 -0
- package/build/screens/conversations/conversations_screen.d.ts.map +1 -1
- package/build/screens/conversations/conversations_screen.js.map +1 -1
- package/build/screens/get_help_screen.d.ts.map +1 -1
- package/build/screens/get_help_screen.js +2 -18
- package/build/screens/get_help_screen.js.map +1 -1
- package/build/screens/index.d.ts +1 -0
- package/build/screens/index.d.ts.map +1 -1
- package/build/screens/index.js +1 -0
- package/build/screens/index.js.map +1 -1
- package/build/screens/settings_screen.d.ts +5 -0
- package/build/screens/settings_screen.d.ts.map +1 -0
- package/build/screens/settings_screen.js +56 -0
- package/build/screens/settings_screen.js.map +1 -0
- package/build/types/jolt_events/conversation_events.d.ts +2 -0
- package/build/types/jolt_events/conversation_events.d.ts.map +1 -1
- package/build/types/jolt_events/conversation_events.js.map +1 -1
- package/build/types/resources/conversation.d.ts +2 -0
- package/build/types/resources/conversation.d.ts.map +1 -1
- package/build/types/resources/conversation.js.map +1 -1
- package/build/types/resources/organization.d.ts +1 -0
- package/build/types/resources/organization.d.ts.map +1 -1
- package/build/types/resources/organization.js.map +1 -1
- package/build/types/resources/person.d.ts +1 -0
- package/build/types/resources/person.d.ts.map +1 -1
- package/build/types/resources/person.js.map +1 -1
- package/build/utils/request/conversation.d.ts +2 -1
- package/build/utils/request/conversation.d.ts.map +1 -1
- package/build/utils/request/conversation.js +15 -6
- package/build/utils/request/conversation.js.map +1 -1
- package/build/utils/time.d.ts +8 -0
- package/build/utils/time.d.ts.map +1 -0
- package/build/utils/time.js +15 -0
- package/build/utils/time.js.map +1 -0
- package/package.json +2 -2
- package/src/components/conversation/messages_disabled_banners.tsx +16 -2
- package/src/components/primitive/form_sheet.tsx +23 -6
- package/src/contexts/api_provider.tsx +4 -1
- package/src/contexts/conversations_context.tsx +6 -2
- package/src/hooks/direct_messages/use_direct_message_candidates.ts +1 -0
- package/src/hooks/groups/use_group_chat_conversation_payload.ts +2 -1
- package/src/hooks/index.ts +1 -0
- package/src/hooks/services/use_services_chat_conversation_payload.ts +2 -1
- package/src/hooks/use_api.ts +10 -1
- package/src/hooks/use_chat_configuration.ts +2 -1
- package/src/hooks/use_chat_permissions.ts +4 -1
- package/src/hooks/use_conversation.ts +1 -0
- package/src/hooks/use_conversation_jolt_events.ts +3 -2
- package/src/hooks/use_current_person.ts +4 -2
- package/src/hooks/use_features.ts +2 -1
- package/src/hooks/use_groups.ts +16 -12
- package/src/hooks/use_groups_groups.ts +19 -15
- package/src/hooks/use_has_direct_messages.ts +21 -0
- package/src/hooks/use_jolt.ts +2 -1
- package/src/hooks/use_organization.ts +4 -1
- package/src/hooks/use_person_settings.ts +29 -0
- package/src/navigation/index.tsx +11 -0
- package/src/screens/conversation_details_screen.tsx +2 -1
- package/src/screens/conversation_filters/components/conversation_filters.tsx +25 -5
- package/src/screens/conversation_filters/components/rows.tsx +16 -3
- package/src/screens/conversation_filters/context/conversation_filter_context.tsx +4 -0
- package/src/screens/conversation_filters/filter_types.ts +1 -0
- package/src/screens/conversation_filters/screen_props.ts +1 -0
- package/src/screens/conversation_screen.tsx +2 -1
- package/src/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.tsx +513 -10
- package/src/screens/conversation_select_type_screen.tsx +6 -2
- package/src/screens/conversations/components/list_header_component.tsx +84 -34
- package/src/screens/conversations/conversations_screen.tsx +1 -0
- package/src/screens/get_help_screen.tsx +2 -29
- package/src/screens/index.ts +1 -0
- package/src/screens/settings_screen.tsx +67 -0
- package/src/types/jolt_events/conversation_events.ts +2 -0
- package/src/types/resources/conversation.ts +3 -0
- package/src/types/resources/organization.ts +1 -0
- package/src/types/resources/person.ts +1 -0
- package/src/utils/__tests__/conversation.test.ts +14 -0
- package/src/utils/request/conversation.ts +13 -5
- package/src/utils/time.ts +17 -0
|
@@ -242,6 +242,7 @@ interface FormSheetActionProps {
|
|
|
242
242
|
accessibilityRole?: AccessibilityRole
|
|
243
243
|
appearance?: FormSheetActionAppearanceUnion
|
|
244
244
|
disabled?: boolean
|
|
245
|
+
disabledReason?: string
|
|
245
246
|
}
|
|
246
247
|
|
|
247
248
|
function FormSheetAction({
|
|
@@ -253,14 +254,17 @@ function FormSheetAction({
|
|
|
253
254
|
accessibilityRole = 'button',
|
|
254
255
|
appearance = 'neutral',
|
|
255
256
|
disabled = false,
|
|
257
|
+
disabledReason,
|
|
256
258
|
}: FormSheetActionProps) {
|
|
257
|
-
const styles = useStyles({ appearance })
|
|
259
|
+
const styles = useStyles({ appearance, disabled })
|
|
258
260
|
|
|
259
261
|
return (
|
|
260
262
|
<PlatformPressable
|
|
261
263
|
onPress={onPress}
|
|
262
264
|
accessibilityLabel={accessibilityLabel}
|
|
263
|
-
accessibilityHint={
|
|
265
|
+
accessibilityHint={
|
|
266
|
+
accessibilityHint ?? (disabled && disabledReason ? disabledReason : undefined)
|
|
267
|
+
}
|
|
264
268
|
accessibilityRole={accessibilityRole}
|
|
265
269
|
style={styles.actionPressable}
|
|
266
270
|
disabled={disabled}
|
|
@@ -268,7 +272,12 @@ function FormSheetAction({
|
|
|
268
272
|
{iconName && (
|
|
269
273
|
<Icon name={iconName} size={16} accessibilityElementsHidden style={styles.actionIcon} />
|
|
270
274
|
)}
|
|
271
|
-
<
|
|
275
|
+
<View style={styles.actionTextBlock}>
|
|
276
|
+
<Text style={styles.actionTitle}>{title}</Text>
|
|
277
|
+
{disabled && disabledReason && (
|
|
278
|
+
<Text style={styles.actionDisabledReason}>{disabledReason}</Text>
|
|
279
|
+
)}
|
|
280
|
+
</View>
|
|
272
281
|
</PlatformPressable>
|
|
273
282
|
)
|
|
274
283
|
}
|
|
@@ -281,9 +290,10 @@ FormSheetAction.displayName = 'FormSheet.Action'
|
|
|
281
290
|
|
|
282
291
|
interface Styles {
|
|
283
292
|
appearance?: FormSheetActionAppearanceUnion
|
|
293
|
+
disabled?: boolean
|
|
284
294
|
}
|
|
285
295
|
|
|
286
|
-
const useStyles = ({ appearance = 'neutral' }: Styles = {}) => {
|
|
296
|
+
const useStyles = ({ appearance = 'neutral', disabled = false }: Styles = {}) => {
|
|
287
297
|
const { colors } = useTheme()
|
|
288
298
|
const { height } = useWindowDimensions()
|
|
289
299
|
const { bottom, top } = useSafeAreaInsets()
|
|
@@ -368,10 +378,17 @@ const useStyles = ({ appearance = 'neutral' }: Styles = {}) => {
|
|
|
368
378
|
gap: 8,
|
|
369
379
|
},
|
|
370
380
|
actionIcon: {
|
|
371
|
-
color: appearanceColorsMap[appearance].iconColor,
|
|
381
|
+
color: disabled ? colors.textColorDefaultDisabled : appearanceColorsMap[appearance].iconColor,
|
|
382
|
+
},
|
|
383
|
+
actionTextBlock: {
|
|
384
|
+
flex: 1,
|
|
372
385
|
},
|
|
373
386
|
actionTitle: {
|
|
374
|
-
color: appearanceColorsMap[appearance].textColor,
|
|
387
|
+
color: disabled ? colors.textColorDefaultDisabled : appearanceColorsMap[appearance].textColor,
|
|
388
|
+
},
|
|
389
|
+
actionDisabledReason: {
|
|
390
|
+
color: colors.textColorDefaultDisabled,
|
|
391
|
+
fontSize: 12,
|
|
375
392
|
},
|
|
376
393
|
})
|
|
377
394
|
}
|
|
@@ -95,7 +95,10 @@ function useSessionChanged(value: Pick<ChatContextValue, 'token' | 'env'>): bool
|
|
|
95
95
|
const isInitialLogin = !prevToken && !!newToken
|
|
96
96
|
if (isInitialLogin) return false
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
const tokenChanged = Boolean(
|
|
99
|
+
prevToken?.access_token && newToken?.access_token !== prevToken?.access_token
|
|
100
|
+
)
|
|
101
|
+
return tokenChanged || Boolean(prevEnv && newEnv !== prevEnv)
|
|
99
102
|
}
|
|
100
103
|
|
|
101
104
|
function usePrevious<T>(value: T): T {
|
|
@@ -39,9 +39,13 @@ export const ConversationsContextProvider = ({
|
|
|
39
39
|
args = {},
|
|
40
40
|
}: PropsWithChildren<{ args: ConversationFiltersParams }>) => {
|
|
41
41
|
const [activeConversationId, setActiveConversationId] = useState<number | undefined>()
|
|
42
|
-
const { chat_group_graph_id, group_source_app_name } = args
|
|
42
|
+
const { chat_group_graph_id, group_source_app_name, show_direct_messages } = args
|
|
43
43
|
|
|
44
|
-
const query = useConversations({
|
|
44
|
+
const query = useConversations({
|
|
45
|
+
chat_group_graph_id,
|
|
46
|
+
group_source_app_name,
|
|
47
|
+
show_direct_messages,
|
|
48
|
+
})
|
|
45
49
|
|
|
46
50
|
const value = useMemo(
|
|
47
51
|
() => ({
|
|
@@ -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
|
|
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
|
package/src/hooks/index.ts
CHANGED
|
@@ -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
|
|
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[]
|
package/src/hooks/use_api.ts
CHANGED
|
@@ -17,7 +17,15 @@ interface ApiGetOptions extends GetRequest {
|
|
|
17
17
|
enabled?: boolean
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
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:
|
|
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 {
|
|
@@ -26,7 +26,8 @@ export function useConversationJoltEvents({ conversationId }: Props) {
|
|
|
26
26
|
|
|
27
27
|
const handleUpdatedConversation = useCallback(
|
|
28
28
|
(e: JoltConversationEvent) => {
|
|
29
|
-
const { last_message_idempotent_key, last_message_author_id, disabled } =
|
|
29
|
+
const { last_message_idempotent_key, last_message_author_id, disabled, disabled_reason } =
|
|
30
|
+
e.data.data
|
|
30
31
|
|
|
31
32
|
if (last_message_idempotent_key && last_message_author_id === currentPersonId) {
|
|
32
33
|
completeMessageCreationConversationTracking({
|
|
@@ -37,7 +38,7 @@ export function useConversationJoltEvents({ conversationId }: Props) {
|
|
|
37
38
|
|
|
38
39
|
queryClient.setQueryData<ApiResource<ConversationResource>>(queryKey, prev => {
|
|
39
40
|
if (!prev?.data) return prev
|
|
40
|
-
return { ...prev, data: { ...prev.data, disabled } }
|
|
41
|
+
return { ...prev, data: { ...prev.data, disabled, disabledReason: disabled_reason } }
|
|
41
42
|
})
|
|
42
43
|
|
|
43
44
|
queryClient.invalidateQueries({ queryKey })
|
|
@@ -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 = {
|
|
@@ -15,6 +16,7 @@ export const currentPersonRequestArgs = {
|
|
|
15
16
|
'unread_count',
|
|
16
17
|
'pco_chat_enabled',
|
|
17
18
|
'age_qualification_status',
|
|
19
|
+
'direct_messages_disabled',
|
|
18
20
|
],
|
|
19
21
|
},
|
|
20
22
|
},
|
|
@@ -24,8 +26,8 @@ export const currentPersonQueryKey = getRequestQueryKey(currentPersonRequestArgs
|
|
|
24
26
|
|
|
25
27
|
export const useCurrentPerson = () => {
|
|
26
28
|
const { data: person } = useSuspenseGet<CurrentPersonResource>(currentPersonRequestArgs, {
|
|
27
|
-
staleTime:
|
|
28
|
-
gcTime:
|
|
29
|
+
staleTime: FIVE_MINUTES,
|
|
30
|
+
gcTime: THIRTY_MINUTES,
|
|
29
31
|
})
|
|
30
32
|
|
|
31
33
|
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:
|
|
22
|
+
staleTime: FIVE_MINUTES,
|
|
22
23
|
})
|
|
23
24
|
|
|
24
25
|
const features = data.data
|
package/src/hooks/use_groups.ts
CHANGED
|
@@ -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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
18
|
-
source_app_name,
|
|
19
|
-
source_type,
|
|
20
|
-
},
|
|
21
|
-
perPage: 100,
|
|
25
|
+
app: 'chat',
|
|
22
26
|
},
|
|
23
|
-
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
22
|
+
app: 'groups',
|
|
19
23
|
},
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
{ staleTime: FIVE_MINUTES }
|
|
25
|
+
)
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
export const useCanDisplayGroupsGroups = () => {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useQuery } from '@tanstack/react-query'
|
|
2
|
+
import { ApiCollection, ConversationResource } from '../types'
|
|
3
|
+
import { useApiClient } from './use_api_client'
|
|
4
|
+
|
|
5
|
+
export function useHasDirectMessages(): boolean {
|
|
6
|
+
const apiClient = useApiClient()
|
|
7
|
+
|
|
8
|
+
const { data, isFetched } = useQuery<ApiCollection<ConversationResource>>({
|
|
9
|
+
queryKey: ['chat', '/me/conversations', 'direct_message', 'has_any'],
|
|
10
|
+
queryFn: () =>
|
|
11
|
+
apiClient.chat.get({
|
|
12
|
+
url: '/me/conversations',
|
|
13
|
+
data: { filter: 'direct_message', perPage: 1, fields: { Conversation: ['id'] } },
|
|
14
|
+
}),
|
|
15
|
+
staleTime: 1000 * 60 * 5,
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
if (!isFetched) return false
|
|
19
|
+
|
|
20
|
+
return (data?.data.length ?? 0) > 0
|
|
21
|
+
}
|
package/src/hooks/use_jolt.ts
CHANGED
|
@@ -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:
|
|
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
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useMutation } from '@tanstack/react-query'
|
|
2
|
+
import { throwResponseError } from '../utils/response_error'
|
|
3
|
+
import { useApiClient } from './use_api_client'
|
|
4
|
+
import { useCurrentPerson, useCurrentPersonCache } from './use_current_person'
|
|
5
|
+
|
|
6
|
+
export function usePersonSettings() {
|
|
7
|
+
const apiClient = useApiClient()
|
|
8
|
+
const person = useCurrentPerson()
|
|
9
|
+
const { update, invalidate } = useCurrentPersonCache()
|
|
10
|
+
|
|
11
|
+
const directMessagesDisabled = person?.directMessagesDisabled ?? false
|
|
12
|
+
|
|
13
|
+
const { mutate: setDirectMessagesDisabled, isPending: isMutating } = useMutation({
|
|
14
|
+
mutationFn: (disabled: boolean) => {
|
|
15
|
+
const action = disabled ? 'disable_direct_messages' : 'enable_direct_messages'
|
|
16
|
+
return apiClient.chat
|
|
17
|
+
.post({ url: `/me/${action}`, data: { data: { type: 'Person', attributes: {} } } })
|
|
18
|
+
.catch(throwResponseError)
|
|
19
|
+
},
|
|
20
|
+
onMutate: disabled => {
|
|
21
|
+
update({ directMessagesDisabled: disabled })
|
|
22
|
+
},
|
|
23
|
+
onError: () => {
|
|
24
|
+
invalidate()
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
return { directMessagesDisabled, setDirectMessagesDisabled, isMutating }
|
|
29
|
+
}
|
package/src/navigation/index.tsx
CHANGED
|
@@ -77,6 +77,7 @@ import { NotificationSettingsScreen } from '../screens/notification_settings_scr
|
|
|
77
77
|
import { PreferredAppSelectionScreen } from '../screens/preferred_app_selection_screen'
|
|
78
78
|
import { ReactionsScreen, ReactionsScreenOptions } from '../screens/reactions_screen'
|
|
79
79
|
import { SendGiphyScreen, SendGiphyScreenOptions } from '../screens/send_giphy_screen'
|
|
80
|
+
import { SettingsScreen } from '../screens/settings_screen'
|
|
80
81
|
import {
|
|
81
82
|
SystemMessagePeopleScreen,
|
|
82
83
|
SystemMessagePeopleScreenOptions,
|
|
@@ -280,6 +281,16 @@ export const ChatStack = createNativeStackNavigator({
|
|
|
280
281
|
screen: AvatarPickerScreen,
|
|
281
282
|
options: AvatarPickerScreenOptions,
|
|
282
283
|
},
|
|
284
|
+
ChatSettings: {
|
|
285
|
+
screen: SettingsScreen,
|
|
286
|
+
options: ({ navigation }) => ({
|
|
287
|
+
title: 'Chat settings',
|
|
288
|
+
headerBackVisible: false,
|
|
289
|
+
headerRight: (props: NativeStackHeaderRightProps) => (
|
|
290
|
+
<HeaderTextButton {...props} onPress={navigation.goBack} title="Done" />
|
|
291
|
+
),
|
|
292
|
+
}),
|
|
293
|
+
},
|
|
283
294
|
NotificationSettings: {
|
|
284
295
|
screen: NotificationSettingsScreen,
|
|
285
296
|
options: ({ navigation }) => ({
|
|
@@ -122,6 +122,7 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
|
|
|
122
122
|
const canDelete = conversation.memberAbility?.canDelete || false
|
|
123
123
|
const isLeader = conversation.memberAbility?.leader || false
|
|
124
124
|
const isDisabled = conversation.disabled ?? false
|
|
125
|
+
const showAdultRequirementNotice = isDisabled && conversation.disabledReason === 'safety_check'
|
|
125
126
|
|
|
126
127
|
const {
|
|
127
128
|
data: members,
|
|
@@ -350,7 +351,7 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
|
|
|
350
351
|
sectionInnerStyle: styles.sectionInnerGenderNotice,
|
|
351
352
|
},
|
|
352
353
|
{
|
|
353
|
-
type:
|
|
354
|
+
type: showAdultRequirementNotice ? SectionTypes.view : SectionTypes.hidden,
|
|
354
355
|
data: {
|
|
355
356
|
children: <AdultRequirementNotice />,
|
|
356
357
|
},
|
|
@@ -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 {
|
|
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:
|
|
109
|
+
type: showGeneralFilters ? SectionTypes.header : SectionTypes.hidden,
|
|
98
110
|
data: { title: 'General Filters' },
|
|
99
111
|
},
|
|
100
112
|
{
|
|
101
|
-
type:
|
|
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 = {
|
|
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 = ({
|
|
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
|
|
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) => {
|
|
@@ -4,6 +4,7 @@ import { GraphId } from '../../types/resources/group_resource'
|
|
|
4
4
|
export type ConversationFiltersParams = {
|
|
5
5
|
chat_group_graph_id?: GraphId
|
|
6
6
|
group_source_app_name?: string
|
|
7
|
+
show_direct_messages?: boolean
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
export type ConversationFiltersScreenProps = StaticScreenProps<ConversationFiltersParams>
|
|
@@ -239,7 +239,8 @@ function ConversationBottomBar({
|
|
|
239
239
|
replyRootId,
|
|
240
240
|
currentlyEditingMessage,
|
|
241
241
|
}: ConversationBottomBarProps) {
|
|
242
|
-
if (conversation.disabled)
|
|
242
|
+
if (conversation.disabled)
|
|
243
|
+
return <ConversationDisabledBanner disabledReason={conversation.disabledReason} />
|
|
243
244
|
if (!canReply) return <MemberMessagesDisabledBanner />
|
|
244
245
|
return (
|
|
245
246
|
<MessageForm.Root
|