conversation scripts and style separation
This commit is contained in:
151
static/js/chat-manager.js
Normal file
151
static/js/chat-manager.js
Normal file
@@ -0,0 +1,151 @@
|
||||
// Global state and socket management
|
||||
if (typeof window.ChatManager === 'undefined') {
|
||||
window.ChatManager = (function() {
|
||||
let instance = null;
|
||||
let socket = null;
|
||||
|
||||
const state = {
|
||||
addedMessageIds: new Set(),
|
||||
messageQueue: new Set(),
|
||||
connectionState: {
|
||||
hasJoined: false,
|
||||
isConnected: false,
|
||||
lastMessageId: null,
|
||||
connectionAttempts: 0,
|
||||
socketId: null
|
||||
}
|
||||
};
|
||||
|
||||
function init(conversationId) {
|
||||
if (instance) {
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Initialize message IDs from existing messages
|
||||
$('.message').each(function() {
|
||||
const messageId = $(this).data('message-id');
|
||||
if (messageId) {
|
||||
state.addedMessageIds.add(messageId);
|
||||
}
|
||||
});
|
||||
|
||||
// Create socket instance
|
||||
socket = io(window.location.origin, {
|
||||
path: '/socket.io/',
|
||||
transports: ['polling', 'websocket'],
|
||||
upgrade: true,
|
||||
reconnection: true,
|
||||
reconnectionAttempts: Infinity,
|
||||
reconnectionDelay: 1000,
|
||||
reconnectionDelayMax: 5000,
|
||||
timeout: 20000,
|
||||
autoConnect: true,
|
||||
forceNew: true,
|
||||
multiplex: false,
|
||||
pingTimeout: 60000,
|
||||
pingInterval: 25000,
|
||||
upgradeTimeout: 10000,
|
||||
rememberUpgrade: true,
|
||||
rejectUnauthorized: false,
|
||||
extraHeaders: {
|
||||
'X-Forwarded-Proto': 'https'
|
||||
}
|
||||
});
|
||||
|
||||
// Set up socket event handlers
|
||||
socket.on('connect', function() {
|
||||
state.connectionState.isConnected = true;
|
||||
state.connectionState.connectionAttempts++;
|
||||
state.connectionState.socketId = socket.id;
|
||||
console.log('Socket connected:', {
|
||||
attempt: state.connectionState.connectionAttempts,
|
||||
socketId: socket.id,
|
||||
existingSocketId: state.connectionState.socketId,
|
||||
transport: socket.io.engine.transport.name
|
||||
});
|
||||
|
||||
// Always rejoin the room on connect
|
||||
console.log('Joining conversation room:', conversationId);
|
||||
socket.emit('join_conversation', {
|
||||
conversation_id: conversationId,
|
||||
timestamp: new Date().toISOString(),
|
||||
socketId: socket.id
|
||||
});
|
||||
state.connectionState.hasJoined = true;
|
||||
});
|
||||
|
||||
socket.on('disconnect', function(reason) {
|
||||
console.log('Disconnected from conversation:', {
|
||||
reason: reason,
|
||||
socketId: socket.id,
|
||||
connectionState: state.connectionState,
|
||||
transport: socket.io.engine?.transport?.name
|
||||
});
|
||||
state.connectionState.isConnected = false;
|
||||
state.connectionState.socketId = null;
|
||||
});
|
||||
|
||||
socket.on('connect_error', function(error) {
|
||||
console.error('Connection error:', error);
|
||||
// Try to reconnect with polling if websocket fails
|
||||
if (socket.io.engine?.transport?.name === 'websocket') {
|
||||
console.log('WebSocket failed, falling back to polling');
|
||||
socket.io.opts.transports = ['polling'];
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('error', function(error) {
|
||||
console.error('Socket error:', error);
|
||||
});
|
||||
|
||||
// Add heartbeat to keep connection alive
|
||||
setInterval(function() {
|
||||
if (socket.connected) {
|
||||
socket.emit('heartbeat', {
|
||||
timestamp: new Date().toISOString(),
|
||||
socketId: socket.id,
|
||||
transport: socket.io.engine.transport.name
|
||||
});
|
||||
}
|
||||
}, 15000);
|
||||
|
||||
// Handle transport upgrade
|
||||
socket.io.engine.on('upgrade', function() {
|
||||
console.log('Transport upgraded to:', socket.io.engine.transport.name);
|
||||
});
|
||||
|
||||
socket.io.engine.on('upgradeError', function(err) {
|
||||
console.error('Transport upgrade error:', err);
|
||||
// Fall back to polling
|
||||
socket.io.opts.transports = ['polling'];
|
||||
});
|
||||
|
||||
instance = {
|
||||
socket: socket,
|
||||
state: state,
|
||||
cleanup: cleanup
|
||||
};
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
console.log('Cleaning up socket connection');
|
||||
if (socket) {
|
||||
socket.off('new_message');
|
||||
socket.disconnect();
|
||||
socket = null;
|
||||
}
|
||||
instance = null;
|
||||
}
|
||||
|
||||
return {
|
||||
getInstance: function(conversationId) {
|
||||
if (!instance) {
|
||||
instance = init(conversationId);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
};
|
||||
})();
|
||||
}
|
||||
Reference in New Issue
Block a user