77 toggleNewTaskDialog ,
88 setActiveTask ,
99 toggleSidebar ,
10- reorderTask ,
10+ reorderTaskVisually ,
1111 getTaskDotStatus ,
1212 getTaskAttentionState ,
1313 getTaskViewportVisibility ,
@@ -126,18 +126,29 @@ export function Sidebar() {
126126 ImportableWorktree [ ] | null
127127 > ( null ) ;
128128 const [ dragFromIndex , setDragFromIndex ] = createSignal < number | null > ( null ) ;
129+ const [ dragFromTaskId , setDragFromTaskId ] = createSignal < string | null > ( null ) ;
129130 const [ dropTargetIndex , setDropTargetIndex ] = createSignal < number | null > ( null ) ;
130131 const [ resizing , setResizing ] = createSignal ( false ) ;
131132 let taskListRef : HTMLDivElement | undefined ;
132133
133134 const sidebarWidth = ( ) => getPanelUserSize ( SIDEBAR_SIZE_KEY ) ?? SIDEBAR_DEFAULT_WIDTH ;
134135
136+ // Maps each visible draggable task ID to its visual position (0-based, excluding coordinated children).
137+ // This keeps drag signals, drop indicators, and data-task-index in the same coordinate space.
135138 const taskIndexById = createMemo ( ( ) => {
136139 const map = new Map < string , number > ( ) ;
137- store . taskOrder . forEach ( ( taskId , idx ) => map . set ( taskId , idx ) ) ;
140+ let visIdx = 0 ;
141+ for ( const taskId of store . taskOrder ) {
142+ if ( ! isCoordinatedChild ( taskId ) ) {
143+ map . set ( taskId , visIdx ++ ) ;
144+ }
145+ }
138146 return map ;
139147 } ) ;
140148
149+ // Number of visible draggable items (used for the end-of-list drop indicator).
150+ const draggableTaskCount = createMemo ( ( ) => taskIndexById ( ) . size ) ;
151+
141152 const groupedTasks = createMemo ( ( ) => computeGroupedTasks ( ) ) ;
142153
143154 function handleResizeMouseDown ( e : MouseEvent ) {
@@ -170,12 +181,12 @@ export function Sidebar() {
170181 const handler = ( e : MouseEvent ) => {
171182 const target = ( e . target as HTMLElement ) . closest < HTMLElement > ( '[data-task-index]' ) ;
172183 if ( ! target ) return ;
173- const index = Number ( target . dataset . taskIndex ) ;
174- const taskId = store . taskOrder [ index ] ;
184+ const visibleIndex = Number ( target . dataset . taskIndex ) ;
185+ // data-task-index is now the visible draggable index; look up the task ID from the visible order
186+ const draggableOrder = store . taskOrder . filter ( ( id ) => ! isCoordinatedChild ( id ) ) ;
187+ const taskId = draggableOrder [ visibleIndex ] ;
175188 if ( taskId === undefined || taskId === null ) return ;
176- // Don't allow dragging coordinated children
177- if ( isCoordinatedChild ( taskId ) ) return ;
178- handleTaskMouseDown ( e , taskId , index ) ;
189+ handleTaskMouseDown ( e , taskId , visibleIndex ) ;
179190 } ;
180191 el . addEventListener ( 'mousedown' , handler ) ;
181192 onCleanup ( ( ) => el . removeEventListener ( 'mousedown' , handler ) ) ;
@@ -262,7 +273,7 @@ export function Sidebar() {
262273 return items . length ;
263274 }
264275
265- function handleTaskMouseDown ( e : MouseEvent , taskId : string , index : number ) {
276+ function handleTaskMouseDown ( e : MouseEvent , taskId : string , visibleIndex : number ) {
266277 if ( e . button !== 0 ) return ;
267278 e . preventDefault ( ) ;
268279 const startX = e . clientX ;
@@ -276,11 +287,12 @@ export function Sidebar() {
276287
277288 if ( ! dragging ) {
278289 dragging = true ;
279- setDragFromIndex ( index ) ;
290+ setDragFromIndex ( visibleIndex ) ;
291+ setDragFromTaskId ( taskId ) ;
280292 document . body . classList . add ( 'dragging-task' ) ;
281293 }
282294
283- setDropTargetIndex ( computeDropIndex ( ev . clientY , index ) ) ;
295+ setDropTargetIndex ( computeDropIndex ( ev . clientY , visibleIndex ) ) ;
284296 }
285297
286298 function onUp ( ) {
@@ -291,12 +303,14 @@ export function Sidebar() {
291303 document . body . classList . remove ( 'dragging-task' ) ;
292304 const from = dragFromIndex ( ) ;
293305 const to = dropTargetIndex ( ) ;
306+ const fromTaskId = dragFromTaskId ( ) ;
294307 setDragFromIndex ( null ) ;
308+ setDragFromTaskId ( null ) ;
295309 setDropTargetIndex ( null ) ;
296310
297- if ( from !== null && to !== null && from !== to ) {
311+ if ( from !== null && to !== null && from !== to && fromTaskId !== null ) {
298312 const adjustedTo = to > from ? to - 1 : to ;
299- reorderTask ( from , adjustedTo ) ;
313+ reorderTaskVisually ( fromTaskId , adjustedTo ) ;
300314 }
301315 } else {
302316 setActiveTask ( taskId ) ;
@@ -739,7 +753,7 @@ export function Sidebar() {
739753 </ For >
740754 </ Show >
741755
742- < Show when = { dropTargetIndex ( ) === store . taskOrder . length } >
756+ < Show when = { dropTargetIndex ( ) === draggableTaskCount ( ) } >
743757 < div class = "drop-indicator" />
744758 </ Show >
745759 </ div >
0 commit comments