native macOS codings agent orchestrator
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Restore sidebar drop targets during drag

onevcat ab86831c 971a98ea

+85 -33
+50 -30
supacode/Features/Repositories/Views/SidebarDragSupport.swift
··· 50 50 } 51 51 52 52 struct SidebarRepositoryDropDelegate: DropDelegate { 53 + let isEnabled: Bool 53 54 let destination: (DropInfo) -> Int 54 55 let repositoryOrderIDs: [Repository.ID] 55 56 @Binding var targetedDestination: Int? ··· 57 58 let onDragEnded: () -> Void 58 59 59 60 func dropEntered(info: DropInfo) { 61 + guard isEnabled else { 62 + targetedDestination = nil 63 + return 64 + } 60 65 targetedDestination = destination(info) 61 66 } 62 67 ··· 65 70 } 66 71 67 72 func dropUpdated(info: DropInfo) -> DropProposal? { 73 + guard isEnabled else { 74 + targetedDestination = nil 75 + return nil 76 + } 68 77 targetedDestination = destination(info) 69 78 return DropProposal(operation: .move) 70 79 } 71 80 72 81 func performDrop(info: DropInfo) -> Bool { 82 + guard isEnabled else { 83 + targetedDestination = nil 84 + return false 85 + } 73 86 let dropDestination = destination(info) 74 87 targetedDestination = nil 75 88 guard let provider = info.itemProviders(for: [.prowlSidebarDragPayload]).first else { ··· 96 109 } 97 110 98 111 struct SidebarWorktreeDropDelegate: DropDelegate { 112 + let isEnabled: Bool 99 113 let destination: (DropInfo) -> Int 100 114 let sectionIDs: [Worktree.ID] 101 115 @Binding var targetedDestination: Int? ··· 103 117 let onDragEnded: () -> Void 104 118 105 119 func dropEntered(info: DropInfo) { 120 + guard isEnabled else { 121 + targetedDestination = nil 122 + return 123 + } 106 124 targetedDestination = destination(info) 107 125 } 108 126 ··· 111 129 } 112 130 113 131 func dropUpdated(info: DropInfo) -> DropProposal? { 132 + guard isEnabled else { 133 + targetedDestination = nil 134 + return nil 135 + } 114 136 targetedDestination = destination(info) 115 137 return DropProposal(operation: .move) 116 138 } 117 139 118 140 func performDrop(info: DropInfo) -> Bool { 141 + guard isEnabled else { 142 + targetedDestination = nil 143 + return false 144 + } 119 145 let dropDestination = destination(info) 120 146 targetedDestination = nil 121 147 guard let provider = info.itemProviders(for: [.prowlSidebarDragPayload]).first else { ··· 294 320 295 321 @ViewBuilder 296 322 func body(content: Content) -> some View { 297 - if isEnabled { 298 - content.onDrop( 299 - of: [.prowlSidebarDragPayload], 300 - delegate: SidebarRepositoryDropDelegate( 301 - destination: { info in 302 - info.location.y < 24 ? index : index + 1 303 - }, 304 - repositoryOrderIDs: repositoryOrderIDs, 305 - targetedDestination: $targetedDestination, 306 - onDrop: actions.onDrop, 307 - onDragEnded: actions.onDragEnded 308 - ) 323 + content.onDrop( 324 + of: [.prowlSidebarDragPayload], 325 + delegate: SidebarRepositoryDropDelegate( 326 + isEnabled: isEnabled, 327 + destination: { info in 328 + info.location.y < 24 ? index : index + 1 329 + }, 330 + repositoryOrderIDs: repositoryOrderIDs, 331 + targetedDestination: $targetedDestination, 332 + onDrop: actions.onDrop, 333 + onDragEnded: actions.onDragEnded 309 334 ) 310 - } else { 311 - content 312 - } 335 + ) 313 336 } 314 337 } 315 338 ··· 322 345 323 346 @ViewBuilder 324 347 func body(content: Content) -> some View { 325 - if isEnabled { 326 - content.onDrop( 327 - of: [.prowlSidebarDragPayload], 328 - delegate: SidebarWorktreeDropDelegate( 329 - destination: { info in 330 - info.location.y < 18 ? index : index + 1 331 - }, 332 - sectionIDs: rowIDs, 333 - targetedDestination: $targetedDestination, 334 - onDrop: actions.onDrop, 335 - onDragEnded: actions.onDragEnded 336 - ) 348 + content.onDrop( 349 + of: [.prowlSidebarDragPayload], 350 + delegate: SidebarWorktreeDropDelegate( 351 + isEnabled: isEnabled, 352 + destination: { info in 353 + info.location.y < 18 ? index : index + 1 354 + }, 355 + sectionIDs: rowIDs, 356 + targetedDestination: $targetedDestination, 357 + onDrop: actions.onDrop, 358 + onDragEnded: actions.onDragEnded 337 359 ) 338 - } else { 339 - content 340 - } 360 + ) 341 361 } 342 362 }
+35 -3
supacode/Features/Repositories/Views/WorktreeRowsView.swift
··· 14 14 @Environment(\.resolvedKeybindings) private var resolvedKeybindings 15 15 @State private var draggingWorktreeIDs: Set<Worktree.ID> = [] 16 16 @State private var hoveredWorktreeID: Worktree.ID? 17 + @State private var contextMenuHighlightedWorktreeID: Worktree.ID? 17 18 @State private var targetedPinnedDropDestination: Int? 18 19 @State private var targetedUnpinnedDropDestination: Int? 19 20 ··· 40 41 shortcutIndexByID: shortcutIndexByID 41 42 ) 42 43 .animation(isSidebarDragActive ? nil : .easeOut(duration: 0.2), value: rowIDs) 44 + .onReceive(NotificationCenter.default.publisher(for: NSMenu.didEndTrackingNotification)) { _ in 45 + contextMenuHighlightedWorktreeID = nil 46 + } 43 47 } 44 48 45 49 @ViewBuilder ··· 134 138 .contentShape(Rectangle()) 135 139 Group { 136 140 if row.isRemovable, let worktree = store.state.worktree(for: row.id), !isRepositoryRemoving { 137 - baseRow.contextMenu { 138 - rowContextMenu(worktree: worktree, row: row) 139 - } 141 + baseRow 142 + .contextMenu { 143 + ContextMenuHighlightActivator { 144 + scheduleContextMenuHighlight(for: row.id) 145 + } 146 + rowContextMenu(worktree: worktree, row: row) 147 + } 140 148 } else { 141 149 baseRow 142 150 } ··· 324 332 325 333 private func worktreeRowView(_ row: WorktreeRowModel, config: WorktreeRowViewConfig) -> some View { 326 334 let isSelected = selectedWorktreeIDs.contains(row.id) 335 + let showsContextMenuHighlight = contextMenuHighlightedWorktreeID == row.id && !isSelected 327 336 let taskStatus = terminalManager.taskStatus(for: row.id) 328 337 let isRunScriptRunning = terminalManager.isRunScriptRunning(for: row.id) 329 338 let isWorktreeDragActive = !draggingWorktreeIDs.isEmpty ··· 359 368 .padding(.horizontal, 6) 360 369 } 361 370 } 371 + .overlay { 372 + if showsContextMenuHighlight { 373 + RoundedRectangle(cornerRadius: 5) 374 + .stroke(Color.accentColor, lineWidth: 2) 375 + .padding(.horizontal, 6) 376 + } 377 + } 362 378 .transition(.opacity) 363 379 .moveDisabled(config.moveDisabled) 380 + } 381 + 382 + private func scheduleContextMenuHighlight(for worktreeID: Worktree.ID) { 383 + guard !selectedWorktreeIDs.contains(worktreeID) else { return } 384 + Task { @MainActor in 385 + contextMenuHighlightedWorktreeID = worktreeID 386 + } 364 387 } 365 388 366 389 @ViewBuilder ··· 495 518 return row.name 496 519 } 497 520 } 521 + 522 + private struct ContextMenuHighlightActivator: View { 523 + let activate: () -> Void 524 + 525 + var body: some View { 526 + EmptyView() 527 + .onAppear(perform: activate) 528 + } 529 + }