fix: channel deletion navigates to space root instead of @me
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.
This commit is contained in:
@@ -240,6 +240,20 @@ export function AppLayout() {
|
|||||||
}
|
}
|
||||||
}, [spaceId, channelId, channels, navigate]);
|
}, [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) {
|
if (isLoading || !user) {
|
||||||
return (
|
return (
|
||||||
<div className="h-screen flex items-center justify-center bg-surface-chat">
|
<div className="h-screen flex items-center justify-center bg-surface-chat">
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import { Modal } from '../ui/Modal';
|
import { Modal } from '../ui/Modal';
|
||||||
import { ConfirmDialog } from '../ui/ConfirmDialog';
|
import { ConfirmDialog } from '../ui/ConfirmDialog';
|
||||||
import { useUIStore } from '../../stores/uiStore';
|
import { useUIStore } from '../../stores/uiStore';
|
||||||
import { useSpaceStore, getApiForOrigin } from '../../stores/spaceStore';
|
import { useSpaceStore, getApiForOrigin } from '../../stores/spaceStore';
|
||||||
import { useChatStore } from '../../stores/chatStore';
|
|
||||||
import { api } from '../../api/client';
|
import { api } from '../../api/client';
|
||||||
import { PermissionBits, permissionsToString, stringToPermissions, hasPermissionBit } from '../../utils/permissions';
|
import { PermissionBits, permissionsToString, stringToPermissions, hasPermissionBit } from '../../utils/permissions';
|
||||||
|
|
||||||
@@ -24,8 +22,6 @@ export function ChannelSettingsModal() {
|
|||||||
const channels = useSpaceStore((s) => s.channels);
|
const channels = useSpaceStore((s) => s.channels);
|
||||||
const spaces = useSpaceStore((s) => s.spaces);
|
const spaces = useSpaceStore((s) => s.spaces);
|
||||||
const spacePermissions = useSpaceStore((s) => s.spacePermissions);
|
const spacePermissions = useSpaceStore((s) => s.spacePermissions);
|
||||||
const currentChannelId = useChatStore((s) => s.currentChannelId);
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const [isPrivate, setIsPrivate] = useState(false);
|
const [isPrivate, setIsPrivate] = useState(false);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
@@ -116,9 +112,6 @@ export function ChannelSettingsModal() {
|
|||||||
const channelApi = getApiForOrigin(space?._instanceOrigin ?? '');
|
const channelApi = getApiForOrigin(space?._instanceOrigin ?? '');
|
||||||
await channelApi.channels.delete(channelId);
|
await channelApi.channels.delete(channelId);
|
||||||
closeModal();
|
closeModal();
|
||||||
if (currentChannelId === channelId) {
|
|
||||||
navigate('/channels/@me');
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError(err instanceof Error ? err.message : 'Failed to delete channel');
|
setError(err instanceof Error ? err.message : 'Failed to delete channel');
|
||||||
setIsDeleting(false);
|
setIsDeleting(false);
|
||||||
|
|||||||
@@ -633,18 +633,6 @@ function handleEvent(origin: string, event: ServerEvent): void {
|
|||||||
useVoiceStore.setState({ voiceUsers: newVoiceUsers });
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user