eretrrefvdsfd / client /src /services /socketService.ts
cnmksjs's picture
Upload 60 files
590318c verified
import { io, Socket } from 'socket.io-client'
import { Message, User, Chat } from '../../../shared/types'
class SocketService {
private socket: Socket | null = null
private reconnectAttempts = 0
private maxReconnectAttempts = 5
private reconnectDelay = 1000
connect(token: string): Promise<void> {
return new Promise((resolve, reject) => {
if (this.socket?.connected) {
resolve()
return
}
const socketUrl = import.meta.env.VITE_SOCKET_URL || 'http://localhost:3001'
this.socket = io(socketUrl, {
auth: {
token
},
transports: ['websocket', 'polling'],
timeout: 10000,
})
this.socket.on('connect', () => {
console.log('Socket connected')
this.reconnectAttempts = 0
resolve()
})
this.socket.on('connect_error', (error) => {
console.error('Socket connection error:', error)
reject(error)
})
this.socket.on('disconnect', (reason) => {
console.log('Socket disconnected:', reason)
if (reason === 'io server disconnect') {
// Server disconnected, try to reconnect
this.handleReconnect()
}
})
this.socket.on('error', (error) => {
console.error('Socket error:', error)
})
// Set up event listeners
this.setupEventListeners()
})
}
disconnect(): void {
if (this.socket) {
this.socket.disconnect()
this.socket = null
}
}
private handleReconnect(): void {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++
const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1)
setTimeout(() => {
console.log(`Attempting to reconnect (${this.reconnectAttempts}/${this.maxReconnectAttempts})`)
this.socket?.connect()
}, delay)
} else {
console.error('Max reconnection attempts reached')
}
}
private setupEventListeners(): void {
if (!this.socket) return
// Authentication events
this.socket.on('authenticated', (user: User) => {
console.log('Socket authenticated for user:', user.username)
})
this.socket.on('authentication_error', (error: string) => {
console.error('Socket authentication error:', error)
})
}
// Message events
onMessageReceive(callback: (message: Message) => void): void {
this.socket?.on('message:receive', callback)
}
onMessageEdit(callback: (message: Message) => void): void {
this.socket?.on('message:edit', callback)
}
onMessageDelete(callback: (messageId: string) => void): void {
this.socket?.on('message:delete', callback)
}
onMessageReaction(callback: (data: { messageId: string; reactions: any[] }) => void): void {
this.socket?.on('message:reaction', callback)
}
// Typing events
onTypingStart(callback: (data: { chatId: string; userId: string; user: User }) => void): void {
this.socket?.on('typing:start', callback)
}
onTypingStop(callback: (data: { chatId: string; userId: string }) => void): void {
this.socket?.on('typing:stop', callback)
}
sendTypingStart(chatId: string): void {
this.socket?.emit('typing:start', { chatId })
}
sendTypingStop(chatId: string): void {
this.socket?.emit('typing:stop', { chatId })
}
// User status events
onUserOnline(callback: (userId: string) => void): void {
this.socket?.on('user:online', callback)
}
onUserOffline(callback: (userId: string) => void): void {
this.socket?.on('user:offline', callback)
}
onUserStatusUpdate(callback: (data: { userId: string; isOnline: boolean; lastSeen?: Date }) => void): void {
this.socket?.on('user:status', callback)
}
// Chat events
onChatUpdate(callback: (chat: Chat) => void): void {
this.socket?.on('chat:update', callback)
}
onChatJoin(callback: (data: { chatId: string; user: User }) => void): void {
this.socket?.on('chat:join', callback)
}
onChatLeave(callback: (data: { chatId: string; userId: string }) => void): void {
this.socket?.on('chat:leave', callback)
}
joinChat(chatId: string): void {
this.socket?.emit('chat:join', chatId)
}
leaveChat(chatId: string): void {
this.socket?.emit('chat:leave', chatId)
}
// Group events
onGroupMemberAdd(callback: (data: { groupId: string; user: User; addedBy: User }) => void): void {
this.socket?.on('group:member:add', callback)
}
onGroupMemberRemove(callback: (data: { groupId: string; userId: string; removedBy: User }) => void): void {
this.socket?.on('group:member:remove', callback)
}
onGroupUpdate(callback: (group: any) => void): void {
this.socket?.on('group:update', callback)
}
// Notification events
onNotification(callback: (notification: any) => void): void {
this.socket?.on('notification', callback)
}
// Utility methods
isConnected(): boolean {
return this.socket?.connected || false
}
emit(event: string, data?: any): void {
this.socket?.emit(event, data)
}
on(event: string, callback: (...args: any[]) => void): void {
this.socket?.on(event, callback)
}
off(event: string, callback?: (...args: any[]) => void): void {
this.socket?.off(event, callback)
}
// Remove all listeners for cleanup
removeAllListeners(): void {
this.socket?.removeAllListeners()
}
}
export const socketService = new SocketService()