Amba-Agent-App/components/other/ChatwootFloatingButton.tsx
2026-01-16 00:22:35 +03:00

184 lines
5.5 KiB
TypeScript

import React, { useEffect, useMemo, useState, useRef } from "react";
import { View, TouchableOpacity } from "react-native";
import { WebView } from "react-native-webview";
import { MessageCircle } from "lucide-react-native";
import { useAuthStore } from "~/lib/stores";
const CHATWOOT_BASE_URL = "https://chat.app.ambapays.com";
const CHATWOOT_WEBSITE_TOKEN = "or1QS1gRowqkuBBcQVEb3Wib";
export default function ChatwootFloatingButton() {
const [visible, setVisible] = useState(false);
const webViewRef = useRef<WebView | null>(null);
const user = useAuthStore((state) => state.user);
const profile = useAuthStore((state) => state.profile);
const identifier = user?.uid || user?.email || "";
const name = profile?.fullName || user?.displayName || "";
const email = user?.email || "";
const phone = profile?.phoneNumber || user?.phoneNumber || "";
const html = useMemo(
() => `<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
html, body { margin: 0; padding: 0; height: 100%; }
</style>
</head>
<body>
<script>
window.chatwootSettings = {
hideMessageBubble: true,
position: "right",
type: "standard",
launcherTitle: "Chat with us",
};
(function(d,t) {
var BASE_URL = '${CHATWOOT_BASE_URL}';
var g = d.createElement(t), s = d.getElementsByTagName(t)[0];
g.src = BASE_URL + '/packs/js/sdk.js';
g.async = true;
s.parentNode.insertBefore(g, s);
g.onload = function() {
if (window.chatwootSDK && typeof window.chatwootSDK.run === 'function') {
window.chatwootSDK.run({
websiteToken: '${CHATWOOT_WEBSITE_TOKEN}',
baseUrl: BASE_URL,
});
if (window.$chatwoot) {
try {
if ('${identifier}') {
window.$chatwoot.setUser('${identifier}', {
email: '${email}',
name: '${name}',
phone_number: '${phone}',
});
}
window.__ambaChatOpen = false;
window.addEventListener('chatwoot:opened', function () {
window.__ambaChatOpen = true;
});
window.addEventListener('chatwoot:closed', function () {
window.__ambaChatOpen = false;
if (
window.ReactNativeWebView &&
window.ReactNativeWebView.postMessage
) {
window.ReactNativeWebView.postMessage('chatwoot:closed');
}
});
var originalToggle = window.$chatwoot.toggle;
window.$chatwoot.toggle = function(state) {
var result = originalToggle.apply(window.$chatwoot, arguments);
// Normalize state: if undefined, treat as a user-driven toggle
var normalized = state;
if (typeof normalized === 'undefined') {
normalized = window.__ambaChatOpen ? 'close' : 'open';
}
if (normalized === 'open') {
window.__ambaChatOpen = true;
}
if (
normalized === 'close' &&
window.__ambaChatOpen &&
window.ReactNativeWebView &&
window.ReactNativeWebView.postMessage
) {
window.__ambaChatOpen = false;
window.ReactNativeWebView.postMessage('chatwoot:closed');
}
return result;
};
// Open widget initially
window.$chatwoot.toggle('open');
} catch (e) {
console.log('Chatwoot integration error', e);
}
}
}
};
})(document, 'script');
</script>
</body>
</html>`,
[identifier, name, email, phone]
);
useEffect(() => {
if (visible && webViewRef.current) {
webViewRef.current.injectJavaScript(
"if (window.$chatwoot) { window.$chatwoot.toggle('open'); } true;"
);
}
}, [visible]);
return (
<>
<TouchableOpacity
activeOpacity={0.9}
onPress={() => setVisible(true)}
style={{
position: "absolute",
right: 20,
bottom: 70,
width: 56,
height: 56,
borderRadius: 28,
backgroundColor: "#105D38",
justifyContent: "center",
alignItems: "center",
shadowColor: "#000",
shadowOpacity: 0.2,
shadowRadius: 6,
shadowOffset: { width: 0, height: 3 },
elevation: 6,
zIndex: 9999,
}}
>
<MessageCircle color="#FFFFFF" size={26} />
</TouchableOpacity>
<View
pointerEvents={visible ? "auto" : "none"}
style={{
position: "absolute",
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: "transparent",
opacity: visible ? 1 : 0,
}}
>
<WebView
ref={webViewRef}
originWhitelist={["*"]}
source={{ html, baseUrl: CHATWOOT_BASE_URL }}
javaScriptEnabled
domStorageEnabled
startInLoadingState
onMessage={(event) => {
if (event.nativeEvent.data === "chatwoot:closed") {
setVisible(false);
}
}}
/>
</View>
</>
);
}