fix(web): normalize channel and server IDs across channel store and auto-select default channel

This commit is contained in:
2026-07-27 11:56:39 -04:00
parent 13e3aec2d5
commit 5eeb659b70
3 changed files with 51 additions and 17 deletions
+13 -1
View File
@@ -117,9 +117,21 @@ export function ChannelList() {
}, [fetchNotifSettings, fetchReadStates]); }, [fetchNotifSettings, fetchReadStates]);
const channels = useMemo(() => { const channels = useMemo(() => {
return activeServerId ? channelsByServer[activeServerId] || [] : []; return activeServerId ? channelsByServer[activeServerId.toLowerCase()] || [] : [];
}, [activeServerId, channelsByServer]); }, [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(() => { const activeServer = useMemo(() => {
if (!activeServerId) return null; if (!activeServerId) return null;
return servers.find((s) => s.id === activeServerId) || null; return servers.find((s) => s.id === activeServerId) || null;
+2 -2
View File
@@ -332,8 +332,8 @@ export function ChatArea() {
); );
const canBulkDelete = true; const canBulkDelete = true;
const channels = activeServerId ? channelsByServer[activeServerId] || [] : []; const channels = activeServerId ? channelsByServer[activeServerId.toLowerCase()] || [] : [];
const activeChannel = channels.find((c) => c.id === activeChannelId); const activeChannel = channels.find((c) => c.id.toLowerCase() === activeChannelId);
const members = activeServerId ? membersByServer[activeServerId] || [] : []; const members = activeServerId ? membersByServer[activeServerId] || [] : [];
// Humans only for mentions / nickname lookup (bots live in member list separately). // Humans only for mentions / nickname lookup (bots live in member list separately).
const humanMembers = useMemo(() => members.filter((m) => !m.is_bot), [members]); const humanMembers = useMemo(() => members.filter((m) => !m.is_bot), [members]);
+36 -14
View File
@@ -33,11 +33,18 @@ export const useChannelStore = create<ChannelState>((set) => ({
error: null, error: null,
fetchChannels: async (serverId) => { fetchChannels: async (serverId) => {
const srvId = serverId.toLowerCase();
set({ isLoading: true, error: null }); set({ isLoading: true, error: null });
try { try {
const channels = await api.get<Channel[]>(`/servers/${serverId}/channels`); const channels = await api.get<Channel[]>(`/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) => ({ set((state) => ({
channelsByServer: { ...state.channelsByServer, [serverId]: channels }, channelsByServer: { ...state.channelsByServer, [srvId]: normalized },
isLoading: false, isLoading: false,
})); }));
} catch (error) { } catch (error) {
@@ -63,37 +70,52 @@ export const useChannelStore = create<ChannelState>((set) => ({
} }
}, },
addChannel: (channel) => addChannel: (channel) => {
const norm = {
...channel,
id: channel.id.toLowerCase(),
server_id: channel.server_id.toLowerCase(),
};
set((state) => { 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 { return {
channelsByServer: { channelsByServer: {
...state.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) => { set((state) => {
const list = state.channelsByServer[channel.server_id] || []; const list = state.channelsByServer[norm.server_id] || [];
return { return {
channelsByServer: { channelsByServer: {
...state.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) => { set((state) => {
const next: Record<string, Channel[]> = {}; const next: Record<string, Channel[]> = {};
for (const serverId of Object.keys(state.channelsByServer)) { 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 { return {
channelsByServer: next, channelsByServer: next,
activeChannelId: state.activeChannelId === id ? null : state.activeChannelId, activeChannelId: state.activeChannelId === chId ? null : state.activeChannelId,
}; };
}), });
},
})); }));