Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Fix #3713: Add option to drag/drop/rearrange favourites on New Tab Page Controller #4401

Merged
merged 2 commits into from
Oct 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,12 @@ class NewTabPageViewController: UIViewController {
}
#endif

collectionView.delegate = self
collectionView.dataSource = self
collectionView.do {
$0.delegate = self
$0.dataSource = self
$0.dragDelegate = self
$0.dropDelegate = self
}

background.changed = { [weak self] in
self?.setupBackgroundImage()
Expand Down Expand Up @@ -907,6 +911,91 @@ extension NewTabPageViewController: UICollectionViewDataSource {
}
}

// MARK: - UICollectionViewDragDelegate & UICollectionViewDropDelegate

extension NewTabPageViewController: UICollectionViewDragDelegate, UICollectionViewDropDelegate {

func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
// Check If the item that is dragged is a favourite item
guard sections[indexPath.section] is FavoritesSectionProvider else {
return []
}

let itemProvider = NSItemProvider(object: "\(indexPath)" as NSString)
let dragItem = UIDragItem(itemProvider: itemProvider).then {
$0.previewProvider = { () -> UIDragPreview? in
guard let cell = collectionView.cellForItem(at: indexPath) as? FavoriteCell else {
return nil
}
return UIDragPreview(view: cell.imageView)
}
}

return [dragItem]
}

func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
guard let sourceIndexPath = coordinator.items.first?.sourceIndexPath else { return }
let destinationIndexPath: IndexPath

if let indexPath = coordinator.destinationIndexPath {
destinationIndexPath = indexPath
} else {
let section = max(collectionView.numberOfSections - 1, 0)
let row = collectionView.numberOfItems(inSection: section)
destinationIndexPath = IndexPath(row: max(row - 1, 0), section: section)
}

guard sourceIndexPath.section == destinationIndexPath.section else { return }

if coordinator.proposal.operation == .move {
guard let item = coordinator.items.first else { return }

Favorite.reorder(
sourceIndexPath: sourceIndexPath,
destinationIndexPath: destinationIndexPath,
isInteractiveDragReorder: true
)
_ = coordinator.drop(item.dragItem, toItemAt: destinationIndexPath)

}
}

func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {
guard let destinationIndexSection = destinationIndexPath?.section,
let favouriteSection = sections[destinationIndexSection] as? FavoritesSectionProvider,
favouriteSection.hasMoreThanOneFavouriteItems else {
return .init(operation: .cancel)
}

return .init(operation: .move, intent: .insertAtDestinationIndexPath)
}

func collectionView(_ collectionView: UICollectionView, dragPreviewParametersForItemAt indexPath: IndexPath) -> UIDragPreviewParameters? {
fetchInteractionPreviewParameters(at: indexPath)
}

func collectionView(_ collectionView: UICollectionView, dropPreviewParametersForItemAt indexPath: IndexPath) -> UIDragPreviewParameters? {
fetchInteractionPreviewParameters(at: indexPath)
}

func collectionView(_ collectionView: UICollectionView, dragSessionIsRestrictedToDraggingApplication session: UIDragSession) -> Bool {
return true
}

private func fetchInteractionPreviewParameters(at indexPath: IndexPath) -> UIDragPreviewParameters {
let previewParameters = UIDragPreviewParameters().then {
$0.backgroundColor = .clear

if let cell = collectionView.cellForItem(at: indexPath) as? FavoriteCell {
$0.visiblePath = UIBezierPath(roundedRect: cell.imageView.frame, cornerRadius: 8)
}
}

return previewParameters
}
}

extension NewTabPageViewController {
private class NewTabCollectionView: UICollectionView {
override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
Expand All @@ -921,6 +1010,8 @@ extension NewTabPageViewController {
showsVerticalScrollIndicator = false
// Even on light mode we use a darker background now
indicatorStyle = .white
// Drag should be enabled to rearrange favourite
dragInteractionEnabled = true
}
@available(*, unavailable)
required init(coder: NSCoder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ class FavoritesSectionProvider: NSObject, NTPObservableSectionProvider {
var action: (Favorite, BookmarksAction) -> Void
var legacyLongPressAction: (UIAlertController) -> Void

var hasMoreThanOneFavouriteItems: Bool {
frc.fetchedObjects?.count ?? 0 > 0
}

private var frc: NSFetchedResultsController<Favorite>

init(action: @escaping (Favorite, BookmarksAction) -> Void,
Expand Down