diff --git a/apps/ios/Plotwist/Plotwist/Views/Home/ProfileCollectionGrid.swift b/apps/ios/Plotwist/Plotwist/Views/Home/ProfileCollectionGrid.swift index b4bba9db..43dd75b5 100644 --- a/apps/ios/Plotwist/Plotwist/Views/Home/ProfileCollectionGrid.swift +++ b/apps/ios/Plotwist/Plotwist/Views/Home/ProfileCollectionGrid.swift @@ -88,7 +88,9 @@ struct ProfileCollectionGrid: View { onTapItem(item) } .onDrag { - draggingItem = item + withAnimation(.easeInOut(duration: 0.2)) { + draggingItem = item + } return NSItemProvider(object: item.id as NSString) } .opacity(removingItemIds.contains(item.id) ? 0 : 1) @@ -108,6 +110,10 @@ struct ProfileCollectionGrid: View { } .padding(.horizontal, 24) .padding(.top, 16) + .onDrop(of: [.text], delegate: GridFallbackDropDelegate( + draggingItem: $draggingItem, + onReorder: onReorder + )) } // MARK: - Context Menu @@ -161,7 +167,28 @@ struct CollectionReorderDelegate: DropDelegate { } func performDrop(info: DropInfo) -> Bool { - draggingItem = nil + withAnimation(.easeInOut(duration: 0.2)) { + draggingItem = nil + } + onReorder() + return true + } + + func dropUpdated(info: DropInfo) -> DropProposal? { + DropProposal(operation: .move) + } +} + +// MARK: - Grid Fallback Drop Delegate +/// Catches drops that land between grid items (in the grid area but not on a specific item) +struct GridFallbackDropDelegate: DropDelegate { + @Binding var draggingItem: UserItemSummary? + var onReorder: () -> Void + + func performDrop(info: DropInfo) -> Bool { + withAnimation(.easeInOut(duration: 0.2)) { + draggingItem = nil + } onReorder() return true } diff --git a/apps/ios/Plotwist/Plotwist/Views/Home/ProfileTabView.swift b/apps/ios/Plotwist/Plotwist/Views/Home/ProfileTabView.swift index 15c98825..311b1116 100644 --- a/apps/ios/Plotwist/Plotwist/Views/Home/ProfileTabView.swift +++ b/apps/ios/Plotwist/Plotwist/Views/Home/ProfileTabView.swift @@ -4,6 +4,7 @@ // import SwiftUI +import UniformTypeIdentifiers // MARK: - Profile Tab View struct ProfileTabView: View { @@ -57,6 +58,15 @@ struct ProfileTabView: View { errorView } } + .onDrop(of: [.text], isTargeted: nil) { _ in + if draggingItem != nil { + withAnimation(.easeInOut(duration: 0.2)) { + draggingItem = nil + } + saveCollectionOrder() + } + return true + } .onAppear { if !hasAppeared { hasAppeared = true @@ -107,7 +117,6 @@ struct ProfileTabView: View { ) } .toolbar(draggingItem != nil ? .hidden : .visible, for: .tabBar) - .animation(.easeInOut(duration: 0.2), value: draggingItem != nil) } }