@planningcenter/chat-react-native 3.14.0-rc.2 → 3.14.0-rc.4
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/attachments/image_attachment.js +18 -2
- package/build/components/conversation/attachments/image_attachment.js.map +1 -1
- package/build/components/conversation/message_reaction.d.ts.map +1 -1
- package/build/components/conversation/message_reaction.js +2 -0
- package/build/components/conversation/message_reaction.js.map +1 -1
- package/build/components/conversations/conversation_actions.js +3 -3
- package/build/components/conversations/conversation_actions.js.map +1 -1
- package/build/components/conversations/{action_toggle_button.d.ts → swipeable_toggle_button.d.ts} +3 -3
- package/build/components/conversations/swipeable_toggle_button.d.ts.map +1 -0
- package/build/components/conversations/{action_toggle_button.js → swipeable_toggle_button.js} +7 -3
- package/build/components/conversations/swipeable_toggle_button.js.map +1 -0
- package/build/hooks/use_conversation.d.ts.map +1 -1
- package/build/hooks/use_conversation.js +2 -0
- package/build/hooks/use_conversation.js.map +1 -1
- package/build/hooks/use_message_create_or_update.d.ts.map +1 -1
- package/build/hooks/use_message_create_or_update.js +2 -1
- package/build/hooks/use_message_create_or_update.js.map +1 -1
- package/build/screens/attachment_actions/hooks/useDeleteAttachment.d.ts.map +1 -1
- package/build/screens/attachment_actions/hooks/useDeleteAttachment.js +2 -0
- package/build/screens/attachment_actions/hooks/useDeleteAttachment.js.map +1 -1
- package/build/screens/conversation_new/components/groups_form.d.ts.map +1 -1
- package/build/screens/conversation_new/components/groups_form.js +2 -0
- package/build/screens/conversation_new/components/groups_form.js.map +1 -1
- package/build/screens/conversation_new/components/services_form.d.ts.map +1 -1
- package/build/screens/conversation_new/components/services_form.js +3 -0
- package/build/screens/conversation_new/components/services_form.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 +2 -0
- package/build/screens/conversations/components/list_header_component.js.map +1 -1
- package/build/screens/message_actions_screen.d.ts.map +1 -1
- package/build/screens/message_actions_screen.js +8 -4
- package/build/screens/message_actions_screen.js.map +1 -1
- package/package.json +2 -2
- package/src/components/conversation/attachments/image_attachment.tsx +25 -2
- package/src/components/conversation/message_reaction.tsx +2 -0
- package/src/components/conversations/conversation_actions.tsx +3 -3
- package/src/components/conversations/{action_toggle_button.tsx → swipeable_toggle_button.tsx} +9 -5
- package/src/hooks/use_conversation.ts +2 -0
- package/src/hooks/use_message_create_or_update.ts +3 -0
- package/src/screens/attachment_actions/hooks/useDeleteAttachment.tsx +2 -0
- package/src/screens/conversation_new/components/groups_form.tsx +2 -0
- package/src/screens/conversation_new/components/services_form.tsx +2 -0
- package/src/screens/conversations/components/list_header_component.tsx +2 -0
- package/src/screens/message_actions_screen.tsx +4 -2
- package/build/components/conversations/action_toggle_button.d.ts.map +0 -1
- package/build/components/conversations/action_toggle_button.js.map +0 -1
|
@@ -33,10 +33,10 @@ import { formatDatePreview } from '../../../utils/date'
|
|
|
33
33
|
import { DenormalizedMessageAttachmentResource } from '../../../types/resources/denormalized_attachment_resource'
|
|
34
34
|
import { PlatformPressable } from '@react-navigation/elements'
|
|
35
35
|
import { useTheme } from '../../../hooks'
|
|
36
|
-
import { platformFontWeightMedium } from '../../../utils'
|
|
36
|
+
import { Haptic, platformFontWeightMedium } from '../../../utils'
|
|
37
37
|
|
|
38
38
|
const { width: WINDOW_WIDTH, height: WINDOW_HEIGHT } = Dimensions.get('window')
|
|
39
|
-
const DISMISS_PAN_THRESHOLD =
|
|
39
|
+
const DISMISS_PAN_THRESHOLD = 175
|
|
40
40
|
const MIN_DISTANCE_FOR_PAN = 10 // Higher threshold gives pinching priority
|
|
41
41
|
const SINGLE_FINGER_POINTER = 1 // Single-finger panning / tapping helps to avoid conflicts with pinching
|
|
42
42
|
const DEFAULT_OPACITY = 1
|
|
@@ -161,6 +161,7 @@ const LightboxGallery = ({
|
|
|
161
161
|
const styles = useStyles()
|
|
162
162
|
const insets = useSafeAreaInsets()
|
|
163
163
|
const [currentImageIndex, setCurrentImageIndex] = useState(initialImageIndex)
|
|
164
|
+
const { soft: triggerMaxZoomHaptic, rigid: triggerDismissHaptic } = Haptic
|
|
164
165
|
|
|
165
166
|
// Get current image data
|
|
166
167
|
const currentImage = imageAttachments[currentImageIndex]
|
|
@@ -510,6 +511,15 @@ const LightboxGallery = ({
|
|
|
510
511
|
MAX_SCALE + MAX_SCALE_OVERSHOOT,
|
|
511
512
|
Math.max(MIN_SCALE, newScale)
|
|
512
513
|
)
|
|
514
|
+
|
|
515
|
+
// Check if we just reached the minimum scale threshold
|
|
516
|
+
const previousScale = scale.value
|
|
517
|
+
const reacjedMinScale = previousScale > MIN_SCALE && newScaleClamped <= MIN_SCALE
|
|
518
|
+
|
|
519
|
+
if (reacjedMinScale) {
|
|
520
|
+
runOnJS(triggerDismissHaptic)()
|
|
521
|
+
}
|
|
522
|
+
|
|
513
523
|
scale.value = newScaleClamped
|
|
514
524
|
|
|
515
525
|
// Calculate new translation to keep focal point under fingers
|
|
@@ -545,6 +555,10 @@ const LightboxGallery = ({
|
|
|
545
555
|
// Check if overshooting the max scale and clamp it
|
|
546
556
|
const finalScale = currentScale > MAX_SCALE ? MAX_SCALE : currentScale
|
|
547
557
|
|
|
558
|
+
if (finalScale === MAX_SCALE) {
|
|
559
|
+
runOnJS(triggerMaxZoomHaptic)()
|
|
560
|
+
}
|
|
561
|
+
|
|
548
562
|
// Recalculate translation using focal point to always return to the same position when image is overshooting the max scale
|
|
549
563
|
const newTranslation = zoomToFocalPoint({
|
|
550
564
|
focalPointX: focalX.value,
|
|
@@ -655,6 +669,15 @@ const LightboxGallery = ({
|
|
|
655
669
|
const fadeDistance = Math.max(0, panDistance - halfThreshold)
|
|
656
670
|
const fadeProgress = fadeDistance / halfThreshold
|
|
657
671
|
|
|
672
|
+
// Check if we just crossed the dismiss threshold
|
|
673
|
+
const previousDistance = Math.abs(dismissY.value)
|
|
674
|
+
const crossedDismissThreshold =
|
|
675
|
+
previousDistance < DISMISS_PAN_THRESHOLD && panDistance >= DISMISS_PAN_THRESHOLD
|
|
676
|
+
|
|
677
|
+
if (crossedDismissThreshold) {
|
|
678
|
+
runOnJS(triggerDismissHaptic)()
|
|
679
|
+
}
|
|
680
|
+
|
|
658
681
|
opacity.value = Math.max(0, DEFAULT_OPACITY - fadeProgress)
|
|
659
682
|
dismissY.value = e.translationY
|
|
660
683
|
})
|
|
@@ -8,6 +8,7 @@ import { useMessageReactionToggle } from '../../hooks/use_message_reaction_toggl
|
|
|
8
8
|
import { ReactionCountResource } from '../../types/resources/reaction'
|
|
9
9
|
import { MessageResource } from '../../types'
|
|
10
10
|
import { useCreateAndroidRippleColor } from '../../hooks/use_create_android_ripple_color'
|
|
11
|
+
import { Haptic } from '../../utils/native_adapters'
|
|
11
12
|
|
|
12
13
|
export const REACTION_EMOJIS: Record<ReactionCountResource['value'], string> = {
|
|
13
14
|
thumbs_up: '👍',
|
|
@@ -42,6 +43,7 @@ export function MessageReaction({
|
|
|
42
43
|
if (!REACTION_EMOJIS[reaction.value]) return null
|
|
43
44
|
|
|
44
45
|
const handlePress = () => {
|
|
46
|
+
Haptic.impactLight()
|
|
45
47
|
handleReactionToggle({ value: reaction.value, mine: !!reaction.mine })
|
|
46
48
|
}
|
|
47
49
|
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
import { ConversationResource } from '../../types'
|
|
21
21
|
import { platformPressedOpacityStyle } from '../../utils'
|
|
22
22
|
import { tokens } from '../../vendor/tapestry/tokens'
|
|
23
|
-
import {
|
|
23
|
+
import { SwipeableToggleButton } from './swipeable_toggle_button'
|
|
24
24
|
|
|
25
25
|
export function ConversationActions({
|
|
26
26
|
children,
|
|
@@ -193,7 +193,7 @@ function LeftActions({
|
|
|
193
193
|
|
|
194
194
|
return (
|
|
195
195
|
<View style={styles.actionButtonContainer}>
|
|
196
|
-
<
|
|
196
|
+
<SwipeableToggleButton
|
|
197
197
|
loading={isMarkReadPending}
|
|
198
198
|
disabled={isConversationEmpty}
|
|
199
199
|
toggled={!read}
|
|
@@ -201,7 +201,7 @@ function LeftActions({
|
|
|
201
201
|
toggleContent={latestMessageUnreadToggleContent}
|
|
202
202
|
backgroundColor={tokens.fillColorInteractionSwipeDefault}
|
|
203
203
|
/>
|
|
204
|
-
<
|
|
204
|
+
<SwipeableToggleButton
|
|
205
205
|
loading={isMutedPending}
|
|
206
206
|
toggled={muted}
|
|
207
207
|
onPress={handleMute}
|
package/src/components/conversations/{action_toggle_button.tsx → swipeable_toggle_button.tsx}
RENAMED
|
@@ -5,8 +5,9 @@ import { Icon, IconString, Spinner, Text } from '../display'
|
|
|
5
5
|
import { useCreateAndroidRippleColor, useTheme } from '../../hooks'
|
|
6
6
|
import { platformFontWeightMedium, platformPressedOpacityStyle } from '../../utils/styles'
|
|
7
7
|
import { tokens } from '../../vendor/tapestry/tokens'
|
|
8
|
+
import { Haptic } from '../../utils/native_adapters/configuration'
|
|
8
9
|
|
|
9
|
-
interface
|
|
10
|
+
interface SwipeableToggleButtonProps extends PressableProps {
|
|
10
11
|
backgroundColor: string
|
|
11
12
|
toggled: boolean
|
|
12
13
|
toggleContent: {
|
|
@@ -16,7 +17,7 @@ interface ActionToggleButtonProps extends PressableProps {
|
|
|
16
17
|
loading?: boolean
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
export function
|
|
20
|
+
export function SwipeableToggleButton({
|
|
20
21
|
backgroundColor,
|
|
21
22
|
onPress,
|
|
22
23
|
toggleContent,
|
|
@@ -24,7 +25,7 @@ export function ActionToggleButton({
|
|
|
24
25
|
toggled,
|
|
25
26
|
loading = false,
|
|
26
27
|
...props
|
|
27
|
-
}:
|
|
28
|
+
}: SwipeableToggleButtonProps) {
|
|
28
29
|
const styles = useStyles({ backgroundColor, disabled })
|
|
29
30
|
const androidRippleColor = useCreateAndroidRippleColor({
|
|
30
31
|
color: backgroundColor,
|
|
@@ -34,7 +35,10 @@ export function ActionToggleButton({
|
|
|
34
35
|
|
|
35
36
|
return (
|
|
36
37
|
<Pressable
|
|
37
|
-
onPress={
|
|
38
|
+
onPress={event => {
|
|
39
|
+
Haptic.impactLight()
|
|
40
|
+
onPress?.(event)
|
|
41
|
+
}}
|
|
38
42
|
style={({ pressed }) => [styles.button, pressed && platformPressedOpacityStyle]}
|
|
39
43
|
android_ripple={{ color: androidRippleColor, borderless: false, foreground: true }}
|
|
40
44
|
disabled={disabled || loading}
|
|
@@ -56,7 +60,7 @@ export function ActionToggleButton({
|
|
|
56
60
|
)
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
const useStyles = ({ backgroundColor, disabled }: Partial<
|
|
63
|
+
const useStyles = ({ backgroundColor, disabled }: Partial<SwipeableToggleButtonProps>) => {
|
|
60
64
|
const { colors } = useTheme()
|
|
61
65
|
const fillColor = disabled ? colors.textColorDefaultDisabled : tokens.colorNeutral100White
|
|
62
66
|
const buttonBackgroundColor = disabled
|
|
@@ -5,6 +5,7 @@ import { transformGetToPost } from '../utils/client/request_helpers'
|
|
|
5
5
|
import { useApiClient } from './use_api_client'
|
|
6
6
|
import { getRequestQueryKey, useSuspenseGet } from './use_suspense_api'
|
|
7
7
|
import { getConversationsRequestArgs } from '../utils/request/conversation'
|
|
8
|
+
import { Haptic } from '../utils/native_adapters'
|
|
8
9
|
|
|
9
10
|
export const getConversationRequestArgs = ({ conversation_id }: { conversation_id: number }) => ({
|
|
10
11
|
url: `/me/conversations/${conversation_id}`,
|
|
@@ -139,6 +140,7 @@ export const useConversationDelete = ({ conversation_id }: { conversation_id: nu
|
|
|
139
140
|
},
|
|
140
141
|
onSuccess: () => {
|
|
141
142
|
queryClient.invalidateQueries({ queryKey: [url] })
|
|
143
|
+
Haptic.notificationSuccess()
|
|
142
144
|
},
|
|
143
145
|
})
|
|
144
146
|
}
|
|
@@ -5,6 +5,7 @@ import { ApiCollection, ApiResource, MessageResource } from '../types'
|
|
|
5
5
|
import { chatQueryClient } from '../contexts/api_provider'
|
|
6
6
|
import {
|
|
7
7
|
deleteRecordInPagesData,
|
|
8
|
+
Haptic,
|
|
8
9
|
updateOrCreateRecordInPagesData,
|
|
9
10
|
updateRecordInPagesData,
|
|
10
11
|
} from '../utils'
|
|
@@ -93,6 +94,8 @@ export function useMessageCreateOrUpdate({ conversationId, message }: Props) {
|
|
|
93
94
|
},
|
|
94
95
|
onError: (error, variables, context) => {
|
|
95
96
|
const { message: optimisticMessage } = context || {}
|
|
97
|
+
Haptic.notificationError()
|
|
98
|
+
|
|
96
99
|
// Add error to the optimistic message from the cache on error
|
|
97
100
|
if (optimisticMessage) {
|
|
98
101
|
const queryKey = getMessagesQueryKey({ conversation_id: conversationId })
|
|
@@ -4,6 +4,7 @@ import { useMutation } from '@tanstack/react-query'
|
|
|
4
4
|
import { useApiClient } from '../../../hooks/use_api_client'
|
|
5
5
|
import { useCallback } from 'react'
|
|
6
6
|
import { useConversationMessages } from '../../../hooks/use_conversation_messages'
|
|
7
|
+
import { Haptic } from '../../../utils/native_adapters'
|
|
7
8
|
|
|
8
9
|
type UseDeleteAttachmentProps = {
|
|
9
10
|
conversation_id: number
|
|
@@ -30,6 +31,7 @@ export function useDeleteAttachment({
|
|
|
30
31
|
mutationFn: deleteAttachment,
|
|
31
32
|
onSuccess: () => {
|
|
32
33
|
refetch()
|
|
34
|
+
Haptic.notificationSuccess()
|
|
33
35
|
navigation.goBack()
|
|
34
36
|
},
|
|
35
37
|
onError: () => {
|
|
@@ -14,6 +14,7 @@ import { GroupsGroupResource } from '../../../types'
|
|
|
14
14
|
import { GraphId } from '../../../types/resources/group_resource'
|
|
15
15
|
import { pluralize } from '../../../utils'
|
|
16
16
|
import { Divider, FormList } from './form_list'
|
|
17
|
+
import { Haptic } from '../../../utils/native_adapters'
|
|
17
18
|
|
|
18
19
|
type GroupsFormProps = {
|
|
19
20
|
groupId: number
|
|
@@ -44,6 +45,7 @@ export const GroupsForm = ({ groupId, chat_group_graph_id }: GroupsFormProps) =>
|
|
|
44
45
|
chat_group_graph_id,
|
|
45
46
|
})
|
|
46
47
|
)
|
|
48
|
+
Haptic.notificationSuccess()
|
|
47
49
|
},
|
|
48
50
|
[chat_group_graph_id, navigation]
|
|
49
51
|
)
|
|
@@ -7,6 +7,7 @@ import { useMarkAllRead } from '../../../hooks/use_conversations_actions'
|
|
|
7
7
|
import { useCanDisplayGroups } from '../../../hooks/use_groups'
|
|
8
8
|
import { ConversationsScreenProps } from '../conversations_screen'
|
|
9
9
|
import { ChatGroupBadge } from './chat_group_badge'
|
|
10
|
+
import { Haptic } from '../../../utils/native_adapters'
|
|
10
11
|
|
|
11
12
|
const ROW_PADDING_HORIZONTAL = 16
|
|
12
13
|
|
|
@@ -41,6 +42,7 @@ export const ListHeaderComponent = () => {
|
|
|
41
42
|
|
|
42
43
|
const handleMarkAllRead = useCallback(() => {
|
|
43
44
|
currentPersonCache.update({ unreadCount: 0 })
|
|
45
|
+
Haptic.notificationSuccess()
|
|
44
46
|
markAllRead()
|
|
45
47
|
}, [currentPersonCache, markAllRead])
|
|
46
48
|
|
|
@@ -82,6 +82,7 @@ export function MessageActionsScreen({ route }: MessageActionsScreenProps) {
|
|
|
82
82
|
mutationFn: deleteMessage,
|
|
83
83
|
onSuccess: () => {
|
|
84
84
|
refetch()
|
|
85
|
+
Haptic.notificationSuccess()
|
|
85
86
|
navigation.goBack()
|
|
86
87
|
},
|
|
87
88
|
onError: () => {
|
|
@@ -129,12 +130,13 @@ export function MessageActionsScreen({ route }: MessageActionsScreenProps) {
|
|
|
129
130
|
<Reaction
|
|
130
131
|
key={index}
|
|
131
132
|
reaction={reaction}
|
|
132
|
-
onPress={() =>
|
|
133
|
+
onPress={() => {
|
|
134
|
+
Haptic.impactLight()
|
|
133
135
|
handleReactionToggle({
|
|
134
136
|
value: reaction.value,
|
|
135
137
|
mine: reaction.mine,
|
|
136
138
|
})
|
|
137
|
-
}
|
|
139
|
+
}}
|
|
138
140
|
/>
|
|
139
141
|
))}
|
|
140
142
|
</View>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"action_toggle_button.d.ts","sourceRoot":"","sources":["../../../src/components/conversations/action_toggle_button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAC7E,OAAO,EAAQ,UAAU,EAAiB,MAAM,YAAY,CAAA;AAK5D,UAAU,uBAAwB,SAAQ,cAAc;IACtD,eAAe,EAAE,MAAM,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE;QACb,IAAI,EAAE;YAAE,QAAQ,EAAE,UAAU,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAA;QAC7C,KAAK,EAAE;YAAE,QAAQ,EAAE,UAAU,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAA;KAC/C,CAAA;IACD,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,wBAAgB,kBAAkB,CAAC,EACjC,eAAe,EACf,OAAO,EACP,aAAa,EACb,QAAgB,EAChB,OAAO,EACP,OAAe,EACf,GAAG,KAAK,EACT,EAAE,uBAAuB,qBA8BzB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"action_toggle_button.js","sourceRoot":"","sources":["../../../src/components/conversations/action_toggle_button.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react'\nimport { StyleSheet } from 'react-native'\nimport { Pressable, type PressableProps } from 'react-native-gesture-handler'\nimport { Icon, IconString, Spinner, Text } from '../display'\nimport { useCreateAndroidRippleColor, useTheme } from '../../hooks'\nimport { platformFontWeightMedium, platformPressedOpacityStyle } from '../../utils/styles'\nimport { tokens } from '../../vendor/tapestry/tokens'\n\ninterface ActionToggleButtonProps extends PressableProps {\n backgroundColor: string\n toggled: boolean\n toggleContent: {\n true: { iconName: IconString; label: string }\n false: { iconName: IconString; label: string }\n }\n loading?: boolean\n}\n\nexport function ActionToggleButton({\n backgroundColor,\n onPress,\n toggleContent,\n disabled = false,\n toggled,\n loading = false,\n ...props\n}: ActionToggleButtonProps) {\n const styles = useStyles({ backgroundColor, disabled })\n const androidRippleColor = useCreateAndroidRippleColor({\n color: backgroundColor,\n })\n\n const { iconName, label } = toggleContent[toggled ? 'true' : 'false']\n\n return (\n <Pressable\n onPress={onPress}\n style={({ pressed }) => [styles.button, pressed && platformPressedOpacityStyle]}\n android_ripple={{ color: androidRippleColor, borderless: false, foreground: true }}\n disabled={disabled || loading}\n accessibilityRole=\"togglebutton\"\n accessibilityState={{ checked: toggled }}\n {...props}\n >\n {loading ? (\n <Spinner size={20} />\n ) : (\n <>\n <Icon name={iconName} style={styles.icon} size={20} />\n <Text variant=\"footnote\" style={styles.text}>\n {label}\n </Text>\n </>\n )}\n </Pressable>\n )\n}\n\nconst useStyles = ({ backgroundColor, disabled }: Partial<ActionToggleButtonProps>) => {\n const { colors } = useTheme()\n const fillColor = disabled ? colors.textColorDefaultDisabled : tokens.colorNeutral100White\n const buttonBackgroundColor = disabled\n ? colors.fillColorButtonNeutralSolidDisabled\n : backgroundColor\n\n return StyleSheet.create({\n button: {\n flex: 1,\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 4,\n height: '100%',\n backgroundColor: buttonBackgroundColor,\n },\n icon: {\n color: fillColor,\n marginTop: 4,\n },\n text: {\n color: fillColor,\n fontWeight: platformFontWeightMedium,\n },\n })\n}\n"]}
|