@usechatting/react-native 0.1.3 → 0.1.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.
|
@@ -12,7 +12,7 @@ export function ChattingConversationScreen(input) {
|
|
|
12
12
|
? "Team is online"
|
|
13
13
|
: "Team is away"
|
|
14
14
|
: null;
|
|
15
|
-
return (_jsxs(View, { style: styles.screen, children: [_jsxs(View, { style: [styles.header, { backgroundColor: brandColor }], children: [title ? _jsx(Text, { style: styles.title, children: title }) : null, teamStatus ? _jsx(Text, { style: styles.subtitle, children: teamStatus }) : null] }), _jsxs(ScrollView, { style: styles.scroll, contentContainerStyle: styles.content, children: [conversation.errorMessage ? (_jsx(View, { style: styles.banner, children: _jsx(Text, { style: [styles.bannerText, styles.error], children: conversation.errorMessage }) })) : null, conversation.isLoading ? _jsx(ActivityIndicator, { color: brandColor }) : null, !conversation.isLoading && conversation.messages.length === 0 ? (_jsxs(View, { style: styles.row, children: [_jsx(Bubble, { message: greeting, isUser: false, brandColor: brandColor }), _jsx(View, { style: styles.spacer })] })) : null, conversation.messages.map((message) => (_jsx(View, { style: styles.row, children: message.sender === "team" ? (_jsxs(_Fragment, { children: [_jsx(Bubble, { message: message.content || "(attachment placeholder)", isUser: false, brandColor: brandColor }), _jsx(View, { style: styles.spacer })] })) : (_jsxs(_Fragment, { children: [_jsx(View, { style: styles.spacer }), _jsx(Bubble, { message: message.content || "(attachment placeholder)", isUser: true, brandColor: brandColor })] })) }, message.id))), conversation.teamTyping ? (_jsxs(View, { style: styles.row, children: [_jsx(Bubble, { message: "Team is typing...", isUser: false, subtle: true, brandColor: brandColor }), _jsx(View, { style: styles.spacer })] })) : null, conversation.faqSuggestions?.items.map((item) => (_jsxs(View, { style: styles.faqCard, children: [_jsx(Text, { style: styles.faqTitle, children: item.question }), _jsx(Text, { style: styles.faqText, children: item.answer })] }, item.id))), conversation.faqSuggestions?.fallbackMessage ? (_jsx(Text, { style: styles.meta, children: conversation.faqSuggestions.fallbackMessage })) : null] }), _jsx(View, { style: styles.footer, children: _jsxs(View, { style: styles.composerRow, children: [_jsx(TextInput, { value: conversation.draftMessage, onChangeText: conversation.setDraftMessage, placeholder: "Type a message", multiline: true, style: [styles.input, styles.composer] }), _jsx(TouchableOpacity, { style: [styles.button, styles.sendButton, { backgroundColor: brandColor }], onPress: () => void conversation.sendMessage(), children: _jsx(Text, { style: styles.buttonText, children:
|
|
15
|
+
return (_jsxs(View, { style: styles.screen, children: [_jsxs(View, { style: [styles.header, { backgroundColor: brandColor }], children: [title ? _jsx(Text, { style: styles.title, children: title }) : null, teamStatus ? _jsx(Text, { style: styles.subtitle, children: teamStatus }) : null] }), _jsxs(ScrollView, { style: styles.scroll, contentContainerStyle: styles.content, children: [conversation.errorMessage ? (_jsx(View, { style: styles.banner, children: _jsx(Text, { style: [styles.bannerText, styles.error], children: conversation.errorMessage }) })) : null, conversation.isLoading ? _jsx(ActivityIndicator, { color: brandColor }) : null, !conversation.isLoading && conversation.messages.length === 0 ? (_jsxs(View, { style: styles.row, children: [_jsx(Bubble, { message: greeting, isUser: false, brandColor: brandColor }), _jsx(View, { style: styles.spacer })] })) : null, conversation.messages.map((message) => (_jsx(View, { style: styles.row, children: message.sender === "team" ? (_jsxs(_Fragment, { children: [_jsx(Bubble, { message: message.content || "(attachment placeholder)", isUser: false, brandColor: brandColor }), _jsx(View, { style: styles.spacer })] })) : (_jsxs(_Fragment, { children: [_jsx(View, { style: styles.spacer }), _jsx(Bubble, { message: message.content || "(attachment placeholder)", isUser: true, brandColor: brandColor })] })) }, message.id))), conversation.teamTyping ? (_jsxs(View, { style: styles.row, children: [_jsx(Bubble, { message: "Team is typing...", isUser: false, subtle: true, brandColor: brandColor }), _jsx(View, { style: styles.spacer })] })) : null, conversation.faqSuggestions?.items.map((item) => (_jsxs(View, { style: styles.faqCard, children: [_jsx(Text, { style: styles.faqTitle, children: item.question }), _jsx(Text, { style: styles.faqText, children: item.answer })] }, item.id))), conversation.faqSuggestions?.fallbackMessage ? (_jsx(Text, { style: styles.meta, children: conversation.faqSuggestions.fallbackMessage })) : null] }), _jsx(View, { style: styles.footer, children: _jsxs(View, { style: styles.composerRow, children: [_jsx(TextInput, { value: conversation.draftMessage, onChangeText: conversation.setDraftMessage, placeholder: "Type a message", multiline: true, style: [styles.input, styles.composer] }), _jsx(TouchableOpacity, { style: [styles.button, styles.sendButton, { backgroundColor: brandColor }], onPress: () => void conversation.sendMessage(), children: _jsx(Text, { style: styles.buttonText, children: "Send" }) })] }) })] }));
|
|
16
16
|
}
|
|
17
17
|
function Bubble(input) {
|
|
18
18
|
return (_jsx(View, { style: [
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ChattingMessage } from "./chatting-types";
|
|
2
|
+
export declare function createOptimisticMessage(content: string): ChattingMessage;
|
|
3
|
+
export declare function settleOptimisticMessage(messages: ChattingMessage[], optimisticId: string, savedMessage: ChattingMessage): ChattingMessage[];
|
|
4
|
+
export declare function removeOptimisticMessage(messages: ChattingMessage[], optimisticId: string): ChattingMessage[];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function createOptimisticMessage(content) {
|
|
2
|
+
return {
|
|
3
|
+
id: `pending-${Date.now()}-${Math.random().toString(16).slice(2)}`,
|
|
4
|
+
content,
|
|
5
|
+
createdAt: new Date().toISOString(),
|
|
6
|
+
sender: "user",
|
|
7
|
+
attachments: [],
|
|
8
|
+
pending: true
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export function settleOptimisticMessage(messages, optimisticId, savedMessage) {
|
|
12
|
+
const remaining = messages.filter((message) => message.id !== optimisticId);
|
|
13
|
+
return remaining.some((message) => message.id === savedMessage.id)
|
|
14
|
+
? remaining
|
|
15
|
+
: [...remaining, savedMessage];
|
|
16
|
+
}
|
|
17
|
+
export function removeOptimisticMessage(messages, optimisticId) {
|
|
18
|
+
return messages.filter((message) => message.id !== optimisticId);
|
|
19
|
+
}
|
package/dist/chatting-types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from "react";
|
|
2
2
|
import { applyConversation, startConversationSync, syncTyping } from "./chatting-hook-helpers";
|
|
3
|
+
import { createOptimisticMessage, removeOptimisticMessage, settleOptimisticMessage } from "./chatting-optimistic-message";
|
|
3
4
|
import { normalizeText, toErrorMessage } from "./chatting-utils";
|
|
4
5
|
export function useChattingConversation(input) {
|
|
5
6
|
const [siteConfig, setSiteConfig] = useState(null);
|
|
@@ -112,15 +113,21 @@ export function useChattingConversation(input) {
|
|
|
112
113
|
if (!nextMessage) {
|
|
113
114
|
return;
|
|
114
115
|
}
|
|
116
|
+
const optimisticMessage = createOptimisticMessage(nextMessage);
|
|
115
117
|
setIsSending(true);
|
|
116
118
|
setErrorMessage(null);
|
|
119
|
+
setDraftMessageState("");
|
|
120
|
+
setMessages((current) => [...current, optimisticMessage]);
|
|
117
121
|
try {
|
|
118
|
-
await input.client.sendMessage(nextMessage, { context: input.context, email: emailAddress });
|
|
119
|
-
|
|
122
|
+
const result = await input.client.sendMessage(nextMessage, { context: input.context, email: emailAddress });
|
|
123
|
+
setMessages((current) => settleOptimisticMessage(current, optimisticMessage.id, result.message));
|
|
124
|
+
setFaqSuggestions(result.faqSuggestions);
|
|
120
125
|
setTeamTyping(false);
|
|
121
126
|
await refreshConversationState();
|
|
122
127
|
}
|
|
123
128
|
catch (error) {
|
|
129
|
+
setMessages((current) => removeOptimisticMessage(current, optimisticMessage.id));
|
|
130
|
+
setDraftMessageState((current) => current || nextMessage);
|
|
124
131
|
setErrorMessage(toErrorMessage(error));
|
|
125
132
|
}
|
|
126
133
|
finally {
|