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; }