fix: join user socket channel to receive approval notifications

The socket wasn't receiving join-request-approved events because it hadn't
joined the user-specific channel. Now:

- Fetch viewer ID from /api/viewer endpoint
- Emit 'join-user-channel' with userId on socket connect
- Socket joins `user:${userId}` room to receive moderation events
- Approval notifications now trigger automatic room join

This completes the real-time approval notification flow.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock
2025-10-14 07:43:49 -05:00
parent 0d4f400dca
commit 7d08fdd906
2 changed files with 84 additions and 38 deletions

View File

@@ -358,28 +358,51 @@ export default function JoinRoomPage({ params }: { params: { code: string } }) {
console.log('[Join Page] Setting up approval listener for room:', targetRoomData.id)
// Socket listener for real-time approval notification
const socket = io({ path: '/api/socket' })
let socket: ReturnType<typeof io> | null = null
socket.on('connect', () => {
console.log('[Join Page] Socket connected')
})
// Fetch viewer ID and set up socket
const setupSocket = async () => {
try {
// Get current user's viewer ID
const res = await fetch('/api/viewer')
if (!res.ok) {
console.error('[Join Page] Failed to get viewer ID')
return
}
socket.on('join-request-approved', (data: { roomId: string; requestId: string }) => {
console.log('[Join Page] Request approved via socket!', data)
if (data.roomId === targetRoomData.id) {
console.log('[Join Page] Joining room automatically...')
handleJoin(targetRoomData.id)
const { viewerId } = await res.json()
console.log('[Join Page] Got viewer ID:', viewerId)
// Connect socket
socket = io({ path: '/api/socket' })
socket.on('connect', () => {
console.log('[Join Page] Socket connected, joining user channel')
// Join user-specific channel to receive moderation events
socket?.emit('join-user-channel', { userId: viewerId })
})
socket.on('join-request-approved', (data: { roomId: string; requestId: string }) => {
console.log('[Join Page] Request approved via socket!', data)
if (data.roomId === targetRoomData.id) {
console.log('[Join Page] Joining room automatically...')
handleJoin(targetRoomData.id)
}
})
socket.on('connect_error', (error) => {
console.error('[Join Page] Socket connection error:', error)
})
} catch (error) {
console.error('[Join Page] Error setting up socket:', error)
}
})
}
socket.on('connect_error', (error) => {
console.error('[Join Page] Socket connection error:', error)
})
setupSocket()
return () => {
console.log('[Join Page] Cleaning up approval listener')
socket.disconnect()
socket?.disconnect()
}
}, [approvalRequested, targetRoomData, handleJoin])

View File

@@ -149,35 +149,58 @@ export function JoinRoomModal({ isOpen, onClose, onSuccess }: JoinRoomModalProps
console.log('[JoinRoomModal] Setting up approval listener for room:', roomInfo.id)
// Socket listener for real-time approval notification
const socket = io({ path: '/api/socket' })
let socket: ReturnType<typeof io> | null = null
socket.on('connect', () => {
console.log('[JoinRoomModal] Socket connected')
})
socket.on('join-request-approved', async (data: { roomId: string; requestId: string }) => {
console.log('[JoinRoomModal] Request approved via socket!', data)
if (data.roomId === roomInfo.id) {
console.log('[JoinRoomModal] Joining room automatically...')
try {
await joinRoom(roomInfo.id)
handleClose()
onSuccess?.()
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to join room')
setIsLoading(false)
// Fetch viewer ID and set up socket
const setupSocket = async () => {
try {
// Get current user's viewer ID
const res = await fetch('/api/viewer')
if (!res.ok) {
console.error('[JoinRoomModal] Failed to get viewer ID')
return
}
}
})
socket.on('connect_error', (error) => {
console.error('[JoinRoomModal] Socket connection error:', error)
})
const { viewerId } = await res.json()
console.log('[JoinRoomModal] Got viewer ID:', viewerId)
// Connect socket
socket = io({ path: '/api/socket' })
socket.on('connect', () => {
console.log('[JoinRoomModal] Socket connected, joining user channel')
// Join user-specific channel to receive moderation events
socket?.emit('join-user-channel', { userId: viewerId })
})
socket.on('join-request-approved', async (data: { roomId: string; requestId: string }) => {
console.log('[JoinRoomModal] Request approved via socket!', data)
if (data.roomId === roomInfo.id) {
console.log('[JoinRoomModal] Joining room automatically...')
try {
await joinRoom(roomInfo.id)
handleClose()
onSuccess?.()
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to join room')
setIsLoading(false)
}
}
})
socket.on('connect_error', (error) => {
console.error('[JoinRoomModal] Socket connection error:', error)
})
} catch (error) {
console.error('[JoinRoomModal] Error setting up socket:', error)
}
}
setupSocket()
return () => {
console.log('[JoinRoomModal] Cleaning up approval listener')
socket.disconnect()
socket?.disconnect()
}
}, [approvalRequested, roomInfo, joinRoom, handleClose, onSuccess])