feat: add leave confirmation dialog for group DM close button
The X button on group DMs now opens a ConfirmDialog instead of soft-closing. The right-click 'Leave Group' context menu also routes through the same confirmation. Prevents dead group DM data from accumulating when users soft-close instead of leaving.
This commit is contained in:
@@ -109,6 +109,8 @@ export function ChannelSidebar() {
|
|||||||
// Delete category confirmation state
|
// Delete category confirmation state
|
||||||
const [deleteCategoryId, setDeleteCategoryId] = useState<string | null>(null);
|
const [deleteCategoryId, setDeleteCategoryId] = useState<string | null>(null);
|
||||||
const [deleteCategoryLoading, setDeleteCategoryLoading] = useState(false);
|
const [deleteCategoryLoading, setDeleteCategoryLoading] = useState(false);
|
||||||
|
const [leaveGroupDmId, setLeaveGroupDmId] = useState<string | null>(null);
|
||||||
|
const [leaveGroupDmLoading, setLeaveGroupDmLoading] = useState(false);
|
||||||
|
|
||||||
// Centralized context menu
|
// Centralized context menu
|
||||||
const openContextMenu = useContextMenuStore((s) => s.open);
|
const openContextMenu = useContextMenuStore((s) => s.open);
|
||||||
@@ -378,15 +380,11 @@ export function ChannelSidebar() {
|
|||||||
</svg>
|
</svg>
|
||||||
),
|
),
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
if (currentChannelId === dmId) {
|
setLeaveGroupDmId(dmId);
|
||||||
navigate('/channels/@me');
|
|
||||||
setCurrentChannel(null);
|
|
||||||
}
|
|
||||||
useSpaceStore.getState().leaveDm(dmId);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}, [openContextMenu, currentChannelId, navigate, setCurrentChannel]);
|
}, [openContextMenu]);
|
||||||
|
|
||||||
const handleChannelClick = (channelId: string) => {
|
const handleChannelClick = (channelId: string) => {
|
||||||
setCurrentChannel(channelId);
|
setCurrentChannel(channelId);
|
||||||
@@ -568,15 +566,18 @@ export function ChannelSidebar() {
|
|||||||
<button
|
<button
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
// Navigate away if currently viewing this DM
|
if (isGroup) {
|
||||||
|
setLeaveGroupDmId(dm.id);
|
||||||
|
} else {
|
||||||
if (currentChannelId === dm.id) {
|
if (currentChannelId === dm.id) {
|
||||||
navigate('/channels/@me');
|
navigate('/channels/@me');
|
||||||
setCurrentChannel(null);
|
setCurrentChannel(null);
|
||||||
}
|
}
|
||||||
useSpaceStore.getState().closeDm(dm.id);
|
useSpaceStore.getState().closeDm(dm.id);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
className="opacity-0 group-hover:opacity-100 text-txt-tertiary hover:text-txt-primary transition-opacity flex-shrink-0 ml-1"
|
className="opacity-0 group-hover:opacity-100 text-txt-tertiary hover:text-txt-primary transition-opacity flex-shrink-0 ml-1"
|
||||||
title="Close DM"
|
title={isGroup ? 'Leave Group DM' : 'Close DM'}
|
||||||
>
|
>
|
||||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
||||||
<path d="M18.4 4L12 10.4L5.6 4L4 5.6L10.4 12L4 18.4L5.6 20L12 13.6L18.4 20L20 18.4L13.6 12L20 5.6L18.4 4Z" />
|
<path d="M18.4 4L12 10.4L5.6 4L4 5.6L10.4 12L4 18.4L5.6 20L12 13.6L18.4 20L20 18.4L13.6 12L20 5.6L18.4 4Z" />
|
||||||
@@ -606,6 +607,31 @@ export function ChannelSidebar() {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
{floatingPanel}
|
{floatingPanel}
|
||||||
|
<ConfirmDialog
|
||||||
|
isOpen={leaveGroupDmId !== null}
|
||||||
|
onClose={() => setLeaveGroupDmId(null)}
|
||||||
|
onConfirm={async () => {
|
||||||
|
if (!leaveGroupDmId) return;
|
||||||
|
setLeaveGroupDmLoading(true);
|
||||||
|
try {
|
||||||
|
if (currentChannelId === leaveGroupDmId) {
|
||||||
|
navigate('/channels/@me');
|
||||||
|
setCurrentChannel(null);
|
||||||
|
}
|
||||||
|
await useSpaceStore.getState().leaveDm(leaveGroupDmId);
|
||||||
|
setLeaveGroupDmId(null);
|
||||||
|
} catch {
|
||||||
|
// leaveDm already handles errors
|
||||||
|
} finally {
|
||||||
|
setLeaveGroupDmLoading(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
title="Leave Group DM"
|
||||||
|
description="Are you sure you want to leave? You won't be able to rejoin unless someone adds you back."
|
||||||
|
confirmLabel="Leave"
|
||||||
|
variant="danger"
|
||||||
|
loading={leaveGroupDmLoading}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -860,6 +886,31 @@ export function ChannelSidebar() {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
{floatingPanel}
|
{floatingPanel}
|
||||||
|
<ConfirmDialog
|
||||||
|
isOpen={leaveGroupDmId !== null}
|
||||||
|
onClose={() => setLeaveGroupDmId(null)}
|
||||||
|
onConfirm={async () => {
|
||||||
|
if (!leaveGroupDmId) return;
|
||||||
|
setLeaveGroupDmLoading(true);
|
||||||
|
try {
|
||||||
|
if (currentChannelId === leaveGroupDmId) {
|
||||||
|
navigate('/channels/@me');
|
||||||
|
setCurrentChannel(null);
|
||||||
|
}
|
||||||
|
await useSpaceStore.getState().leaveDm(leaveGroupDmId);
|
||||||
|
setLeaveGroupDmId(null);
|
||||||
|
} catch {
|
||||||
|
// leaveDm already handles errors
|
||||||
|
} finally {
|
||||||
|
setLeaveGroupDmLoading(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
title="Leave Group DM"
|
||||||
|
description="Are you sure you want to leave? You won't be able to rejoin unless someone adds you back."
|
||||||
|
confirmLabel="Leave"
|
||||||
|
variant="danger"
|
||||||
|
loading={leaveGroupDmLoading}
|
||||||
|
/>
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
isOpen={deleteCategoryId !== null}
|
isOpen={deleteCategoryId !== null}
|
||||||
onClose={() => setDeleteCategoryId(null)}
|
onClose={() => setDeleteCategoryId(null)}
|
||||||
|
|||||||
Reference in New Issue
Block a user