@planningcenter/chat-react-native 3.1.0-rc.2 → 3.1.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/message.d.ts +1 -1
- package/build/components/conversation/message.js.map +1 -1
- package/build/components/conversations.d.ts.map +1 -1
- package/build/components/conversations.js +3 -6
- package/build/components/conversations.js.map +1 -1
- package/build/hooks/use_conversation.d.ts +3 -3
- 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 +4 -3
- package/build/hooks/use_conversation_jolt_events.js.map +1 -1
- package/build/hooks/use_conversation_messages.d.ts +3 -3
- package/build/hooks/use_conversation_messages.js.map +1 -1
- package/build/hooks/use_conversation_messages_jolt_events.d.ts +1 -1
- package/build/hooks/use_conversation_messages_jolt_events.js.map +1 -1
- package/build/hooks/use_current_person.js +1 -1
- package/build/hooks/use_current_person.js.map +1 -1
- package/build/screens/conversation_details_screen.d.ts +1 -1
- package/build/screens/conversation_details_screen.d.ts.map +1 -1
- package/build/screens/conversation_details_screen.js +47 -17
- package/build/screens/conversation_details_screen.js.map +1 -1
- package/build/screens/conversation_screen.d.ts +1 -1
- package/build/screens/conversation_screen.js.map +1 -1
- package/build/screens/create/conversation_create_screen.js.map +1 -1
- package/build/screens/design_system_screen.js +2 -2
- package/build/screens/design_system_screen.js.map +1 -1
- package/build/screens/message_actions_screen.d.ts +1 -1
- package/build/screens/message_actions_screen.js.map +1 -1
- package/build/screens/reactions_screen.d.ts +1 -1
- package/build/screens/reactions_screen.js +2 -2
- package/build/screens/reactions_screen.js.map +1 -1
- package/build/types/api_primitives.d.ts +1 -1
- package/build/types/api_primitives.d.ts.map +1 -1
- package/build/types/api_primitives.js.map +1 -1
- package/build/types/resources/app_grant.d.ts +2 -0
- package/build/types/resources/app_grant.d.ts.map +1 -1
- package/build/types/resources/app_grant.js.map +1 -1
- package/build/types/resources/conversation.d.ts +1 -1
- package/build/types/resources/conversation.js.map +1 -1
- package/build/types/resources/groups/groups_group_resource.d.ts +2 -0
- package/build/types/resources/groups/groups_group_resource.d.ts.map +1 -1
- package/build/types/resources/groups/groups_group_resource.js.map +1 -1
- package/build/types/resources/member.d.ts +1 -1
- package/build/types/resources/member.js.map +1 -1
- package/build/types/resources/person.d.ts +2 -0
- package/build/types/resources/person.d.ts.map +1 -1
- package/build/types/resources/person.js.map +1 -1
- package/build/types/resources/reaction.js.map +1 -1
- package/build/utils/cache/page_mutations.d.ts +3 -1
- package/build/utils/cache/page_mutations.d.ts.map +1 -1
- package/build/utils/cache/page_mutations.js.map +1 -1
- package/build/utils/jolt/transform_message_event_data_to_message_resource.d.ts +1 -1
- package/build/utils/jolt/transform_message_event_data_to_message_resource.js +2 -2
- package/build/utils/jolt/transform_message_event_data_to_message_resource.js.map +1 -1
- package/build/utils/jolt/transform_reaction_event_data_to_reaction_count_resource.d.ts +1 -1
- package/build/utils/jolt/transform_reaction_event_data_to_reaction_count_resource.js.map +1 -1
- package/build/utils/theme.d.ts +1 -0
- package/build/utils/theme.d.ts.map +1 -1
- package/build/utils/theme.js +2 -0
- package/build/utils/theme.js.map +1 -1
- package/build/vendor/tapestry/tokens.d.ts +2 -0
- package/build/vendor/tapestry/tokens.d.ts.map +1 -1
- package/build/vendor/tapestry/tokens.js +2 -0
- package/build/vendor/tapestry/tokens.js.map +1 -1
- package/package.json +2 -2
- package/src/components/conversation/message.tsx +1 -1
- package/src/components/conversations.tsx +6 -8
- package/src/hooks/use_conversation.ts +3 -3
- package/src/hooks/use_conversation_jolt_events.ts +8 -11
- package/src/hooks/use_conversation_messages.ts +3 -3
- package/src/hooks/use_conversation_messages_jolt_events.ts +1 -1
- package/src/hooks/use_current_person.ts +1 -1
- package/src/screens/conversation_details_screen.tsx +65 -15
- package/src/screens/conversation_screen.tsx +1 -1
- package/src/screens/create/conversation_create_screen.tsx +1 -1
- package/src/screens/design_system_screen.tsx +2 -2
- package/src/screens/message_actions_screen.tsx +1 -1
- package/src/screens/reactions_screen.tsx +3 -3
- package/src/types/api_primitives.ts +1 -1
- package/src/types/resources/app_grant.ts +2 -0
- package/src/types/resources/conversation.ts +1 -1
- package/src/types/resources/groups/groups_group_resource.ts +2 -0
- package/src/types/resources/member.ts +1 -1
- package/src/types/resources/person.ts +2 -0
- package/src/types/resources/reaction.ts +1 -1
- package/src/utils/cache/page_mutations.ts +1 -1
- package/src/utils/jolt/transform_message_event_data_to_message_resource.ts +3 -3
- package/src/utils/jolt/transform_reaction_event_data_to_reaction_count_resource.ts +1 -1
- package/src/utils/theme.ts +3 -0
- package/src/vendor/tapestry/tokens.ts +2 -0
|
@@ -15,7 +15,7 @@ import { JoltReactionEvent } from '../types/jolt_events'
|
|
|
15
15
|
import { transformReactionEventDataToReactionCountResource } from '../utils/jolt/transform_reaction_event_data_to_reaction_count_resource'
|
|
16
16
|
|
|
17
17
|
interface Props {
|
|
18
|
-
conversationId:
|
|
18
|
+
conversationId: number
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export function useConversationMessagesJoltEvents({ conversationId }: Props) {
|
|
@@ -6,6 +6,7 @@ import React, {
|
|
|
6
6
|
type SetStateAction,
|
|
7
7
|
type Dispatch,
|
|
8
8
|
type ReactNode,
|
|
9
|
+
useRef,
|
|
9
10
|
} from 'react'
|
|
10
11
|
import {
|
|
11
12
|
StyleSheet,
|
|
@@ -14,6 +15,7 @@ import {
|
|
|
14
15
|
type TextStyle,
|
|
15
16
|
type ViewStyle,
|
|
16
17
|
type ViewProps,
|
|
18
|
+
Pressable,
|
|
17
19
|
} from 'react-native'
|
|
18
20
|
import { Heading, Icon, Person, Switch, Text } from '../components'
|
|
19
21
|
import { useSuspenseGet, useTheme } from '../hooks'
|
|
@@ -26,6 +28,7 @@ import { MemberResource, isDefined } from '../types'
|
|
|
26
28
|
import { HeaderRightButton } from '../navigation/header'
|
|
27
29
|
import { FlashList } from '@shopify/flash-list'
|
|
28
30
|
import { space } from '../utils'
|
|
31
|
+
import { tokens } from '../vendor/tapestry/tokens'
|
|
29
32
|
|
|
30
33
|
// =========================================
|
|
31
34
|
// ====== Factory Constants & Types ========
|
|
@@ -58,7 +61,7 @@ interface DataItem<T, TName extends SectionTypes> {
|
|
|
58
61
|
// =================================
|
|
59
62
|
|
|
60
63
|
export type ConversationDetailsScreenProps = StaticScreenProps<{
|
|
61
|
-
conversation_id:
|
|
64
|
+
conversation_id: number
|
|
62
65
|
}>
|
|
63
66
|
|
|
64
67
|
export function ConversationDetailsScreen({ route }: ConversationDetailsScreenProps) {
|
|
@@ -70,6 +73,9 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
|
|
|
70
73
|
const { muted, setMuted } = useConversationMute(route.params)
|
|
71
74
|
const { mutate: saveTitle } = useConversationUpdate(route.params)
|
|
72
75
|
|
|
76
|
+
const trimmedTitle = title.trim()
|
|
77
|
+
const emptyTitle = trimmedTitle === '' || title === null
|
|
78
|
+
|
|
73
79
|
const canUpdate = conversation.memberAbility?.canUpdate || false
|
|
74
80
|
const { data: members } = useSuspenseGet<MemberResource[]>({
|
|
75
81
|
url: `/me/conversations/${route.params.conversation_id}/members`,
|
|
@@ -90,14 +96,14 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
|
|
|
90
96
|
return (
|
|
91
97
|
<HeaderRightButton
|
|
92
98
|
onPress={() => {
|
|
93
|
-
saveTitle({ title })
|
|
99
|
+
saveTitle({ title: trimmedTitle || conversation.title })
|
|
94
100
|
navigation.goBack()
|
|
95
101
|
}}
|
|
96
102
|
>
|
|
97
103
|
Done
|
|
98
104
|
</HeaderRightButton>
|
|
99
105
|
)
|
|
100
|
-
}, [navigation, saveTitle,
|
|
106
|
+
}, [conversation.title, navigation, saveTitle, trimmedTitle])
|
|
101
107
|
|
|
102
108
|
useEffect(() => {
|
|
103
109
|
navigation.setOptions({
|
|
@@ -109,8 +115,14 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
|
|
|
109
115
|
{
|
|
110
116
|
type: SectionTypes.view,
|
|
111
117
|
data: {
|
|
112
|
-
children:
|
|
113
|
-
|
|
118
|
+
children: (
|
|
119
|
+
<TitleInput
|
|
120
|
+
canUpdate={canUpdate}
|
|
121
|
+
title={title}
|
|
122
|
+
setTitle={setTitle}
|
|
123
|
+
isEmpty={emptyTitle}
|
|
124
|
+
/>
|
|
125
|
+
),
|
|
114
126
|
},
|
|
115
127
|
},
|
|
116
128
|
{
|
|
@@ -215,23 +227,45 @@ interface InputProps {
|
|
|
215
227
|
canUpdate: boolean
|
|
216
228
|
title: string
|
|
217
229
|
setTitle: Dispatch<SetStateAction<string>>
|
|
230
|
+
style?: ViewStyle
|
|
231
|
+
isEmpty: boolean
|
|
218
232
|
}
|
|
219
233
|
|
|
220
|
-
function TitleInput({ canUpdate, title, setTitle }: InputProps) {
|
|
234
|
+
function TitleInput({ canUpdate, title, setTitle, style, isEmpty }: InputProps) {
|
|
221
235
|
const styles = useStyles()
|
|
236
|
+
const textRef = useRef<TextInput>(null)
|
|
237
|
+
|
|
238
|
+
const handleFocus = () => {
|
|
239
|
+
if (textRef.current) {
|
|
240
|
+
textRef.current.focus()
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
222
244
|
return (
|
|
223
|
-
|
|
224
|
-
<View style={
|
|
225
|
-
<Text variant="tertiary">
|
|
226
|
-
|
|
245
|
+
<Pressable style={[styles.titleContainer, style]} onPress={() => handleFocus()}>
|
|
246
|
+
<View style={styles.titleLabelContainer}>
|
|
247
|
+
<Text variant="tertiary" style={styles.titleLabel}>
|
|
248
|
+
Title
|
|
249
|
+
</Text>
|
|
250
|
+
{!canUpdate && <Icon name="general.lock" style={styles.titleDisabledIcon} />}
|
|
227
251
|
</View>
|
|
228
252
|
<TextInput
|
|
253
|
+
ref={textRef}
|
|
229
254
|
editable={canUpdate}
|
|
230
255
|
onChangeText={setTitle}
|
|
231
256
|
style={[styles.titleInput, !canUpdate && styles.titleInputDisabled]}
|
|
232
257
|
value={title}
|
|
258
|
+
multiline
|
|
259
|
+
maxLength={255} // Matches Chat Web
|
|
260
|
+
enterKeyHint="done"
|
|
261
|
+
submitBehavior="blurAndSubmit"
|
|
233
262
|
/>
|
|
234
|
-
|
|
263
|
+
{isEmpty && (
|
|
264
|
+
<Text variant="footnote" style={styles.inputValidationText}>
|
|
265
|
+
A title is required for your conversation.
|
|
266
|
+
</Text>
|
|
267
|
+
)}
|
|
268
|
+
</Pressable>
|
|
235
269
|
)
|
|
236
270
|
}
|
|
237
271
|
|
|
@@ -298,17 +332,33 @@ const useStyles = ({ isStart, isEnd }: { isStart?: boolean; isEnd?: boolean } =
|
|
|
298
332
|
addBottomBorder: {
|
|
299
333
|
borderBottomWidth: isEnd ? 0 : 1,
|
|
300
334
|
},
|
|
301
|
-
titleContainer: {
|
|
302
|
-
|
|
335
|
+
titleContainer: {
|
|
336
|
+
gap: 4,
|
|
337
|
+
},
|
|
303
338
|
titleLabelContainer: {
|
|
304
339
|
flexDirection: 'row',
|
|
305
340
|
alignItems: 'center',
|
|
306
|
-
gap:
|
|
341
|
+
gap: 4,
|
|
342
|
+
},
|
|
343
|
+
titleLabel: {
|
|
344
|
+
color: colors.textColorDefaultSecondary,
|
|
345
|
+
},
|
|
346
|
+
titleDisabledIcon: {
|
|
347
|
+
color: colors.iconColorDefaultSecondary,
|
|
307
348
|
},
|
|
308
349
|
titleInput: {
|
|
309
350
|
color: colors.textColorDefaultPrimary,
|
|
351
|
+
fontSize: tokens.fontSizeMd,
|
|
352
|
+
},
|
|
353
|
+
titleInputDisabled: {
|
|
354
|
+
color: colors.textColorDefaultSecondary,
|
|
355
|
+
},
|
|
356
|
+
inputValidationText: {
|
|
357
|
+
color: colors.statusErrorText,
|
|
358
|
+
paddingTop: 8,
|
|
359
|
+
borderTopWidth: 1,
|
|
360
|
+
borderColor: colors.borderColorStatusError,
|
|
310
361
|
},
|
|
311
|
-
titleInputDisabled: { opacity: 0.7 },
|
|
312
362
|
header: {
|
|
313
363
|
paddingVertical: space(1.5),
|
|
314
364
|
},
|
|
@@ -16,7 +16,7 @@ import { useConversation } from '../hooks/use_conversation'
|
|
|
16
16
|
import { useConversationMessages } from '../hooks/use_conversation_messages'
|
|
17
17
|
|
|
18
18
|
type ConversationRouteProps = {
|
|
19
|
-
conversation_id:
|
|
19
|
+
conversation_id: number
|
|
20
20
|
chat_group_graph_id?: string
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -64,7 +64,7 @@ export const ConversationCreateScreen = ({ route }: ConversationCreateScreenProp
|
|
|
64
64
|
})
|
|
65
65
|
|
|
66
66
|
const handleRedirectToConversation = useCallback(
|
|
67
|
-
({ conversation_id }: { conversation_id:
|
|
67
|
+
({ conversation_id }: { conversation_id: number }) => {
|
|
68
68
|
// exit from the create stack
|
|
69
69
|
navigation.getParent()?.goBack()
|
|
70
70
|
// navigate to the conversation screen
|
|
@@ -52,7 +52,7 @@ const URL = {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
const personAdult = {
|
|
55
|
-
id:
|
|
55
|
+
id: 1,
|
|
56
56
|
type: 'Member' as const,
|
|
57
57
|
name: 'John Doe',
|
|
58
58
|
avatar: URL.avatar,
|
|
@@ -61,7 +61,7 @@ const personAdult = {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
const personChild = {
|
|
64
|
-
id:
|
|
64
|
+
id: 2,
|
|
65
65
|
type: 'Member' as const,
|
|
66
66
|
name: 'Kid McChild',
|
|
67
67
|
avatar: URL.two_avatars[1],
|
|
@@ -24,7 +24,7 @@ export const MessageActionsScreenOptions: NativeStackNavigationOptions = {
|
|
|
24
24
|
|
|
25
25
|
export type ReactionScreenProps = StaticScreenProps<{
|
|
26
26
|
message_id: string
|
|
27
|
-
conversation_id:
|
|
27
|
+
conversation_id: number
|
|
28
28
|
}>
|
|
29
29
|
|
|
30
30
|
export function MessageActionsScreen({ route }: ReactionScreenProps) {
|
|
@@ -20,7 +20,7 @@ export const ReactionsScreenOptions: NativeStackNavigationOptions = {
|
|
|
20
20
|
|
|
21
21
|
export type ReactionScreenProps = StaticScreenProps<{
|
|
22
22
|
message_id: string
|
|
23
|
-
conversation_id:
|
|
23
|
+
conversation_id: number
|
|
24
24
|
reaction_value?: string
|
|
25
25
|
}>
|
|
26
26
|
|
|
@@ -45,7 +45,7 @@ export function ReactionsScreen({ route }: ReactionScreenProps) {
|
|
|
45
45
|
React.useState<ReactionCountResource>(initialReactionCount)
|
|
46
46
|
|
|
47
47
|
const authorIds = reactionCount.authorIds
|
|
48
|
-
const authors = members.filter(member => authorIds.includes(member.id))
|
|
48
|
+
const authors = members.filter(member => authorIds.includes(member.id.toString()))
|
|
49
49
|
|
|
50
50
|
return (
|
|
51
51
|
<View style={styles.container}>
|
|
@@ -64,7 +64,7 @@ export function ReactionsScreen({ route }: ReactionScreenProps) {
|
|
|
64
64
|
/>
|
|
65
65
|
<FlatList
|
|
66
66
|
data={authors}
|
|
67
|
-
keyExtractor={item => item.id}
|
|
67
|
+
keyExtractor={item => item.id.toString()}
|
|
68
68
|
renderItem={({ item: author }) => (
|
|
69
69
|
<View style={styles.authorList}>
|
|
70
70
|
<Avatar size={'md'} sourceUri={author.avatar} />
|
|
@@ -8,7 +8,7 @@ export function transformMessageEventDataToMessageResource({
|
|
|
8
8
|
currentPersonId,
|
|
9
9
|
}: {
|
|
10
10
|
data: MessageCreatedEvent['data']['data']
|
|
11
|
-
currentPersonId:
|
|
11
|
+
currentPersonId: number
|
|
12
12
|
}): MessageResource {
|
|
13
13
|
return {
|
|
14
14
|
type: 'Message',
|
|
@@ -18,11 +18,11 @@ export function transformMessageEventDataToMessageResource({
|
|
|
18
18
|
createdAt: data.created_at,
|
|
19
19
|
deletedAt: data.deleted_at,
|
|
20
20
|
textEditedAt: data.text_edited_at,
|
|
21
|
-
mine: data.author_id
|
|
21
|
+
mine: data.author_id === currentPersonId,
|
|
22
22
|
attachments: deepCamelCaseKeys<DenormalizedAttachmentResource[]>(data.attachments) || [],
|
|
23
23
|
author: {
|
|
24
24
|
type: 'Person',
|
|
25
|
-
id: data.author_id
|
|
25
|
+
id: data.author_id,
|
|
26
26
|
name: data.author_name,
|
|
27
27
|
avatar: data.author_avatar,
|
|
28
28
|
},
|
package/src/utils/theme.ts
CHANGED
|
@@ -73,6 +73,7 @@ interface ChatColors {
|
|
|
73
73
|
statusNeutralIcon: string
|
|
74
74
|
statusNeutralText: string
|
|
75
75
|
statusNeutralBackground: string
|
|
76
|
+
borderColorStatusError: string
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
const colorsChatLight: ChatColors = {
|
|
@@ -99,6 +100,7 @@ const colorsChatLight: ChatColors = {
|
|
|
99
100
|
statusNeutralIcon: tokens.iconColorStatusNeutralPrimary,
|
|
100
101
|
statusNeutralText: tokens.textColorStatusNeutral,
|
|
101
102
|
statusNeutralBackground: tokens.fillColorStatusNeutralGhost,
|
|
103
|
+
borderColorStatusError: tokens.borderColorStatusError,
|
|
102
104
|
}
|
|
103
105
|
|
|
104
106
|
const colorsChatDark: ChatColors = {
|
|
@@ -125,6 +127,7 @@ const colorsChatDark: ChatColors = {
|
|
|
125
127
|
statusNeutralIcon: tokens.iconColorStatusNeutralPrimaryDark,
|
|
126
128
|
statusNeutralText: tokens.textColorStatusNeutralDark,
|
|
127
129
|
statusNeutralBackground: tokens.fillColorStatusNeutralGhostDark,
|
|
130
|
+
borderColorStatusError: tokens.borderColorStatusErrorDark,
|
|
128
131
|
}
|
|
129
132
|
|
|
130
133
|
const chatThemeColorMap = {
|
|
@@ -20,6 +20,8 @@ const colorPrimitives = {
|
|
|
20
20
|
colorNeutral95: 'hsl(0, 0%, 95%)',
|
|
21
21
|
colorNeutral97: 'hsl(0, 0%, 97%)',
|
|
22
22
|
colorNeutral98: 'hsl(0, 0%, 98%)',
|
|
23
|
+
borderColorStatusError: 'hsl(8, 60%, 47%)',
|
|
24
|
+
borderColorStatusErrorDark: 'hsl(8, 60%, 55%)',
|
|
23
25
|
colorNeutral100White: 'hsl(0, 0%, 100%)',
|
|
24
26
|
fillColorInteractionDefault: 'hsl(204, 100%, 40%)',
|
|
25
27
|
fillColorStatusNeutralGhost: 'hsl(0, 0%, 93%)',
|