UNPKG

livechat-widget

Version:

LiveChat Widget for Next.js applications

286 lines (285 loc) 15 kB
var WebSocketService = /** @class */ (function () { function WebSocketService(url) { this.url = url; this.socket = null; this.messageListeners = []; this.connectionListeners = []; this.reconnectInterval = null; this.reconnectAttempts = 0; this.maxReconnectAttempts = 5; this.reconnectDelay = 3000; // 3 seconds this.receivedMessageIds = new Set(); this.roomCode = null; this.appId = null; this.userCode = null; this.deleteMessageListeners = []; } WebSocketService.prototype.connect = function (roomCode, appId, userCode) { var _this = this; if (userCode === void 0) { userCode = "anonymous"; } if (this.socket) { this.disconnect(); } this.receivedMessageIds.clear(); var fullUrl = "".concat(this.url, "?room_code=").concat(roomCode, "&app_id=").concat(appId, "&user_code=").concat(userCode); this.socket = new WebSocket(fullUrl); this.roomCode = roomCode; this.appId = appId; this.userCode = userCode; return new Promise(function (resolve) { if (_this.socket) { _this.socket.onopen = function () { console.log("WebSocket connection established"); _this.reconnectAttempts = 0; _this.notifyConnectionListeners(true); resolve(true); }; _this.socket.onmessage = function (event) { try { // ตรวจสอบว่าข้อมูลที่ได้รับเป็นข้อความหรือไม่ if (typeof event.data !== "string") { console.error("Received non-string data:", event.data); return; } // ตรวจสอบและทำความสะอาดข้อมูลก่อนแปลง JSON var cleanData = event.data.trim(); // ตรวจสอบว่ามีข้อความหลายรายการที่ถูกส่งมาพร้อมกันหรือไม่ if (cleanData.includes("}{")) { console.warn("Multiple JSON objects detected in one message, processing first object only"); cleanData = cleanData.substring(0, cleanData.indexOf("}{") + 1); } // ตรวจสอบว่าข้อความเริ่มต้นด้วย { และจบด้วย } หรือไม่ if (!cleanData.startsWith("{") || !cleanData.endsWith("}")) { console.error("Invalid JSON format:", cleanData); return; } var data = JSON.parse(cleanData); // ตรวจสอบประเภทของข้อความ if (data.type === "chat" && data.payload) { // ตรวจสอบว่า payload มีรูปแบบ snake_case var payload = data.payload; // ตรวจสอบว่ามี user_info หรือไม่ if (!payload.user_info) { payload.user_info = { username: "Unknown User", profile_image: "/image/profile.png", }; } // ตรวจสอบว่ามี created_at หรือไม่ if (!payload.created_at) { payload.created_at = new Date().toISOString(); } // สร้าง id ถ้าไม่มี if (!payload.id) { payload.id = "".concat(payload.user_code, "_").concat(new Date(payload.created_at).getTime()); } // ตรวจสอบว่าข้อความซ้ำกันหรือไม่ if (!_this.receivedMessageIds.has(payload.id)) { _this.receivedMessageIds.add(payload.id); _this.notifyMessageListeners(payload); } else { console.log("Duplicate message received, ignoring:", payload.id); } } else if (data.type === "message_deleted" && data.payload) { // รับการแจ้งเตือนการลบข้อความ var deletePayload = data.payload; // console.log('Message deleted notification received:', deletePayload); // แจ้งเตือนผู้ฟังเกี่ยวกับการลบข้อความ _this.notifyDeleteMessageListeners(deletePayload.message_id); } } catch (error) { console.error("Error parsing WebSocket message:", error); } }; _this.socket.onclose = function (event) { console.log("WebSocket connection closed:", event.code, event.reason); _this.notifyConnectionListeners(false); _this.socket = null; // เพิ่มตัวแปรเพื่อเก็บค่า userCode และ roomCode ปัจจุบัน var currentUserCode = _this.userCode; var currentRoomCode = _this.roomCode; var currentAppId = _this.appId; // Attempt to reconnect if (_this.reconnectAttempts < _this.maxReconnectAttempts) { _this.reconnectInterval = setTimeout(function () { console.log("WebSocket reconnect attempt", _this.reconnectAttempts + 1); // ตรวจสอบว่า userCode และ roomCode ไม่เปลี่ยนแปลง if (_this.userCode === currentUserCode && _this.roomCode === currentRoomCode && _this.appId === currentAppId) { _this.reconnectAttempts++; _this.connect(_this.roomCode, _this.appId, _this.userCode || "anonymous").then(function (connected) { if (!connected) { resolve(false); } }); } else { resolve(false); } }, _this.reconnectDelay); } else { resolve(false); } }; _this.socket.onerror = function (error) { console.error("WebSocket error:", error); resolve(false); }; } else { resolve(false); } }); }; WebSocketService.prototype.disconnect = function () { var _this = this; if (this.socket) { console.log("Disconnecting WebSocket connection"); this.socket.close(); // ล้าง receivedMessageIds เมื่อตัดการเชื่อมต่อ this.receivedMessageIds.clear(); if (this.reconnectInterval) { clearTimeout(this.reconnectInterval); this.reconnectInterval = null; } this.socket = null; // รอเวลาก่อนรีเซ็ต socket เพื่อให้แน่ใจว่าการเชื่อมต่อถูกปิดสมบูรณ์ setTimeout(function () { console.log("WebSocket connection fully closed"); _this.socket = null; }, 300); } else { console.log("No WebSocket connection to disconnect"); } }; WebSocketService.prototype.getUrl = function () { return this.url; }; WebSocketService.prototype.getCurrentUserCode = function () { return this.userCode; }; WebSocketService.prototype.getCurrentRoomCode = function () { return this.roomCode; }; WebSocketService.prototype.sendMessage = function (message) { var _this = this; if (!this.socket || this.socket.readyState !== WebSocket.OPEN) { console.error("WebSocket is not connected"); // ลองเชื่อมต่อใหม่ถ้าไม่มีการเชื่อมต่อ if (!this.socket) { console.log("Attempting to reconnect before sending message..."); // ใช้ roomCode และ appId ที่เก็บไว้ในตัวแปรระดับคลาส var roomCode = this.roomCode; var appId = this.appId; var userCode = this.userCode; if (roomCode && appId && userCode) { this.connect(roomCode, appId, userCode).then(function (connected) { if (connected) { console.log("Reconnected successfully, sending message..."); _this.sendMessage(message); } else { console.error("Failed to reconnect, message not sent"); } }); } else { console.error("Cannot reconnect: missing roomCode, appId or userCode"); } } return; } // ตรวจสอบว่า message มี user_info หรือไม่ if (!message.user_info) { message.user_info = { username: "Unknown User", profile_image: "/image/profile.png", }; } var wsMessage = { type: "chat", payload: message, }; this.socket.send(JSON.stringify(wsMessage)); }; WebSocketService.prototype.addMessageListener = function (listener) { this.messageListeners.push(listener); }; WebSocketService.prototype.removeMessageListener = function (listener) { this.messageListeners = this.messageListeners.filter(function (l) { return l !== listener; }); }; WebSocketService.prototype.addConnectionListener = function (listener) { this.connectionListeners.push(listener); }; WebSocketService.prototype.removeConnectionListener = function (listener) { this.connectionListeners = this.connectionListeners.filter(function (l) { return l !== listener; }); }; WebSocketService.prototype.addDeleteMessageListener = function (listener) { this.deleteMessageListeners.push(listener); }; WebSocketService.prototype.removeDeleteMessageListener = function (listener) { this.deleteMessageListeners = this.deleteMessageListeners.filter(function (l) { return l !== listener; }); }; WebSocketService.prototype.notifyMessageListeners = function (message) { this.messageListeners.forEach(function (listener) { return listener(message); }); }; WebSocketService.prototype.notifyConnectionListeners = function (connected) { this.connectionListeners.forEach(function (listener) { return listener(connected); }); }; WebSocketService.prototype.notifyDeleteMessageListeners = function (messageId) { this.deleteMessageListeners.forEach(function (listener) { return listener(messageId); }); }; WebSocketService.prototype.isConnected = function () { return this.socket !== null && this.socket.readyState === WebSocket.OPEN; }; return WebSocketService; }()); export { WebSocketService }; // สร้าง instance ใหม่ทุกครั้ง var defaultWsUrl = ""; var wsServiceInstance = null; var isCreatingInstance = false; // เพิ่มตัวแปรเพื่อป้องกันการสร้าง instance ซ้ำซ้อน // เพิ่มฟังก์ชันสำหรับกำหนด WebSocket URL export function setWebSocketUrl(url) { defaultWsUrl = url; } // ฟังก์ชันสำหรับดึง WebSocketService export function getWebSocketService(url) { // ถ้ากำลังสร้าง instance อยู่ และมี instance อยู่แล้ว ให้ใช้ instance เดิม if (isCreatingInstance && wsServiceInstance) { console.log("Already creating WebSocketService instance, returning existing instance"); return wsServiceInstance; } // ตั้งค่าตัวแปรเพื่อป้องกันการสร้าง instance ซ้ำซ้อน isCreatingInstance = true; try { var wsUrl = url || defaultWsUrl || "ws://localhost:8080/ws"; // ตรวจสอบว่ามี instance อยู่แล้วหรือไม่ if (wsServiceInstance) { // ตรวจสอบว่า URL เปลี่ยนไปหรือไม่ if (wsServiceInstance.getUrl() !== wsUrl) { console.log("WebSocket URL changed, creating new instance"); // ปิดการเชื่อมต่อเดิมก่อนสร้าง instance ใหม่ wsServiceInstance.disconnect(); wsServiceInstance = new WebSocketService(wsUrl); } } else { console.log("Creating new WebSocketService instance"); wsServiceInstance = new WebSocketService(wsUrl); } return wsServiceInstance; } finally { // รีเซ็ตตัวแปรเมื่อเสร็จสิ้นการสร้าง instance setTimeout(function () { isCreatingInstance = false; }, 100); } }