UNPKG

e2ee-chat

Version:

A simple realtime chat SDK for web and mobile apps using socket.io with support for end-to-end encryption and multi-tenant backend integration.

234 lines (216 loc) 6.82 kB
// Example React component showing proper useChat integration // This addresses the encryption issue between Flutter and React import React, { useState, useEffect } from "react"; import { useChat } from "e2ee-chat"; const ChatComponent = () => { const [messageInput, setMessageInput] = useState(""); const [debugInfo, setDebugInfo] = useState([]); // Chat configuration - ensure these match your Flutter app const chatConfig = { serverUrl: "https://datahex-chat-server.azurewebsites.net", roomId: "your-room-id", // Replace with actual room ID userId: "649c0fee27d113dddba5491c", // Replace with actual user ID userType: "admin", secretKey: "shared-secret-123", // Must match Flutter apiKey: "abc123-secret", receiverId: "other-user-id", // Replace with actual receiver ID }; // Enhanced message handler for debugging const handleMessage = (message) => { console.log("📥 New message received:", message); // Add debug info setDebugInfo((prev) => [ ...prev, { type: "received", timestamp: new Date().toLocaleTimeString(), senderId: message.senderId, encrypted: message.encryptedText, decrypted: message.decryptedText, hasError: !!message.decryptionError, }, ]); }; // Use the updated chat hook const { messages, sendMessage, joined, unreadCount, markMessagesAsRead, fetchUnreadCounts, } = useChat({ ...chatConfig, onMessage: handleMessage, }); // Handle sending messages const handleSendMessage = (e) => { e.preventDefault(); if (!messageInput.trim() || !joined) return; console.log("📤 Sending message:", messageInput); // Add debug info for sent message setDebugInfo((prev) => [ ...prev, { type: "sent", timestamp: new Date().toLocaleTimeString(), senderId: chatConfig.userId, message: messageInput, }, ]); sendMessage(messageInput, chatConfig.receiverId); setMessageInput(""); }; // Debug effect to log encryption issues useEffect(() => { const errorMessages = messages.filter((msg) => msg.decryptionError); if (errorMessages.length > 0) { console.error("🚨 Found messages with decryption errors:", errorMessages); } }, [messages]); return ( <div className="chat-container" style={{ maxWidth: "600px", margin: "0 auto", padding: "20px" }} > <div className="chat-header"> <h2>Chat Component</h2> <div className="status-info"> <span>Status: {joined ? "🟢 Connected" : "🔴 Disconnected"}</span> {unreadCount > 0 && <span> | Unread: {unreadCount}</span>} </div> </div> {/* Debug Panel */} <div className="debug-panel" style={{ background: "#f5f5f5", padding: "10px", marginBottom: "20px", borderRadius: "5px", fontSize: "12px", }} > <h4>Debug Info:</h4> <p>Room ID: {chatConfig.roomId}</p> <p>User ID: {chatConfig.userId}</p> <p>Secret Key: {chatConfig.secretKey}</p> <p>Messages: {messages.length}</p> <p> Decryption Errors: {messages.filter((m) => m.decryptionError).length} </p> </div> {/* Messages Display */} <div className="messages" style={{ height: "400px", overflowY: "auto", border: "1px solid #ddd", padding: "10px", marginBottom: "20px", }} > {messages.length === 0 ? ( <div style={{ textAlign: "center", color: "#888" }}> No messages yet.{" "} {joined ? "Start the conversation!" : "Connecting..."} </div> ) : ( messages.map((msg, idx) => { const isFromMe = msg.senderId === chatConfig.userId; return ( <div key={idx} style={{ marginBottom: "10px", textAlign: isFromMe ? "right" : "left", }} > <div style={{ display: "inline-block", maxWidth: "70%", padding: "8px 12px", borderRadius: "18px", backgroundColor: isFromMe ? "#007bff" : "#e9ecef", color: isFromMe ? "white" : "black", border: msg.decryptionError ? "2px solid red" : "none", }} > <div>{msg.decryptedText}</div> <div style={{ fontSize: "10px", opacity: 0.7, marginTop: "4px" }} > {new Date(msg.timestamp).toLocaleTimeString()} {msg.decryptionError && " ⚠️ Decryption Error"} </div> </div> </div> ); }) )} </div> {/* Message Input */} <form onSubmit={handleSendMessage} style={{ display: "flex", gap: "10px" }} > <input type="text" value={messageInput} onChange={(e) => setMessageInput(e.target.value)} placeholder="Type your message..." disabled={!joined} style={{ flex: 1, padding: "10px", border: "1px solid #ddd", borderRadius: "5px", }} /> <button type="submit" disabled={!joined || !messageInput.trim()} style={{ padding: "10px 20px", backgroundColor: "#007bff", color: "white", border: "none", borderRadius: "5px", cursor: joined ? "pointer" : "not-allowed", }} > Send </button> </form> {/* Recent Debug Info */} <div className="recent-debug" style={{ marginTop: "20px", maxHeight: "200px", overflowY: "auto", fontSize: "11px", backgroundColor: "#f8f9fa", padding: "10px", borderRadius: "5px", }} > <h4>Recent Activity:</h4> {debugInfo.slice(-10).map((info, idx) => ( <div key={idx} style={{ marginBottom: "5px" }}> <strong>{info.timestamp}</strong> -{" "} {info.type === "sent" ? "📤" : "📥"} {info.type === "sent" ? ` Sent: "${info.message}"` : ` From ${info.senderId}: "${info.decrypted}" ${ info.hasError ? "⚠️" : "✅" }`} </div> ))} </div> </div> ); }; export default ChatComponent;