@getwidgets/live-chat-widget 1.0.0 → 1.0.1
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/live-chat-widget.umd.js +123 -39
- package/package.json +1 -1
|
@@ -19540,6 +19540,21 @@
|
|
|
19540
19540
|
if (!res.ok) throw new Error("Failed to fetch widget config");
|
|
19541
19541
|
return res.json();
|
|
19542
19542
|
};
|
|
19543
|
+
const checkSessionStatus = async (widgetId, sessionId) => {
|
|
19544
|
+
try {
|
|
19545
|
+
const url = `https://api.getwidgets.app/api/widgets/livechat/${widgetId}/status/?session_id=${sessionId}`;
|
|
19546
|
+
const res = await fetch(url);
|
|
19547
|
+
if (!res.ok) {
|
|
19548
|
+
const txt = await res.text().catch(() => null);
|
|
19549
|
+
throw new Error(txt || "Failed to check session status");
|
|
19550
|
+
}
|
|
19551
|
+
const data = await res.json();
|
|
19552
|
+
return data;
|
|
19553
|
+
} catch (e) {
|
|
19554
|
+
console.warn("checkSessionStatus failed", e);
|
|
19555
|
+
return { error: "Failed to check session status" };
|
|
19556
|
+
}
|
|
19557
|
+
};
|
|
19543
19558
|
const getSessionId = (widgetId) => {
|
|
19544
19559
|
if (typeof window === "undefined") return null;
|
|
19545
19560
|
const key = `live-chat-widget/session-id`;
|
|
@@ -19570,8 +19585,12 @@
|
|
|
19570
19585
|
const [sessionId, setSessionId] = reactExports.useState(null);
|
|
19571
19586
|
const [localMessages, setLocalMessages] = reactExports.useState([]);
|
|
19572
19587
|
const [localLoading, setLocalLoading] = reactExports.useState(false);
|
|
19588
|
+
const [isSessionInitialized, setIsSessionInitialized] = reactExports.useState(false);
|
|
19589
|
+
const [isConnecting, setIsConnecting] = reactExports.useState(false);
|
|
19590
|
+
const [queuedFirstMessage, setQueuedFirstMessage] = reactExports.useState(null);
|
|
19573
19591
|
const wsRef = reactExports.useRef(null);
|
|
19574
19592
|
const audioRef = reactExports.useRef(null);
|
|
19593
|
+
const [hasCheckedSession, setHasCheckedSession] = reactExports.useState(false);
|
|
19575
19594
|
const normalizeIncomingMessage = (m2) => {
|
|
19576
19595
|
if (!m2) return { id: void 0, role: "agent", content: "", timestamp: (/* @__PURE__ */ new Date()).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }), created_at: Date.now() };
|
|
19577
19596
|
if (m2.sent_by) {
|
|
@@ -19611,33 +19630,27 @@
|
|
|
19611
19630
|
fetchWidgetConfig(widgetId).then((data) => setConfig(data)).catch((err) => console.error("Failed to load widget config:", err));
|
|
19612
19631
|
}, [widgetId, apiKey]);
|
|
19613
19632
|
reactExports.useEffect(() => {
|
|
19614
|
-
|
|
19615
|
-
|
|
19616
|
-
|
|
19617
|
-
const existing = getSessionId();
|
|
19633
|
+
const checkAndInitializeSession = async () => {
|
|
19634
|
+
var _a2;
|
|
19635
|
+
if (!widgetId || !sessionId || hasCheckedSession) return;
|
|
19618
19636
|
try {
|
|
19619
|
-
|
|
19620
|
-
|
|
19621
|
-
|
|
19622
|
-
|
|
19623
|
-
|
|
19624
|
-
|
|
19625
|
-
|
|
19626
|
-
|
|
19627
|
-
|
|
19628
|
-
|
|
19629
|
-
|
|
19630
|
-
|
|
19631
|
-
|
|
19632
|
-
init2();
|
|
19633
|
-
return () => {
|
|
19634
|
-
mounted = false;
|
|
19635
|
-
if (wsRef.current) try {
|
|
19636
|
-
wsRef.current.close();
|
|
19637
|
-
} catch (e) {
|
|
19637
|
+
const status = await checkSessionStatus(widgetId, sessionId);
|
|
19638
|
+
if (status.success && ((_a2 = status.data) == null ? void 0 : _a2.is_active)) {
|
|
19639
|
+
console.log("Session is active, connecting to websocket...");
|
|
19640
|
+
setIsConnecting(true);
|
|
19641
|
+
openLiveWebsocket(sessionId);
|
|
19642
|
+
setIsSessionInitialized(true);
|
|
19643
|
+
} else {
|
|
19644
|
+
console.log("Session not active, will create new session on first message");
|
|
19645
|
+
}
|
|
19646
|
+
} catch (error) {
|
|
19647
|
+
console.error("Failed to check session status:", error);
|
|
19648
|
+
} finally {
|
|
19649
|
+
setHasCheckedSession(true);
|
|
19638
19650
|
}
|
|
19639
19651
|
};
|
|
19640
|
-
|
|
19652
|
+
checkAndInitializeSession();
|
|
19653
|
+
}, [widgetId, sessionId, hasCheckedSession]);
|
|
19641
19654
|
reactExports.useEffect(() => {
|
|
19642
19655
|
try {
|
|
19643
19656
|
audioRef.current = new Audio("https://res.cloudinary.com/dtqjv8s9r/video/upload/v1699024420/new-notification-014-363678_iatlfa.mp3");
|
|
@@ -19662,10 +19675,10 @@
|
|
|
19662
19675
|
return data.session_id || data.id || currentSessionId;
|
|
19663
19676
|
} catch (e) {
|
|
19664
19677
|
console.warn("startLiveSession failed", e);
|
|
19665
|
-
|
|
19678
|
+
throw e;
|
|
19666
19679
|
}
|
|
19667
19680
|
};
|
|
19668
|
-
const openLiveWebsocket = (sid) => {
|
|
19681
|
+
const openLiveWebsocket = (sid, onOpenCallback) => {
|
|
19669
19682
|
if (!sid) return;
|
|
19670
19683
|
try {
|
|
19671
19684
|
if (wsRef.current) {
|
|
@@ -19681,6 +19694,10 @@
|
|
|
19681
19694
|
ws.onopen = () => {
|
|
19682
19695
|
console.log("LiveChat WS connected", url);
|
|
19683
19696
|
setLocalLoading(false);
|
|
19697
|
+
setIsConnecting(false);
|
|
19698
|
+
if (onOpenCallback) {
|
|
19699
|
+
onOpenCallback();
|
|
19700
|
+
}
|
|
19684
19701
|
};
|
|
19685
19702
|
ws.onmessage = (evt) => {
|
|
19686
19703
|
try {
|
|
@@ -19737,10 +19754,68 @@
|
|
|
19737
19754
|
} catch (e) {
|
|
19738
19755
|
}
|
|
19739
19756
|
wsRef.current = null;
|
|
19757
|
+
setIsSessionInitialized(false);
|
|
19758
|
+
setIsConnecting(false);
|
|
19759
|
+
};
|
|
19760
|
+
ws.onerror = (e) => {
|
|
19761
|
+
console.error("LiveChat WS error", e);
|
|
19762
|
+
setIsConnecting(false);
|
|
19740
19763
|
};
|
|
19741
|
-
ws.onerror = (e) => console.error("LiveChat WS error", e);
|
|
19742
19764
|
} catch (e) {
|
|
19743
19765
|
console.error("Failed to open LiveChat WS", e);
|
|
19766
|
+
setIsConnecting(false);
|
|
19767
|
+
}
|
|
19768
|
+
};
|
|
19769
|
+
const sendMessageOverWebSocket = (message) => {
|
|
19770
|
+
if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
|
|
19771
|
+
try {
|
|
19772
|
+
wsRef.current.send(JSON.stringify({ message }));
|
|
19773
|
+
return true;
|
|
19774
|
+
} catch (e) {
|
|
19775
|
+
console.error("Failed to send live message", e);
|
|
19776
|
+
return false;
|
|
19777
|
+
}
|
|
19778
|
+
}
|
|
19779
|
+
return false;
|
|
19780
|
+
};
|
|
19781
|
+
const initializeSession = async (firstMessage) => {
|
|
19782
|
+
if (isSessionInitialized) return true;
|
|
19783
|
+
setIsConnecting(true);
|
|
19784
|
+
setLocalLoading(true);
|
|
19785
|
+
try {
|
|
19786
|
+
const newSessionId = v4();
|
|
19787
|
+
const sid = await startLiveSession(widgetId, newSessionId);
|
|
19788
|
+
try {
|
|
19789
|
+
localStorage.setItem("live-chat-widget/session-id", sid);
|
|
19790
|
+
} catch (e) {
|
|
19791
|
+
}
|
|
19792
|
+
setSessionId(sid);
|
|
19793
|
+
setIsSessionInitialized(true);
|
|
19794
|
+
openLiveWebsocket(sid, () => {
|
|
19795
|
+
if (firstMessage) {
|
|
19796
|
+
const sent = sendMessageOverWebSocket(firstMessage);
|
|
19797
|
+
if (!sent) {
|
|
19798
|
+
setLocalMessages((prev) => [...prev, {
|
|
19799
|
+
id: `error-${Date.now()}`,
|
|
19800
|
+
role: "system",
|
|
19801
|
+
content: "Failed to send message. Please try again.",
|
|
19802
|
+
isError: true
|
|
19803
|
+
}]);
|
|
19804
|
+
}
|
|
19805
|
+
}
|
|
19806
|
+
});
|
|
19807
|
+
return true;
|
|
19808
|
+
} catch (error) {
|
|
19809
|
+
console.error("Failed to initialize session:", error);
|
|
19810
|
+
setLocalLoading(false);
|
|
19811
|
+
setIsConnecting(false);
|
|
19812
|
+
setLocalMessages((prev) => [...prev, {
|
|
19813
|
+
id: `error-${Date.now()}`,
|
|
19814
|
+
role: "system",
|
|
19815
|
+
content: "Failed to connect to support. Please try again.",
|
|
19816
|
+
isError: true
|
|
19817
|
+
}]);
|
|
19818
|
+
return false;
|
|
19744
19819
|
}
|
|
19745
19820
|
};
|
|
19746
19821
|
const performSend = async () => {
|
|
@@ -19755,19 +19830,28 @@
|
|
|
19755
19830
|
pending: true
|
|
19756
19831
|
};
|
|
19757
19832
|
setLocalMessages((prev) => [...prev, userMsg]);
|
|
19758
|
-
setLocalLoading(false);
|
|
19759
19833
|
setInputMessage("");
|
|
19760
|
-
if (
|
|
19761
|
-
|
|
19762
|
-
|
|
19763
|
-
|
|
19764
|
-
|
|
19834
|
+
if (!isSessionInitialized) {
|
|
19835
|
+
setLocalMessages((prev) => [...prev, {
|
|
19836
|
+
id: `sys-${Date.now()}`,
|
|
19837
|
+
role: "system",
|
|
19838
|
+
content: "Connecting to support..."
|
|
19839
|
+
}]);
|
|
19840
|
+
const initialized = await initializeSession(msg);
|
|
19841
|
+
if (!initialized) {
|
|
19842
|
+
setLocalMessages((prev) => prev.filter((m2) => m2.role !== "system" || !m2.content.includes("Connecting")));
|
|
19765
19843
|
}
|
|
19766
19844
|
} else {
|
|
19767
|
-
|
|
19768
|
-
|
|
19769
|
-
|
|
19770
|
-
|
|
19845
|
+
const sent = sendMessageOverWebSocket(msg);
|
|
19846
|
+
if (!sent) {
|
|
19847
|
+
setTimeout(() => {
|
|
19848
|
+
setLocalMessages((prev) => [...prev, {
|
|
19849
|
+
id: `sys-${Date.now()}`,
|
|
19850
|
+
role: "system",
|
|
19851
|
+
content: "Reconnecting..."
|
|
19852
|
+
}]);
|
|
19853
|
+
}, 300);
|
|
19854
|
+
}
|
|
19771
19855
|
}
|
|
19772
19856
|
};
|
|
19773
19857
|
const handleKeyPress = (e) => {
|
|
@@ -19871,8 +19955,8 @@
|
|
|
19871
19955
|
zIndex: 0
|
|
19872
19956
|
} }), /* @__PURE__ */ React.createElement("div", { className: "relative z-10 p-3 sm:p-4 space-y-2 sm:space-y-3", style: {
|
|
19873
19957
|
backgroundColor: appearanceConfig.inner_background_color !== void 0 ? appearanceConfig.inner_background_color : "transparent"
|
|
19874
|
-
} }, combinedMessages.length === 0 ? /* @__PURE__ */ React.createElement("div", { className: "flex justify-start" }, /* @__PURE__ */ React.createElement("div", { className: `text-left p-3 inline-block max-w-[80%]`, style: { backgroundColor: chatAreaConfig.ai_response_color || "#E2E8F0", borderRadius: chatAreaConfig.chat_bubble_radius || "18px", color: chatAreaConfig.ai_font_color || "#111827", fontSize: "14px" } }, inputAreaConfig.first_ai_message || "Hello! How can I assist you today?")) : combinedMessages.map((message) => /* @__PURE__ */ React.createElement("div", { key: message.id, className: `flex ${message.role === "user" ? "justify-end" : "justify-start"}` }, /* @__PURE__ */ React.createElement("div", { className: `p-3 inline-block max-w-[80%]`, style: { backgroundColor: message.role === "user" ? chatAreaConfig.user_response_color || "#4ADE80" : message.isError ? "#FEE2E2" : chatAreaConfig.ai_response_color || "#E2E8F0", borderRadius: chatAreaConfig.chat_bubble_radius || "18px", fontSize: "14px", color: message.role === "user" ? chatAreaConfig.user_font_color || "#111827" : message.isError ? "#991B1B" : chatAreaConfig.ai_font_color || "#111827" } }, message.role !== "system" ? /* @__PURE__ */ React.createElement(Markdown, { remarkPlugins: [remarkGfm] }, message.content) : /* @__PURE__ */ React.createElement("em", { className: "text-xs opacity-70" }, message.content), chatAreaConfig.show_timestamps && message.timestamp && /* @__PURE__ */ React.createElement("div", { className: "text-xs opacity-70 mt-1 text-right" }, message.timestamp)))),
|
|
19875
|
-
/* @__PURE__ */ React.createElement("div", { className: "p-3 flex items-center gap-2 border-t flex-shrink-0", style: { backgroundColor: inputAreaConfig.background_color || "#FFF", borderColor: inputAreaConfig.border_color || "#D1D5DB", minHeight: 70 } }, /* @__PURE__ */ React.createElement("input", { ref: inputRef, value: inputMessage, onChange: (e) => setInputMessage(e.target.value), onKeyPress: handleKeyPress, disabled:
|
|
19958
|
+
} }, combinedMessages.length === 0 ? /* @__PURE__ */ React.createElement("div", { className: "flex justify-start" }, /* @__PURE__ */ React.createElement("div", { className: `text-left p-3 inline-block max-w-[80%]`, style: { backgroundColor: chatAreaConfig.ai_response_color || "#E2E8F0", borderRadius: chatAreaConfig.chat_bubble_radius || "18px", color: chatAreaConfig.ai_font_color || "#111827", fontSize: "14px" } }, inputAreaConfig.first_ai_message || "Hello! How can I assist you today?")) : combinedMessages.map((message) => /* @__PURE__ */ React.createElement("div", { key: message.id, className: `flex ${message.role === "user" ? "justify-end" : "justify-start"}` }, /* @__PURE__ */ React.createElement("div", { className: `p-3 inline-block max-w-[80%]`, style: { backgroundColor: message.role === "user" ? chatAreaConfig.user_response_color || "#4ADE80" : message.isError ? "#FEE2E2" : chatAreaConfig.ai_response_color || "#E2E8F0", borderRadius: chatAreaConfig.chat_bubble_radius || "18px", fontSize: "14px", color: message.role === "user" ? chatAreaConfig.user_font_color || "#111827" : message.isError ? "#991B1B" : chatAreaConfig.ai_font_color || "#111827" } }, message.role !== "system" ? /* @__PURE__ */ React.createElement(Markdown, { remarkPlugins: [remarkGfm] }, message.content) : /* @__PURE__ */ React.createElement("em", { className: "text-xs opacity-70" }, message.content), chatAreaConfig.show_timestamps && message.timestamp && /* @__PURE__ */ React.createElement("div", { className: "text-xs opacity-70 mt-1 text-right" }, message.timestamp)))), localLoading && /* @__PURE__ */ React.createElement("div", { className: "flex justify-start" }, /* @__PURE__ */ React.createElement("div", { className: "text-left p-3 inline-block max-w-[85%]", style: { backgroundColor: chatAreaConfig.ai_response_color || "#E2E8F0", borderRadius: chatAreaConfig.chat_bubble_radius || "18px", fontSize: "14px", color: chatAreaConfig.ai_font_color || "#111827" } }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React.createElement("div", { className: "flex space-x-1" }, /* @__PURE__ */ React.createElement("div", { className: "w-2 h-2 bg-gray-600 rounded-full animate-bounce" }), /* @__PURE__ */ React.createElement("div", { className: "w-2 h-2 bg-gray-600 rounded-full animate-bounce", style: { animationDelay: "0.1s" } }), /* @__PURE__ */ React.createElement("div", { className: "w-2 h-2 bg-gray-600 rounded-full animate-bounce", style: { animationDelay: "0.2s" } })), /* @__PURE__ */ React.createElement("span", { className: "text-sm" }, isConnecting ? "Connecting..." : "Thinking...")))))),
|
|
19959
|
+
/* @__PURE__ */ React.createElement("div", { className: "p-3 flex items-center gap-2 border-t flex-shrink-0", style: { backgroundColor: inputAreaConfig.background_color || "#FFF", borderColor: inputAreaConfig.border_color || "#D1D5DB", minHeight: 70 } }, /* @__PURE__ */ React.createElement("input", { ref: inputRef, value: inputMessage, onChange: (e) => setInputMessage(e.target.value), onKeyPress: handleKeyPress, disabled: localLoading, className: "flex-1 px-3 py-2 border rounded-lg", style: { borderColor: inputAreaConfig.border_color || "#D1D5DB", color: inputAreaConfig.text_color || "#111827", fontSize: "14px", backgroundColor: inputAreaConfig.background_color || "#FFF", minHeight: "44px" }, placeholder: inputAreaConfig.placeholder_text || "Type your message..." }), /* @__PURE__ */ React.createElement("button", { onClick: performSend, disabled: localLoading || !inputMessage.trim(), className: "rounded-full flex items-center justify-center", style: { backgroundColor: ((_b = inputAreaConfig.send_button) == null ? void 0 : _b.color) || "#2563EB", width: 44, height: 44 } }, localLoading ? /* @__PURE__ */ React.createElement("div", { className: "rounded-full animate-spin", style: { width: 16, height: 16, border: "2px solid #FFFFFF", borderTop: "2px solid transparent" } }) : /* @__PURE__ */ React.createElement("svg", { viewBox: "0 0 24 24", fill: "currentColor", style: { width: 18, height: 18, color: "#fff" } }, /* @__PURE__ */ React.createElement("path", { d: "M2 21l21-9L2 3v7l15 2-15 2v7z" })))),
|
|
19876
19960
|
inputAreaConfig.show_branding !== false && /* @__PURE__ */ React.createElement("div", { className: "px-3 pb-3 text-center text-xs opacity-80", style: { backgroundColor: inputAreaConfig.background_color } }, /* @__PURE__ */ React.createElement("a", { href: "https://www.getwidgets.app", target: "_blank", rel: "noopener noreferrer", style: { color: getContrastColor(inputAreaConfig.background_color || "#d52929ff") } }, "Powered by WidgetKraft"))
|
|
19877
19961
|
));
|
|
19878
19962
|
};
|