Attachment reordering

This commit is contained in:
Shadowfacts 2024-09-13 11:20:10 -04:00
parent 7d47f1f259
commit 02fd724b0b
1 changed files with 66 additions and 1 deletions

View File

@ -62,6 +62,11 @@ private struct Callbacks {
draft.attachments = NSMutableOrderedSet(array: array) draft.attachments = NSMutableOrderedSet(array: array)
} }
func reorderAttachments(with difference: CollectionDifference<DraftAttachment>) {
let array = draft.draftAttachments.applying(difference)!
draft.attachments = NSMutableOrderedSet(array: array)
}
func addPhoto() { func addPhoto() {
presentAssetPicker?() { presentAssetPicker?() {
insertAttachments(at: draft.attachments.count, itemProviders: $0.map(\.itemProvider)) insertAttachments(at: draft.attachments.count, itemProviders: $0.map(\.itemProvider))
@ -100,6 +105,31 @@ private struct WrappedCollectionView: UIViewRepresentable {
context.coordinator.dataSource = dataSource context.coordinator.dataSource = dataSource
view.delegate = context.coordinator view.delegate = context.coordinator
view.isScrollEnabled = false view.isScrollEnabled = false
dataSource.reorderingHandlers.canReorderItem = {
if case .attachment(_) = $0 {
true
} else {
false
}
}
dataSource.reorderingHandlers.didReorder = { transaction in
let attachmentsChanges = transaction.difference.map {
switch $0 {
case .insert(let offset, let element, let associatedWith):
guard case .attachment(let attachment) = element else { fatalError() }
return CollectionDifference<DraftAttachment>.Change.insert(offset: offset, element: attachment, associatedWith: associatedWith)
case .remove(let offset, let element, let associatedWith):
guard case .attachment(let attachment) = element else { fatalError() }
return CollectionDifference<DraftAttachment>.Change.remove(offset: offset, element: attachment, associatedWith: associatedWith)
}
}
let attachmentsDiff = CollectionDifference(attachmentsChanges)!
callbacks.reorderAttachments(with: attachmentsDiff)
}
let longPressRecognizer = UILongPressGestureRecognizer(target: context.coordinator, action: #selector(WrappedCollectionViewCoordinator.reorderingLongPressRecognized))
longPressRecognizer.delegate = context.coordinator
view.addGestureRecognizer(longPressRecognizer)
return view return view
} }
@ -188,7 +218,7 @@ private final class IntrinsicContentSizeCollectionView: UICollectionView {
} }
@available(iOS 16.0, *) @available(iOS 16.0, *)
private final class WrappedCollectionViewCoordinator: NSObject, UICollectionViewDelegate { private final class WrappedCollectionViewCoordinator: NSObject, UICollectionViewDelegate, UIGestureRecognizerDelegate {
var callbacks: Callbacks var callbacks: Callbacks
var setHeightOfCellBeingDeleted: ((CGFloat) -> Void)? var setHeightOfCellBeingDeleted: ((CGFloat) -> Void)?
@ -277,6 +307,41 @@ private final class WrappedCollectionViewCoordinator: NSObject, UICollectionView
callbacks.togglePoll() callbacks.togglePoll()
} }
} }
func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveOfItemFromOriginalIndexPath originalIndexPath: IndexPath, atCurrentIndexPath currentIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
let snapshot = dataSource.snapshot()
let attachmentsSection = snapshot.indexOfSection(.attachments)!
if proposedIndexPath.section != attachmentsSection {
return IndexPath(item: snapshot.itemIdentifiers(inSection: .attachments).count - 1, section: attachmentsSection)
} else {
return proposedIndexPath
}
}
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
let collectionView = gestureRecognizer.view as! UICollectionView
let location = gestureRecognizer.location(in: collectionView)
guard let indexPath = collectionView.indexPathForItem(at: location) else {
return false
}
return collectionView.beginInteractiveMovementForItem(at: indexPath)
}
@objc func reorderingLongPressRecognized(_ recognizer: UILongPressGestureRecognizer) {
let collectionView = recognizer.view as! UICollectionView
switch recognizer.state {
case .began:
break
case .changed:
collectionView.updateInteractiveMovementTargetPosition(recognizer.location(in: collectionView))
case .ended:
collectionView.endInteractiveMovement()
case .cancelled:
collectionView.cancelInteractiveMovement()
default:
break
}
}
} }