From dd24158603f0782f078704994ae821d1aa1f3369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mariusz=20=C5=9Apiewak?= Date: Fri, 2 Aug 2024 18:27:29 +0200 Subject: [PATCH] Enable favorites reordering on New Tab Page (#3169) Task/Issue URL: https://app.asana.com/0/1206226850447395/1207932325145653/f Tech Design URL: CC: **Description**: Adds reordering capability for Favorites on New Tab Page. **Steps to test this PR**: 1. Reorder Favorites in different ways (to last, to first etc.) 2. Verify if the order is preserved across launches and NTP instances. 3. Check if the order is reflected in the Bookmakrs/Favorites list --- DuckDuckGo/Favorite.swift | 2 +- DuckDuckGo/FavoritesDefaultModel.swift | 13 ++++++++++++ DuckDuckGo/FavoritesModel.swift | 1 + DuckDuckGo/FavoritesPreviewModel.swift | 4 ++++ DuckDuckGo/FavoritesView.swift | 28 +++++++++++++++++++++++++- 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/DuckDuckGo/Favorite.swift b/DuckDuckGo/Favorite.swift index 70262d0086..5b13b1f484 100644 --- a/DuckDuckGo/Favorite.swift +++ b/DuckDuckGo/Favorite.swift @@ -20,7 +20,7 @@ import Bookmarks import SwiftUI -struct Favorite: Identifiable, Equatable { +struct Favorite: Identifiable, Equatable, Hashable { let id: String let title: String let domain: String diff --git a/DuckDuckGo/FavoritesDefaultModel.swift b/DuckDuckGo/FavoritesDefaultModel.swift index b91c44c579..eae3da8301 100644 --- a/DuckDuckGo/FavoritesDefaultModel.swift +++ b/DuckDuckGo/FavoritesDefaultModel.swift @@ -114,6 +114,19 @@ final class FavoritesDefaultModel: FavoritesModel { onFavoriteEdit?(entity) } + func moveFavorites(from indexSet: IndexSet, to index: Int) { + guard indexSet.count == 1, + let fromIndex = indexSet.first else { return } + + let favorite = allFavorites[fromIndex] + guard let entity = lookupEntity(for: favorite) else { return } + + // adjust for different target index handling + let toIndex = index > fromIndex ? index - 1 : index + interactionModel.moveFavorite(entity, fromIndex: fromIndex, toIndex: toIndex) + allFavorites.move(fromOffsets: IndexSet(integer: fromIndex), toOffset: index) + } + private func lookupEntity(for favorite: Favorite) -> BookmarkEntity? { interactionModel.favorites.first { $0.uuid == favorite.id diff --git a/DuckDuckGo/FavoritesModel.swift b/DuckDuckGo/FavoritesModel.swift index 60313089b1..427df29d1a 100644 --- a/DuckDuckGo/FavoritesModel.swift +++ b/DuckDuckGo/FavoritesModel.swift @@ -37,6 +37,7 @@ protocol FavoritesModel: AnyObject, ObservableObject { func favoriteSelected(_ favorite: Favorite) func editFavorite(_ favorite: Favorite) func deleteFavorite(_ favorite: Favorite) + func moveFavorites(from indexSet: IndexSet, to index: Int) } struct FavoritesSlice { diff --git a/DuckDuckGo/FavoritesPreviewModel.swift b/DuckDuckGo/FavoritesPreviewModel.swift index a3e145013f..4e59572887 100644 --- a/DuckDuckGo/FavoritesPreviewModel.swift +++ b/DuckDuckGo/FavoritesPreviewModel.swift @@ -71,6 +71,10 @@ final class FavoritesPreviewModel: FavoritesModel { } + func moveFavorites(from indexSet: IndexSet, to index: Int) { + allFavorites.move(fromOffsets: indexSet, toOffset: index) + } + func loadFavicon(for favorite: Favorite, size: CGFloat) async { } diff --git a/DuckDuckGo/FavoritesView.swift b/DuckDuckGo/FavoritesView.swift index 24a01a2bc0..bd2f690fe5 100644 --- a/DuckDuckGo/FavoritesView.swift +++ b/DuckDuckGo/FavoritesView.swift @@ -19,6 +19,7 @@ import Bookmarks import SwiftUI +import UniformTypeIdentifiers struct FavoritesView: View { @Environment(\.horizontalSizeClass) var horizontalSizeClass @@ -35,7 +36,7 @@ struct FavoritesView: View { let result = model.prefixedFavorites(for: columns) NewTabPageGridView { _ in - ForEach(result.items) { item in + ReorderableForEach(result.items) { item in Button(action: { model.favoriteSelected(item) selectionFeedback.selectionChanged() @@ -52,6 +53,15 @@ struct FavoritesView: View { .background(.clear) .frame(width: NewTabPageGrid.Item.edgeSize) }) + .previewShape() + } preview: { favorite in + FavoriteIconView(favorite: favorite, faviconLoading: model.faviconLoader) + .frame(width: NewTabPageGrid.Item.edgeSize) + .previewShape() + } onMove: { from, to in + withAnimation { + model.moveFavorites(from: from, to: to) + } } } @@ -70,6 +80,22 @@ struct FavoritesView: View { } } +private extension View { + func previewShape() -> some View { + contentShape(.dragPreview, RoundedRectangle(cornerRadius: 8)) + } +} + +extension Favorite: Reorderable { + var dropItemProvider: NSItemProvider { + NSItemProvider(object: (urlObject?.absoluteString ?? "") as NSString) + } + + var dropType: UTType { + .plainText + } +} + #Preview { FavoritesView(model: FavoritesPreviewModel()) }