@diffsome/react 1.2.11 → 1.2.13
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/dist/chat.css +33 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +88 -45
- package/dist/index.mjs +88 -45
- package/package.json +1 -1
package/dist/chat.css
CHANGED
|
@@ -263,6 +263,39 @@
|
|
|
263
263
|
color: #ef4444;
|
|
264
264
|
}
|
|
265
265
|
|
|
266
|
+
/* End Chat Button */
|
|
267
|
+
.diffsome-chat-end-container {
|
|
268
|
+
padding: 8px 16px 12px;
|
|
269
|
+
text-align: center;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.diffsome-chat-end-btn {
|
|
273
|
+
background: none;
|
|
274
|
+
border: 1px solid var(--diffsome-chat-border);
|
|
275
|
+
color: var(--diffsome-chat-text-muted);
|
|
276
|
+
font-size: 12px;
|
|
277
|
+
padding: 6px 16px;
|
|
278
|
+
border-radius: 16px;
|
|
279
|
+
cursor: pointer;
|
|
280
|
+
transition: all 0.2s ease;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.diffsome-chat-end-btn:hover {
|
|
284
|
+
border-color: #ef4444;
|
|
285
|
+
color: #ef4444;
|
|
286
|
+
background: #fef2f2;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/* Chat Ended Message */
|
|
290
|
+
.diffsome-chat-ended {
|
|
291
|
+
padding: 16px;
|
|
292
|
+
text-align: center;
|
|
293
|
+
color: var(--diffsome-chat-text-muted);
|
|
294
|
+
font-size: 14px;
|
|
295
|
+
border-top: 1px solid var(--diffsome-chat-border);
|
|
296
|
+
background: var(--diffsome-chat-bg);
|
|
297
|
+
}
|
|
298
|
+
|
|
266
299
|
/* System Message */
|
|
267
300
|
.diffsome-chat-message-system {
|
|
268
301
|
align-self: center;
|
package/dist/index.d.mts
CHANGED
|
@@ -884,11 +884,13 @@ interface ChatWidgetProps {
|
|
|
884
884
|
onSend: (message: string) => void;
|
|
885
885
|
onTyping?: () => void;
|
|
886
886
|
onClose?: () => void;
|
|
887
|
+
onEndChat?: () => void;
|
|
887
888
|
title?: string;
|
|
888
889
|
subtitle?: string;
|
|
889
890
|
placeholder?: string;
|
|
890
891
|
loading?: boolean;
|
|
891
892
|
typing?: boolean;
|
|
893
|
+
ended?: boolean;
|
|
892
894
|
className?: string;
|
|
893
895
|
}
|
|
894
896
|
declare const ChatWidget: React__default.FC<ChatWidgetProps>;
|
package/dist/index.d.ts
CHANGED
|
@@ -884,11 +884,13 @@ interface ChatWidgetProps {
|
|
|
884
884
|
onSend: (message: string) => void;
|
|
885
885
|
onTyping?: () => void;
|
|
886
886
|
onClose?: () => void;
|
|
887
|
+
onEndChat?: () => void;
|
|
887
888
|
title?: string;
|
|
888
889
|
subtitle?: string;
|
|
889
890
|
placeholder?: string;
|
|
890
891
|
loading?: boolean;
|
|
891
892
|
typing?: boolean;
|
|
893
|
+
ended?: boolean;
|
|
892
894
|
className?: string;
|
|
893
895
|
}
|
|
894
896
|
declare const ChatWidget: React__default.FC<ChatWidgetProps>;
|
package/dist/index.js
CHANGED
|
@@ -2719,11 +2719,13 @@ var ChatWidget = ({
|
|
|
2719
2719
|
onSend,
|
|
2720
2720
|
onTyping,
|
|
2721
2721
|
onClose,
|
|
2722
|
+
onEndChat,
|
|
2722
2723
|
title = "Chat Support",
|
|
2723
2724
|
subtitle = "We typically reply within a few minutes",
|
|
2724
2725
|
placeholder = "Type a message...",
|
|
2725
2726
|
loading = false,
|
|
2726
2727
|
typing = false,
|
|
2728
|
+
ended = false,
|
|
2727
2729
|
className = ""
|
|
2728
2730
|
}) => {
|
|
2729
2731
|
const messagesEndRef = (0, import_react23.useRef)(null);
|
|
@@ -2791,20 +2793,31 @@ var ChatWidget = ({
|
|
|
2791
2793
|
] }),
|
|
2792
2794
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { ref: messagesEndRef })
|
|
2793
2795
|
] }) }),
|
|
2794
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2796
|
+
ended ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "diffsome-chat-ended", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Chat ended. Thank you!" }) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
2797
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2798
|
+
ChatInput,
|
|
2799
|
+
{
|
|
2800
|
+
onSend,
|
|
2801
|
+
onTyping,
|
|
2802
|
+
placeholder,
|
|
2803
|
+
disabled: loading
|
|
2804
|
+
}
|
|
2805
|
+
),
|
|
2806
|
+
onEndChat && messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "diffsome-chat-end-container", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2807
|
+
"button",
|
|
2808
|
+
{
|
|
2809
|
+
className: "diffsome-chat-end-btn",
|
|
2810
|
+
onClick: onEndChat,
|
|
2811
|
+
children: "End Chat"
|
|
2812
|
+
}
|
|
2813
|
+
) })
|
|
2814
|
+
] })
|
|
2803
2815
|
] });
|
|
2804
2816
|
};
|
|
2805
2817
|
|
|
2806
2818
|
// src/components/chat/ChatBubble.tsx
|
|
2807
2819
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
2820
|
+
var STORAGE_KEY = "diffsome_conversation_id";
|
|
2808
2821
|
var ChatBubble = ({
|
|
2809
2822
|
client,
|
|
2810
2823
|
title = "Chat Support",
|
|
@@ -2823,29 +2836,23 @@ var ChatBubble = ({
|
|
|
2823
2836
|
}) => {
|
|
2824
2837
|
const [isOpen, setIsOpen] = (0, import_react24.useState)(false);
|
|
2825
2838
|
const [messages, setMessages] = (0, import_react24.useState)([]);
|
|
2826
|
-
const [conversationId, setConversationId] = (0, import_react24.useState)(
|
|
2827
|
-
if (typeof localStorage !== "undefined") {
|
|
2828
|
-
const saved = localStorage.getItem("diffsome_conversation_id");
|
|
2829
|
-
return saved ? parseInt(saved, 10) : null;
|
|
2830
|
-
}
|
|
2831
|
-
return null;
|
|
2832
|
-
});
|
|
2839
|
+
const [conversationId, setConversationId] = (0, import_react24.useState)(null);
|
|
2833
2840
|
const [connection, setConnection] = (0, import_react24.useState)(null);
|
|
2834
2841
|
const [loading, setLoading] = (0, import_react24.useState)(false);
|
|
2835
2842
|
const [typing, setTyping] = (0, import_react24.useState)(false);
|
|
2836
2843
|
const [unreadCount, setUnreadCount] = (0, import_react24.useState)(0);
|
|
2844
|
+
const [initialized, setInitialized] = (0, import_react24.useState)(false);
|
|
2845
|
+
const [ended, setEnded] = (0, import_react24.useState)(false);
|
|
2837
2846
|
const seenMessageIds = (0, import_react24.useRef)(/* @__PURE__ */ new Set());
|
|
2838
|
-
const
|
|
2839
|
-
const
|
|
2840
|
-
const conn = client.chat.connect(convId);
|
|
2841
|
-
setConnection(conn);
|
|
2847
|
+
const connectionRef = (0, import_react24.useRef)(null);
|
|
2848
|
+
const setupListeners = (0, import_react24.useCallback)((conn) => {
|
|
2842
2849
|
conn.onMessage((msg) => {
|
|
2843
2850
|
if (seenMessageIds.current.has(msg.id)) {
|
|
2844
2851
|
return;
|
|
2845
2852
|
}
|
|
2846
2853
|
seenMessageIds.current.add(msg.id);
|
|
2847
2854
|
setMessages((prev) => [...prev, msg]);
|
|
2848
|
-
if (
|
|
2855
|
+
if (msg.sender_type !== "visitor") {
|
|
2849
2856
|
setUnreadCount((c) => c + 1);
|
|
2850
2857
|
}
|
|
2851
2858
|
});
|
|
@@ -2855,26 +2862,33 @@ var ChatBubble = ({
|
|
|
2855
2862
|
setTimeout(() => setTyping(false), 3e3);
|
|
2856
2863
|
}
|
|
2857
2864
|
});
|
|
2858
|
-
|
|
2859
|
-
}, [client.chat, isOpen]);
|
|
2865
|
+
}, []);
|
|
2860
2866
|
const initChat = (0, import_react24.useCallback)(async () => {
|
|
2861
|
-
if (
|
|
2867
|
+
if (initialized || connectionRef.current) return;
|
|
2862
2868
|
setLoading(true);
|
|
2863
2869
|
try {
|
|
2864
|
-
let
|
|
2865
|
-
if (
|
|
2866
|
-
|
|
2870
|
+
let savedConvId = null;
|
|
2871
|
+
if (typeof localStorage !== "undefined") {
|
|
2872
|
+
const saved = localStorage.getItem(STORAGE_KEY);
|
|
2873
|
+
if (saved) {
|
|
2874
|
+
savedConvId = parseInt(saved, 10);
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
if (savedConvId) {
|
|
2867
2878
|
try {
|
|
2868
|
-
const conn2 =
|
|
2879
|
+
const conn2 = client.chat.connect(savedConvId);
|
|
2880
|
+
connectionRef.current = conn2;
|
|
2881
|
+
setConnection(conn2);
|
|
2882
|
+
setupListeners(conn2);
|
|
2869
2883
|
const existingMessages2 = await conn2.getMessages();
|
|
2870
2884
|
existingMessages2.forEach((m) => seenMessageIds.current.add(m.id));
|
|
2871
2885
|
setMessages(existingMessages2);
|
|
2886
|
+
setConversationId(savedConvId);
|
|
2887
|
+
setInitialized(true);
|
|
2872
2888
|
return;
|
|
2873
2889
|
} catch (error) {
|
|
2874
2890
|
console.log("Could not restore conversation, starting new one");
|
|
2875
|
-
|
|
2876
|
-
setConversationId(null);
|
|
2877
|
-
localStorage.removeItem("diffsome_conversation_id");
|
|
2891
|
+
localStorage.removeItem(STORAGE_KEY);
|
|
2878
2892
|
}
|
|
2879
2893
|
}
|
|
2880
2894
|
const result = await client.chat.start({
|
|
@@ -2882,35 +2896,38 @@ var ChatBubble = ({
|
|
|
2882
2896
|
visitor_email: visitorEmail,
|
|
2883
2897
|
initial_message: greeting
|
|
2884
2898
|
});
|
|
2885
|
-
|
|
2886
|
-
setConversationId(
|
|
2899
|
+
const newConvId = result.conversation_id;
|
|
2900
|
+
setConversationId(newConvId);
|
|
2887
2901
|
if (typeof localStorage !== "undefined") {
|
|
2888
|
-
localStorage.setItem(
|
|
2902
|
+
localStorage.setItem(STORAGE_KEY, newConvId.toString());
|
|
2889
2903
|
}
|
|
2890
|
-
const conn =
|
|
2904
|
+
const conn = client.chat.connect(newConvId);
|
|
2905
|
+
connectionRef.current = conn;
|
|
2906
|
+
setConnection(conn);
|
|
2907
|
+
setupListeners(conn);
|
|
2891
2908
|
const existingMessages = await conn.getMessages();
|
|
2892
2909
|
existingMessages.forEach((m) => seenMessageIds.current.add(m.id));
|
|
2893
2910
|
setMessages(existingMessages);
|
|
2911
|
+
setInitialized(true);
|
|
2894
2912
|
} catch (error) {
|
|
2895
2913
|
console.error("Failed to initialize chat:", error);
|
|
2896
2914
|
} finally {
|
|
2897
2915
|
setLoading(false);
|
|
2898
2916
|
}
|
|
2899
|
-
}, [client.chat,
|
|
2917
|
+
}, [client.chat, initialized, setupListeners, visitorName, visitorEmail, greeting]);
|
|
2900
2918
|
const handleOpen = () => {
|
|
2901
2919
|
setIsOpen(true);
|
|
2902
2920
|
setUnreadCount(0);
|
|
2903
2921
|
onOpen?.();
|
|
2904
|
-
|
|
2905
|
-
initChat();
|
|
2906
|
-
}
|
|
2922
|
+
initChat();
|
|
2907
2923
|
};
|
|
2908
2924
|
const handleClose = () => {
|
|
2909
2925
|
setIsOpen(false);
|
|
2910
2926
|
onClose?.();
|
|
2911
2927
|
};
|
|
2912
2928
|
const handleSend = async (content) => {
|
|
2913
|
-
|
|
2929
|
+
const conn = connectionRef.current;
|
|
2930
|
+
if (!conn) return;
|
|
2914
2931
|
const tempId = -Date.now();
|
|
2915
2932
|
const pendingMessage = {
|
|
2916
2933
|
id: tempId,
|
|
@@ -2921,7 +2938,7 @@ var ChatBubble = ({
|
|
|
2921
2938
|
};
|
|
2922
2939
|
setMessages((prev) => [...prev, pendingMessage]);
|
|
2923
2940
|
try {
|
|
2924
|
-
const sentMessage = await
|
|
2941
|
+
const sentMessage = await conn.send(content);
|
|
2925
2942
|
if (sentMessage) {
|
|
2926
2943
|
seenMessageIds.current.add(sentMessage.id);
|
|
2927
2944
|
setMessages(
|
|
@@ -2936,13 +2953,37 @@ var ChatBubble = ({
|
|
|
2936
2953
|
}
|
|
2937
2954
|
};
|
|
2938
2955
|
const handleTyping = () => {
|
|
2939
|
-
|
|
2956
|
+
connectionRef.current?.sendTyping();
|
|
2957
|
+
};
|
|
2958
|
+
const handleEndChat = async () => {
|
|
2959
|
+
const conn = connectionRef.current;
|
|
2960
|
+
if (!conn) return;
|
|
2961
|
+
try {
|
|
2962
|
+
await conn.close();
|
|
2963
|
+
} catch (error) {
|
|
2964
|
+
console.error("Failed to close chat:", error);
|
|
2965
|
+
}
|
|
2966
|
+
if (typeof localStorage !== "undefined") {
|
|
2967
|
+
localStorage.removeItem(STORAGE_KEY);
|
|
2968
|
+
}
|
|
2969
|
+
setEnded(true);
|
|
2970
|
+
connectionRef.current?.disconnect();
|
|
2971
|
+
connectionRef.current = null;
|
|
2972
|
+
setConnection(null);
|
|
2973
|
+
setInitialized(false);
|
|
2974
|
+
setConversationId(null);
|
|
2975
|
+
};
|
|
2976
|
+
const handleStartNewChat = () => {
|
|
2977
|
+
setEnded(false);
|
|
2978
|
+
setMessages([]);
|
|
2979
|
+
seenMessageIds.current.clear();
|
|
2980
|
+
initChat();
|
|
2940
2981
|
};
|
|
2941
2982
|
(0, import_react24.useEffect)(() => {
|
|
2942
2983
|
return () => {
|
|
2943
|
-
|
|
2984
|
+
connectionRef.current?.disconnect();
|
|
2944
2985
|
};
|
|
2945
|
-
}, [
|
|
2986
|
+
}, []);
|
|
2946
2987
|
const positionClass = position === "bottom-left" ? "diffsome-chat-bubble-left" : "diffsome-chat-bubble-right";
|
|
2947
2988
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2948
2989
|
"div",
|
|
@@ -2957,11 +2998,13 @@ var ChatBubble = ({
|
|
|
2957
2998
|
onSend: handleSend,
|
|
2958
2999
|
onTyping: handleTyping,
|
|
2959
3000
|
onClose: handleClose,
|
|
3001
|
+
onEndChat: handleEndChat,
|
|
2960
3002
|
title,
|
|
2961
3003
|
subtitle,
|
|
2962
3004
|
placeholder,
|
|
2963
3005
|
loading,
|
|
2964
|
-
typing
|
|
3006
|
+
typing,
|
|
3007
|
+
ended
|
|
2965
3008
|
}
|
|
2966
3009
|
),
|
|
2967
3010
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
package/dist/index.mjs
CHANGED
|
@@ -2627,11 +2627,13 @@ var ChatWidget = ({
|
|
|
2627
2627
|
onSend,
|
|
2628
2628
|
onTyping,
|
|
2629
2629
|
onClose,
|
|
2630
|
+
onEndChat,
|
|
2630
2631
|
title = "Chat Support",
|
|
2631
2632
|
subtitle = "We typically reply within a few minutes",
|
|
2632
2633
|
placeholder = "Type a message...",
|
|
2633
2634
|
loading = false,
|
|
2634
2635
|
typing = false,
|
|
2636
|
+
ended = false,
|
|
2635
2637
|
className = ""
|
|
2636
2638
|
}) => {
|
|
2637
2639
|
const messagesEndRef = useRef2(null);
|
|
@@ -2699,20 +2701,31 @@ var ChatWidget = ({
|
|
|
2699
2701
|
] }),
|
|
2700
2702
|
/* @__PURE__ */ jsx5("div", { ref: messagesEndRef })
|
|
2701
2703
|
] }) }),
|
|
2702
|
-
/* @__PURE__ */ jsx5(
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2704
|
+
ended ? /* @__PURE__ */ jsx5("div", { className: "diffsome-chat-ended", children: /* @__PURE__ */ jsx5("span", { children: "Chat ended. Thank you!" }) }) : /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
2705
|
+
/* @__PURE__ */ jsx5(
|
|
2706
|
+
ChatInput,
|
|
2707
|
+
{
|
|
2708
|
+
onSend,
|
|
2709
|
+
onTyping,
|
|
2710
|
+
placeholder,
|
|
2711
|
+
disabled: loading
|
|
2712
|
+
}
|
|
2713
|
+
),
|
|
2714
|
+
onEndChat && messages.length > 0 && /* @__PURE__ */ jsx5("div", { className: "diffsome-chat-end-container", children: /* @__PURE__ */ jsx5(
|
|
2715
|
+
"button",
|
|
2716
|
+
{
|
|
2717
|
+
className: "diffsome-chat-end-btn",
|
|
2718
|
+
onClick: onEndChat,
|
|
2719
|
+
children: "End Chat"
|
|
2720
|
+
}
|
|
2721
|
+
) })
|
|
2722
|
+
] })
|
|
2711
2723
|
] });
|
|
2712
2724
|
};
|
|
2713
2725
|
|
|
2714
2726
|
// src/components/chat/ChatBubble.tsx
|
|
2715
2727
|
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2728
|
+
var STORAGE_KEY = "diffsome_conversation_id";
|
|
2716
2729
|
var ChatBubble = ({
|
|
2717
2730
|
client,
|
|
2718
2731
|
title = "Chat Support",
|
|
@@ -2731,29 +2744,23 @@ var ChatBubble = ({
|
|
|
2731
2744
|
}) => {
|
|
2732
2745
|
const [isOpen, setIsOpen] = useState22(false);
|
|
2733
2746
|
const [messages, setMessages] = useState22([]);
|
|
2734
|
-
const [conversationId, setConversationId] = useState22(
|
|
2735
|
-
if (typeof localStorage !== "undefined") {
|
|
2736
|
-
const saved = localStorage.getItem("diffsome_conversation_id");
|
|
2737
|
-
return saved ? parseInt(saved, 10) : null;
|
|
2738
|
-
}
|
|
2739
|
-
return null;
|
|
2740
|
-
});
|
|
2747
|
+
const [conversationId, setConversationId] = useState22(null);
|
|
2741
2748
|
const [connection, setConnection] = useState22(null);
|
|
2742
2749
|
const [loading, setLoading] = useState22(false);
|
|
2743
2750
|
const [typing, setTyping] = useState22(false);
|
|
2744
2751
|
const [unreadCount, setUnreadCount] = useState22(0);
|
|
2752
|
+
const [initialized, setInitialized] = useState22(false);
|
|
2753
|
+
const [ended, setEnded] = useState22(false);
|
|
2745
2754
|
const seenMessageIds = useRef3(/* @__PURE__ */ new Set());
|
|
2746
|
-
const
|
|
2747
|
-
const
|
|
2748
|
-
const conn = client.chat.connect(convId);
|
|
2749
|
-
setConnection(conn);
|
|
2755
|
+
const connectionRef = useRef3(null);
|
|
2756
|
+
const setupListeners = useCallback22((conn) => {
|
|
2750
2757
|
conn.onMessage((msg) => {
|
|
2751
2758
|
if (seenMessageIds.current.has(msg.id)) {
|
|
2752
2759
|
return;
|
|
2753
2760
|
}
|
|
2754
2761
|
seenMessageIds.current.add(msg.id);
|
|
2755
2762
|
setMessages((prev) => [...prev, msg]);
|
|
2756
|
-
if (
|
|
2763
|
+
if (msg.sender_type !== "visitor") {
|
|
2757
2764
|
setUnreadCount((c) => c + 1);
|
|
2758
2765
|
}
|
|
2759
2766
|
});
|
|
@@ -2763,26 +2770,33 @@ var ChatBubble = ({
|
|
|
2763
2770
|
setTimeout(() => setTyping(false), 3e3);
|
|
2764
2771
|
}
|
|
2765
2772
|
});
|
|
2766
|
-
|
|
2767
|
-
}, [client.chat, isOpen]);
|
|
2773
|
+
}, []);
|
|
2768
2774
|
const initChat = useCallback22(async () => {
|
|
2769
|
-
if (
|
|
2775
|
+
if (initialized || connectionRef.current) return;
|
|
2770
2776
|
setLoading(true);
|
|
2771
2777
|
try {
|
|
2772
|
-
let
|
|
2773
|
-
if (
|
|
2774
|
-
|
|
2778
|
+
let savedConvId = null;
|
|
2779
|
+
if (typeof localStorage !== "undefined") {
|
|
2780
|
+
const saved = localStorage.getItem(STORAGE_KEY);
|
|
2781
|
+
if (saved) {
|
|
2782
|
+
savedConvId = parseInt(saved, 10);
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
if (savedConvId) {
|
|
2775
2786
|
try {
|
|
2776
|
-
const conn2 =
|
|
2787
|
+
const conn2 = client.chat.connect(savedConvId);
|
|
2788
|
+
connectionRef.current = conn2;
|
|
2789
|
+
setConnection(conn2);
|
|
2790
|
+
setupListeners(conn2);
|
|
2777
2791
|
const existingMessages2 = await conn2.getMessages();
|
|
2778
2792
|
existingMessages2.forEach((m) => seenMessageIds.current.add(m.id));
|
|
2779
2793
|
setMessages(existingMessages2);
|
|
2794
|
+
setConversationId(savedConvId);
|
|
2795
|
+
setInitialized(true);
|
|
2780
2796
|
return;
|
|
2781
2797
|
} catch (error) {
|
|
2782
2798
|
console.log("Could not restore conversation, starting new one");
|
|
2783
|
-
|
|
2784
|
-
setConversationId(null);
|
|
2785
|
-
localStorage.removeItem("diffsome_conversation_id");
|
|
2799
|
+
localStorage.removeItem(STORAGE_KEY);
|
|
2786
2800
|
}
|
|
2787
2801
|
}
|
|
2788
2802
|
const result = await client.chat.start({
|
|
@@ -2790,35 +2804,38 @@ var ChatBubble = ({
|
|
|
2790
2804
|
visitor_email: visitorEmail,
|
|
2791
2805
|
initial_message: greeting
|
|
2792
2806
|
});
|
|
2793
|
-
|
|
2794
|
-
setConversationId(
|
|
2807
|
+
const newConvId = result.conversation_id;
|
|
2808
|
+
setConversationId(newConvId);
|
|
2795
2809
|
if (typeof localStorage !== "undefined") {
|
|
2796
|
-
localStorage.setItem(
|
|
2810
|
+
localStorage.setItem(STORAGE_KEY, newConvId.toString());
|
|
2797
2811
|
}
|
|
2798
|
-
const conn =
|
|
2812
|
+
const conn = client.chat.connect(newConvId);
|
|
2813
|
+
connectionRef.current = conn;
|
|
2814
|
+
setConnection(conn);
|
|
2815
|
+
setupListeners(conn);
|
|
2799
2816
|
const existingMessages = await conn.getMessages();
|
|
2800
2817
|
existingMessages.forEach((m) => seenMessageIds.current.add(m.id));
|
|
2801
2818
|
setMessages(existingMessages);
|
|
2819
|
+
setInitialized(true);
|
|
2802
2820
|
} catch (error) {
|
|
2803
2821
|
console.error("Failed to initialize chat:", error);
|
|
2804
2822
|
} finally {
|
|
2805
2823
|
setLoading(false);
|
|
2806
2824
|
}
|
|
2807
|
-
}, [client.chat,
|
|
2825
|
+
}, [client.chat, initialized, setupListeners, visitorName, visitorEmail, greeting]);
|
|
2808
2826
|
const handleOpen = () => {
|
|
2809
2827
|
setIsOpen(true);
|
|
2810
2828
|
setUnreadCount(0);
|
|
2811
2829
|
onOpen?.();
|
|
2812
|
-
|
|
2813
|
-
initChat();
|
|
2814
|
-
}
|
|
2830
|
+
initChat();
|
|
2815
2831
|
};
|
|
2816
2832
|
const handleClose = () => {
|
|
2817
2833
|
setIsOpen(false);
|
|
2818
2834
|
onClose?.();
|
|
2819
2835
|
};
|
|
2820
2836
|
const handleSend = async (content) => {
|
|
2821
|
-
|
|
2837
|
+
const conn = connectionRef.current;
|
|
2838
|
+
if (!conn) return;
|
|
2822
2839
|
const tempId = -Date.now();
|
|
2823
2840
|
const pendingMessage = {
|
|
2824
2841
|
id: tempId,
|
|
@@ -2829,7 +2846,7 @@ var ChatBubble = ({
|
|
|
2829
2846
|
};
|
|
2830
2847
|
setMessages((prev) => [...prev, pendingMessage]);
|
|
2831
2848
|
try {
|
|
2832
|
-
const sentMessage = await
|
|
2849
|
+
const sentMessage = await conn.send(content);
|
|
2833
2850
|
if (sentMessage) {
|
|
2834
2851
|
seenMessageIds.current.add(sentMessage.id);
|
|
2835
2852
|
setMessages(
|
|
@@ -2844,13 +2861,37 @@ var ChatBubble = ({
|
|
|
2844
2861
|
}
|
|
2845
2862
|
};
|
|
2846
2863
|
const handleTyping = () => {
|
|
2847
|
-
|
|
2864
|
+
connectionRef.current?.sendTyping();
|
|
2865
|
+
};
|
|
2866
|
+
const handleEndChat = async () => {
|
|
2867
|
+
const conn = connectionRef.current;
|
|
2868
|
+
if (!conn) return;
|
|
2869
|
+
try {
|
|
2870
|
+
await conn.close();
|
|
2871
|
+
} catch (error) {
|
|
2872
|
+
console.error("Failed to close chat:", error);
|
|
2873
|
+
}
|
|
2874
|
+
if (typeof localStorage !== "undefined") {
|
|
2875
|
+
localStorage.removeItem(STORAGE_KEY);
|
|
2876
|
+
}
|
|
2877
|
+
setEnded(true);
|
|
2878
|
+
connectionRef.current?.disconnect();
|
|
2879
|
+
connectionRef.current = null;
|
|
2880
|
+
setConnection(null);
|
|
2881
|
+
setInitialized(false);
|
|
2882
|
+
setConversationId(null);
|
|
2883
|
+
};
|
|
2884
|
+
const handleStartNewChat = () => {
|
|
2885
|
+
setEnded(false);
|
|
2886
|
+
setMessages([]);
|
|
2887
|
+
seenMessageIds.current.clear();
|
|
2888
|
+
initChat();
|
|
2848
2889
|
};
|
|
2849
2890
|
useEffect21(() => {
|
|
2850
2891
|
return () => {
|
|
2851
|
-
|
|
2892
|
+
connectionRef.current?.disconnect();
|
|
2852
2893
|
};
|
|
2853
|
-
}, [
|
|
2894
|
+
}, []);
|
|
2854
2895
|
const positionClass = position === "bottom-left" ? "diffsome-chat-bubble-left" : "diffsome-chat-bubble-right";
|
|
2855
2896
|
return /* @__PURE__ */ jsxs5(
|
|
2856
2897
|
"div",
|
|
@@ -2865,11 +2906,13 @@ var ChatBubble = ({
|
|
|
2865
2906
|
onSend: handleSend,
|
|
2866
2907
|
onTyping: handleTyping,
|
|
2867
2908
|
onClose: handleClose,
|
|
2909
|
+
onEndChat: handleEndChat,
|
|
2868
2910
|
title,
|
|
2869
2911
|
subtitle,
|
|
2870
2912
|
placeholder,
|
|
2871
2913
|
loading,
|
|
2872
|
-
typing
|
|
2914
|
+
typing,
|
|
2915
|
+
ended
|
|
2873
2916
|
}
|
|
2874
2917
|
),
|
|
2875
2918
|
/* @__PURE__ */ jsxs5(
|