From 39174e5454aa92bc120bda98beb0012f2b2b653e Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Thu, 12 Mar 2026 02:55:52 +0100 Subject: [PATCH] fix: channel deletion navigates to space root instead of @me MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add stale-channel guard in AppLayout that redirects to the space root when the URL's channelId no longer exists in the channel list. Remove the hardcoded navigate('/channels/@me') from ChannelSettingsModal and the redundant setCurrentChannel fallback from the WS channel_deleted handler — AppLayout's guard now handles all cases uniformly. --- packages/web/src/components/layout/AppLayout.tsx | 14 ++++++++++++++ .../src/components/modals/ChannelSettingsModal.tsx | 7 ------- packages/web/src/hooks/useWebSocket.ts | 12 ------------ 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/packages/web/src/components/layout/AppLayout.tsx b/packages/web/src/components/layout/AppLayout.tsx index 602ef643..075df99c 100644 --- a/packages/web/src/components/layout/AppLayout.tsx +++ b/packages/web/src/components/layout/AppLayout.tsx @@ -240,6 +240,20 @@ export function AppLayout() { } }, [spaceId, channelId, channels, navigate]); + // Guard: redirect when URL channelId no longer exists (deleted, permission revoked, etc.) + useEffect(() => { + if (!spaceId || spaceId === '@me' || !channelId) return; + if (channels.length === 0) return; + + const { channelToSpaceMap } = useSpaceStore.getState(); + const firstCh = channels[0]; + if (!firstCh || channelToSpaceMap.get(firstCh.id) !== spaceId) return; + + if (!channels.some(c => c.id === channelId)) { + navigate(`/channels/${spaceId}`, { replace: true }); + } + }, [spaceId, channelId, channels, navigate]); + if (isLoading || !user) { return (
diff --git a/packages/web/src/components/modals/ChannelSettingsModal.tsx b/packages/web/src/components/modals/ChannelSettingsModal.tsx index 72cf828b..93ff5669 100644 --- a/packages/web/src/components/modals/ChannelSettingsModal.tsx +++ b/packages/web/src/components/modals/ChannelSettingsModal.tsx @@ -1,10 +1,8 @@ import React, { useState, useEffect } from 'react'; -import { useNavigate } from 'react-router-dom'; import { Modal } from '../ui/Modal'; import { ConfirmDialog } from '../ui/ConfirmDialog'; import { useUIStore } from '../../stores/uiStore'; import { useSpaceStore, getApiForOrigin } from '../../stores/spaceStore'; -import { useChatStore } from '../../stores/chatStore'; import { api } from '../../api/client'; import { PermissionBits, permissionsToString, stringToPermissions, hasPermissionBit } from '../../utils/permissions'; @@ -24,8 +22,6 @@ export function ChannelSettingsModal() { const channels = useSpaceStore((s) => s.channels); const spaces = useSpaceStore((s) => s.spaces); const spacePermissions = useSpaceStore((s) => s.spacePermissions); - const currentChannelId = useChatStore((s) => s.currentChannelId); - const navigate = useNavigate(); const [isPrivate, setIsPrivate] = useState(false); const [isLoading, setIsLoading] = useState(false); @@ -116,9 +112,6 @@ export function ChannelSettingsModal() { const channelApi = getApiForOrigin(space?._instanceOrigin ?? ''); await channelApi.channels.delete(channelId); closeModal(); - if (currentChannelId === channelId) { - navigate('/channels/@me'); - } } catch (err) { setError(err instanceof Error ? err.message : 'Failed to delete channel'); setIsDeleting(false); diff --git a/packages/web/src/hooks/useWebSocket.ts b/packages/web/src/hooks/useWebSocket.ts index 25aaa0b9..25d4f50c 100644 --- a/packages/web/src/hooks/useWebSocket.ts +++ b/packages/web/src/hooks/useWebSocket.ts @@ -633,18 +633,6 @@ function handleEvent(origin: string, event: ServerEvent): void { useVoiceStore.setState({ voiceUsers: newVoiceUsers }); } } - { - const { currentChannelId } = useChatStore.getState(); - if (currentChannelId === event.channelId) { - const { channels: remainingChannels } = useSpaceStore.getState(); - const firstText = remainingChannels.find(c => c.type === 'text'); - if (firstText) { - useChatStore.getState().setCurrentChannel(firstText.id); - } else { - useChatStore.getState().setCurrentChannel(null); - } - } - } break; }