From 5eeb659b70fdb5eaca1dfc9d7b908b4de4f82cb8 Mon Sep 17 00:00:00 2001 From: hobokenchicken Date: Mon, 27 Jul 2026 11:56:39 -0400 Subject: [PATCH] fix(web): normalize channel and server IDs across channel store and auto-select default channel --- web/src/components/ChannelList.tsx | 14 ++++++++- web/src/components/ChatArea.tsx | 4 +-- web/src/stores/channel.ts | 50 +++++++++++++++++++++--------- 3 files changed, 51 insertions(+), 17 deletions(-) diff --git a/web/src/components/ChannelList.tsx b/web/src/components/ChannelList.tsx index 7151690..5e5401c 100644 --- a/web/src/components/ChannelList.tsx +++ b/web/src/components/ChannelList.tsx @@ -117,9 +117,21 @@ export function ChannelList() { }, [fetchNotifSettings, fetchReadStates]); const channels = useMemo(() => { - return activeServerId ? channelsByServer[activeServerId] || [] : []; + return activeServerId ? channelsByServer[activeServerId.toLowerCase()] || [] : []; }, [activeServerId, channelsByServer]); + useEffect(() => { + if (channels.length > 0) { + const activeExists = activeChannelId && channels.some((c) => c.id === activeChannelId); + if (!activeExists) { + const defaultChannel = channels.find((c) => c.type === 'text') || channels[0]; + if (defaultChannel) { + setActiveChannel(defaultChannel.id); + } + } + } + }, [channels, activeChannelId, setActiveChannel]); + const activeServer = useMemo(() => { if (!activeServerId) return null; return servers.find((s) => s.id === activeServerId) || null; diff --git a/web/src/components/ChatArea.tsx b/web/src/components/ChatArea.tsx index 966ce25..dc99bfb 100644 --- a/web/src/components/ChatArea.tsx +++ b/web/src/components/ChatArea.tsx @@ -332,8 +332,8 @@ export function ChatArea() { ); const canBulkDelete = true; - const channels = activeServerId ? channelsByServer[activeServerId] || [] : []; - const activeChannel = channels.find((c) => c.id === activeChannelId); + const channels = activeServerId ? channelsByServer[activeServerId.toLowerCase()] || [] : []; + const activeChannel = channels.find((c) => c.id.toLowerCase() === activeChannelId); const members = activeServerId ? membersByServer[activeServerId] || [] : []; // Humans only for mentions / nickname lookup (bots live in member list separately). const humanMembers = useMemo(() => members.filter((m) => !m.is_bot), [members]); diff --git a/web/src/stores/channel.ts b/web/src/stores/channel.ts index 2348d62..890dcd1 100644 --- a/web/src/stores/channel.ts +++ b/web/src/stores/channel.ts @@ -33,11 +33,18 @@ export const useChannelStore = create((set) => ({ error: null, fetchChannels: async (serverId) => { + const srvId = serverId.toLowerCase(); set({ isLoading: true, error: null }); try { - const channels = await api.get(`/servers/${serverId}/channels`); + const channels = await api.get(`/servers/${srvId}/channels`); + const list = Array.isArray(channels) ? channels : []; + const normalized = list.map((c) => ({ + ...c, + id: c.id.toLowerCase(), + server_id: c.server_id.toLowerCase(), + })); set((state) => ({ - channelsByServer: { ...state.channelsByServer, [serverId]: channels }, + channelsByServer: { ...state.channelsByServer, [srvId]: normalized }, isLoading: false, })); } catch (error) { @@ -63,37 +70,52 @@ export const useChannelStore = create((set) => ({ } }, - addChannel: (channel) => + addChannel: (channel) => { + const norm = { + ...channel, + id: channel.id.toLowerCase(), + server_id: channel.server_id.toLowerCase(), + }; set((state) => { - const list = state.channelsByServer[channel.server_id] || []; + const list = state.channelsByServer[norm.server_id] || []; + if (list.some((c) => c.id === norm.id)) return state; return { channelsByServer: { ...state.channelsByServer, - [channel.server_id]: [...list, channel], + [norm.server_id]: [...list, norm], }, }; - }), + }); + }, - updateChannel: (channel) => + updateChannel: (channel) => { + const norm = { + ...channel, + id: channel.id.toLowerCase(), + server_id: channel.server_id.toLowerCase(), + }; set((state) => { - const list = state.channelsByServer[channel.server_id] || []; + const list = state.channelsByServer[norm.server_id] || []; return { channelsByServer: { ...state.channelsByServer, - [channel.server_id]: list.map((c) => (c.id === channel.id ? channel : c)), + [norm.server_id]: list.map((c) => (c.id === norm.id ? norm : c)), }, }; - }), + }); + }, - removeChannel: (id) => + removeChannel: (id) => { + const chId = id.toLowerCase(); set((state) => { const next: Record = {}; for (const serverId of Object.keys(state.channelsByServer)) { - next[serverId] = state.channelsByServer[serverId].filter((c) => c.id !== id); + next[serverId] = state.channelsByServer[serverId].filter((c) => c.id !== chId); } return { channelsByServer: next, - activeChannelId: state.activeChannelId === id ? null : state.activeChannelId, + activeChannelId: state.activeChannelId === chId ? null : state.activeChannelId, }; - }), + }); + }, }));