refactor: wire useDragManager handlers into ChannelSidebar JSX and ChannelItem

This commit is contained in:
Jannis Braun
2026-03-20 20:45:30 +01:00
parent 999c13cdab
commit 439a71dc13
@@ -602,7 +602,7 @@ export function ChannelSidebar() {
</div> </div>
{/* Channels — dynamic category layout */} {/* Channels — dynamic category layout */}
<div className="flex-1 overflow-y-auto pt-3 px-2 space-y-[2px] no-scrollbar" style={{ paddingBottom: floatingPanelHeight + 24 }} onDrop={handleDrop} onDragOver={(e) => e.preventDefault()} onContextMenu={handleSidebarContextMenu}> <div ref={scrollContainerRef} className="flex-1 overflow-y-auto pt-3 px-2 space-y-[2px] no-scrollbar" style={{ paddingBottom: floatingPanelHeight + 24 }} onDrop={containerHandlers.onDrop} onDragOver={containerHandlers.onDragOver} onContextMenu={handleSidebarContextMenu}>
{/* Uncategorized channels */} {/* Uncategorized channels */}
{uncategorizedChannels.length > 0 && ( {uncategorizedChannels.length > 0 && (
<div className="mb-[19px]"> <div className="mb-[19px]">
@@ -627,20 +627,17 @@ export function ChannelSidebar() {
isActive={currentChannelId === channel.id} isActive={currentChannelId === channel.id}
isUnread={unreadChannels.has(channel.id) && currentChannelId !== channel.id} isUnread={unreadChannels.has(channel.id) && currentChannelId !== channel.id}
canManage={canManageChannels} canManage={canManageChannels}
isDragging={channelDragState?.dragType === 'channel' && channelDragState.dragId === channel.id} isDragging={activeDrag?.type === 'channel' && activeDrag.dragId === channel.id}
dropIndicator={dropIndicator?.targetId === channel.id ? dropIndicator.position : null} dropIndicator={dropTarget?.targetId === channel.id ? dropTarget.position : null}
onChannelClick={channel.type === 'voice' ? (() => { onChannelClick={channel.type === 'voice' ? (() => {
const chPerms = channelPermissions.get(channel.id); const chPerms = channelPermissions.get(channel.id);
const canConnect = hasPermissionBit(chPerms, PermissionBits.CONNECT); const canConnect = hasPermissionBit(chPerms, PermissionBits.CONNECT);
if (canConnect) handleVoiceJoin(channel.id); if (canConnect) handleVoiceJoin(channel.id);
}) : (() => handleChannelClick(channel.id))} }) : (() => handleChannelClick(channel.id))}
onSettingsClick={() => openModal('channelSettings', { channelId: channel.id })} onSettingsClick={() => openModal('channelSettings', { channelId: channel.id })}
onDragStart={(e) => handleChannelDragStart(e, channel.id)} channelDragHandlers={channelHandlers(channel.id)}
onDragOver={(e) => handleChannelDragOver(e, channel.id, 'channel')} voiceUserHandlers={voiceUserHandlers}
onDragEnd={handleDragEnd} voiceChannelDropZone={voiceChannelDropZone(channel.id)}
voiceDragState={voiceDragState}
onVoiceDragStart={(userId: string) => setVoiceDragState({ userId, fromChannelId: channel.id })}
onVoiceDragEnd={() => setVoiceDragState(null)}
channelPermissions={channelPermissions} channelPermissions={channelPermissions}
handleVoiceJoin={handleVoiceJoin} handleVoiceJoin={handleVoiceJoin}
/> />
@@ -658,12 +655,9 @@ export function ChannelSidebar() {
const categoryHeader = ( const categoryHeader = (
<div <div
className={`flex items-center justify-between px-1 mb-1 group cursor-pointer ${ className={`flex items-center justify-between px-1 mb-1 group cursor-pointer ${
channelDragState?.dragType === 'category' && channelDragState.dragId === category.id ? 'opacity-50' : '' activeDrag?.type === 'category' && activeDrag.dragId === category.id ? 'opacity-50' : ''
} ${dropIndicator?.targetId === category.id && dropIndicator.type === 'category' ? 'ring-1 ring-accent-mint/40 rounded' : ''}`} } ${dropTarget?.targetId === category.id && dropTarget.targetType === 'category' ? 'ring-1 ring-accent-mint/40 rounded' : ''}`}
draggable={canManageChannels} {...categoryHandlers(category.id)}
onDragStart={(e) => handleCategoryDragStart(e, category.id)}
onDragEnd={handleDragEnd}
onDragOver={(e) => handleChannelDragOver(e, category.id, 'category')}
onClick={() => toggleCollapse(category.id)} onClick={() => toggleCollapse(category.id)}
> >
<div className="flex items-center gap-0.5 text-txt-tertiary hover:text-txt-secondary transition-colors min-w-0"> <div className="flex items-center gap-0.5 text-txt-tertiary hover:text-txt-secondary transition-colors min-w-0">
@@ -728,20 +722,17 @@ export function ChannelSidebar() {
isActive={currentChannelId === channel.id} isActive={currentChannelId === channel.id}
isUnread={unreadChannels.has(channel.id) && currentChannelId !== channel.id} isUnread={unreadChannels.has(channel.id) && currentChannelId !== channel.id}
canManage={canManageChannels} canManage={canManageChannels}
isDragging={channelDragState?.dragType === 'channel' && channelDragState.dragId === channel.id} isDragging={activeDrag?.type === 'channel' && activeDrag.dragId === channel.id}
dropIndicator={dropIndicator?.targetId === channel.id ? dropIndicator.position : null} dropIndicator={dropTarget?.targetId === channel.id ? dropTarget.position : null}
onChannelClick={channel.type === 'voice' ? (() => { onChannelClick={channel.type === 'voice' ? (() => {
const chPerms = channelPermissions.get(channel.id); const chPerms = channelPermissions.get(channel.id);
const canConnect = hasPermissionBit(chPerms, PermissionBits.CONNECT); const canConnect = hasPermissionBit(chPerms, PermissionBits.CONNECT);
if (canConnect) handleVoiceJoin(channel.id); if (canConnect) handleVoiceJoin(channel.id);
}) : (() => handleChannelClick(channel.id))} }) : (() => handleChannelClick(channel.id))}
onSettingsClick={() => openModal('channelSettings', { channelId: channel.id })} onSettingsClick={() => openModal('channelSettings', { channelId: channel.id })}
onDragStart={(e) => handleChannelDragStart(e, channel.id)} channelDragHandlers={channelHandlers(channel.id)}
onDragOver={(e) => handleChannelDragOver(e, channel.id, 'channel')} voiceUserHandlers={voiceUserHandlers}
onDragEnd={handleDragEnd} voiceChannelDropZone={voiceChannelDropZone(channel.id)}
voiceDragState={voiceDragState}
onVoiceDragStart={(userId: string) => setVoiceDragState({ userId, fromChannelId: channel.id })}
onVoiceDragEnd={() => setVoiceDragState(null)}
channelPermissions={channelPermissions} channelPermissions={channelPermissions}
handleVoiceJoin={handleVoiceJoin} handleVoiceJoin={handleVoiceJoin}
/> />
@@ -1221,12 +1212,9 @@ function ChannelItem({
dropIndicator, dropIndicator,
onChannelClick, onChannelClick,
onSettingsClick, onSettingsClick,
onDragStart, channelDragHandlers,
onDragOver, voiceUserHandlers,
onDragEnd, voiceChannelDropZone,
voiceDragState,
onVoiceDragStart,
onVoiceDragEnd,
channelPermissions, channelPermissions,
handleVoiceJoin, handleVoiceJoin,
}: { }: {
@@ -1238,12 +1226,26 @@ function ChannelItem({
dropIndicator: 'before' | 'after' | null; dropIndicator: 'before' | 'after' | null;
onChannelClick: () => void; onChannelClick: () => void;
onSettingsClick: () => void; onSettingsClick: () => void;
onDragStart: (e: React.DragEvent) => void; channelDragHandlers: {
onDragOver: (e: React.DragEvent) => void; draggable: boolean;
onDragEnd: () => void; onDragStart: (e: React.DragEvent) => void;
voiceDragState: { userId: string; fromChannelId: string } | null; onDragOver: (e: React.DragEvent) => void;
onVoiceDragStart: (userId: string) => void; onDragEnd: () => void;
onVoiceDragEnd: () => void; };
voiceUserHandlers: (userId: string, channelId: string) => {
draggable: boolean;
isBeingDragged: boolean;
onDragStart: (e: React.DragEvent) => void;
onDragEnd: (e: React.DragEvent) => void;
};
voiceChannelDropZone: {
onDragOver: (e: React.DragEvent) => void;
onDragEnter: (e: React.DragEvent) => void;
onDragLeave: (e: React.DragEvent) => void;
onDrop: (e: React.DragEvent) => void;
isDragOver: boolean;
isValidTarget: boolean;
};
channelPermissions: Map<string, string>; channelPermissions: Map<string, string>;
handleVoiceJoin: (channelId: string) => void; handleVoiceJoin: (channelId: string) => void;
}) { }) {
@@ -1253,10 +1255,7 @@ function ChannelItem({
return ( return (
<div <div
className={`relative ${isDragging ? 'opacity-50' : ''}`} className={`relative ${isDragging ? 'opacity-50' : ''}`}
draggable={canManage} {...channelDragHandlers}
onDragStart={onDragStart}
onDragOver={onDragOver}
onDragEnd={onDragEnd}
> >
{dropIndicator === 'before' && <div className="absolute top-0 left-2 right-2 h-[2px] bg-accent-mint rounded-full z-10" />} {dropIndicator === 'before' && <div className="absolute top-0 left-2 right-2 h-[2px] bg-accent-mint rounded-full z-10" />}
<VoiceChannel <VoiceChannel
@@ -1266,9 +1265,8 @@ function ChannelItem({
locked={!canConnect} locked={!canConnect}
canManage={canManage} canManage={canManage}
onSettingsClick={onSettingsClick} onSettingsClick={onSettingsClick}
dragState={voiceDragState} voiceUserHandlers={voiceUserHandlers}
onDragStart={onVoiceDragStart} dropZone={voiceChannelDropZone}
onDragEnd={onVoiceDragEnd}
/> />
{dropIndicator === 'after' && <div className="absolute bottom-0 left-2 right-2 h-[2px] bg-accent-mint rounded-full z-10" />} {dropIndicator === 'after' && <div className="absolute bottom-0 left-2 right-2 h-[2px] bg-accent-mint rounded-full z-10" />}
</div> </div>
@@ -1278,10 +1276,7 @@ function ChannelItem({
return ( return (
<div <div
className={`relative ${isDragging ? 'opacity-50' : ''}`} className={`relative ${isDragging ? 'opacity-50' : ''}`}
draggable={canManage} {...channelDragHandlers}
onDragStart={onDragStart}
onDragOver={onDragOver}
onDragEnd={onDragEnd}
> >
{dropIndicator === 'before' && <div className="absolute top-0 left-2 right-2 h-[2px] bg-accent-mint rounded-full z-10" />} {dropIndicator === 'before' && <div className="absolute top-0 left-2 right-2 h-[2px] bg-accent-mint rounded-full z-10" />}
<button <button