diff --git a/packages/web/src/components/voice/VoiceChannel.tsx b/packages/web/src/components/voice/VoiceChannel.tsx index c8837eed..6d40d936 100644 --- a/packages/web/src/components/voice/VoiceChannel.tsx +++ b/packages/web/src/components/voice/VoiceChannel.tsx @@ -138,8 +138,8 @@ export function VoiceChannel({ channelId, channelName, onClick, locked, canManag )} - {channelName} - {canManage && onSettingsClick && ( + {channelName} + {canManage && ( { e.stopPropagation(); - onSettingsClick(); + onSettingsClick?.(); }} > diff --git a/packages/web/src/hooks/useWebSocket.ts b/packages/web/src/hooks/useWebSocket.ts index a99fb0cd..6c251f7f 100644 --- a/packages/web/src/hooks/useWebSocket.ts +++ b/packages/web/src/hooks/useWebSocket.ts @@ -143,11 +143,31 @@ function handleEvent(origin: string, event: ServerEvent): void { } } - // Only force-reload the current channel on reconnect; other channels keep their cache - if (isHome) { - const { loadMessages: reloadMessages, currentChannelId } = useChatStore.getState(); - if (currentChannelId) { - reloadMessages(currentChannelId, true); + // Clear stale message cache for all channels on this origin so the next + // visit does a fresh fetch (and scroll-to-bottom fires correctly). + // Force-reload the currently open channel immediately. + { + const chatState = useChatStore.getState(); + const { channelOriginMap } = useSpaceStore.getState(); + const newMessages = new Map(chatState.messages); + const newHasMore = new Map(chatState.hasMore); + for (const [channelId, chOrigin] of channelOriginMap) { + if (chOrigin === origin) { + newMessages.delete(channelId); + newHasMore.delete(channelId); + } + } + if (isHome) { + for (const key of [...newMessages.keys()]) { + if (key.startsWith('dm-')) { + newMessages.delete(key); + newHasMore.delete(key); + } + } + } + useChatStore.setState({ messages: newMessages, hasMore: newHasMore }); + if (chatState.currentChannelId) { + chatState.loadMessages(chatState.currentChannelId, true); } }