livechat-widget
Version:
LiveChat Widget for Next.js applications
286 lines (285 loc) • 15 kB
JavaScript
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);
}
}