Skip to content

Commit ad8884c

Browse files
committed
feat: add drag and drop to move favorites between folders and to root
1 parent d004e3c commit ad8884c

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

TablePro/ViewModels/FavoritesSidebarViewModel.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,16 @@ final class FavoritesSidebarViewModel {
128128
}
129129
}
130130

131+
func moveFavorite(id: UUID, toFolder folderId: UUID?) {
132+
Task {
133+
let allFavorites = await manager.fetchFavorites(connectionId: connectionId)
134+
guard var favorite = allFavorites.first(where: { $0.id == id }) else { return }
135+
favorite.folderId = folderId
136+
favorite.updatedAt = Date()
137+
_ = await manager.updateFavorite(favorite)
138+
}
139+
}
140+
131141
func deleteFavorites(_ favorites: [SQLFavorite]) {
132142
Task {
133143
await manager.deleteFavorites(ids: favorites.map(\.id))

TablePro/Views/Sidebar/FavoritesTabView.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77

88
import SwiftUI
9+
import UniformTypeIdentifiers
910

1011
/// Full-tab favorites view with folder hierarchy and bottom toolbar
1112
struct FavoritesTabView: View {
@@ -77,6 +78,9 @@ struct FavoritesTabView: View {
7778
.onDeleteCommand {
7879
deleteSelectedFavorites()
7980
}
81+
.onDrop(of: [.plainText], isTargeted: nil) { providers in
82+
handleDrop(providers: providers, targetFolderId: nil)
83+
}
8084
}
8185

8286
/// Renders tree items with DisclosureGroup for folders.
@@ -100,6 +104,9 @@ struct FavoritesTabView: View {
100104
coordinator: coordinator
101105
)
102106
}
107+
.onDrag {
108+
NSItemProvider(object: favorite.id.uuidString as NSString)
109+
}
103110
case .folder(let folder, let children):
104111
DisclosureGroup(isExpanded: Binding(
105112
get: { viewModel.expandedFolderIds.contains(folder.id) },
@@ -156,7 +163,24 @@ struct FavoritesTabView: View {
156163
}
157164
)
158165
}
166+
.onDrop(of: [.plainText], isTargeted: nil) { providers in
167+
handleDrop(providers: providers, targetFolderId: folder.id)
168+
}
169+
}
170+
}
171+
172+
private func handleDrop(providers: [NSItemProvider], targetFolderId: UUID?) -> Bool {
173+
guard let provider = providers.first else { return false }
174+
provider.loadObject(ofClass: NSString.self) { object, _ in
175+
guard let idString = object as? String, let favoriteId = UUID(uuidString: idString) else { return }
176+
Task { @MainActor in
177+
viewModel.moveFavorite(id: favoriteId, toFolder: targetFolderId)
178+
if let targetFolderId {
179+
viewModel.expandedFolderIds.insert(targetFolderId)
180+
}
181+
}
159182
}
183+
return true
160184
}
161185

162186
private func deleteSelectedFavorites() {

0 commit comments

Comments
 (0)