diff --git a/Source/IGListKit/IGListSectionController.h b/Source/IGListKit/IGListSectionController.h index 6be1e3358..8e18f372c 100644 --- a/Source/IGListKit/IGListSectionController.h +++ b/Source/IGListKit/IGListSectionController.h @@ -132,6 +132,28 @@ NS_SWIFT_NAME(ListSectionController) */ - (UIContextMenuConfiguration * _Nullable)contextMenuConfigurationForItemAtIndex:(NSInteger)index point:(CGPoint)point API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos); +/** + Tells the section controller that the cell has requested a preview for context menu highlight. + + @param configuration Context menu configuration. + + @return An object that conforms to `UITargetedPreview` + + @note The default implementation does nothing. **Calling super is not required.** + */ +- (UITargetedPreview * _Nullable)previewForHighlightingContextMenuWithConfiguration:(UIContextMenuConfiguration *)configuration API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos); + +/** + Tells the section controller that the cell has requested a preview for context menu dismiss. + + @param configuration Context menu configuration. + + @return An object that conforms to `UITargetedPreview` + + @note The default implementation does nothing. **Calling super is not required.** + */ +- (UITargetedPreview * _Nullable)previewForDismissingContextMenuWithConfiguration:(UIContextMenuConfiguration *)configuration API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos); + /** Identifies whether an object can be moved through interactive reordering. diff --git a/Source/IGListKit/IGListSectionController.m b/Source/IGListKit/IGListSectionController.m index bdb2b17fc..b8dcbd180 100644 --- a/Source/IGListKit/IGListSectionController.m +++ b/Source/IGListKit/IGListSectionController.m @@ -101,6 +101,14 @@ - (UIContextMenuConfiguration * _Nullable)contextMenuConfigurationForItemAtIndex return nil; } +- (UITargetedPreview * _Nullable)previewForHighlightingContextMenuWithConfiguration:(UIContextMenuConfiguration *)configuration { + return nil; +} + +- (UITargetedPreview * _Nullable)previewForDismissingContextMenuWithConfiguration:(UIContextMenuConfiguration *)configuration { + return nil; +} + - (BOOL)canMoveItemAtIndex:(NSInteger)index { return NO; } diff --git a/Source/IGListKit/Internal/IGListAdapter+UICollectionView.m b/Source/IGListKit/Internal/IGListAdapter+UICollectionView.m index 3c9405902..5844c6d6c 100644 --- a/Source/IGListKit/Internal/IGListAdapter+UICollectionView.m +++ b/Source/IGListKit/Internal/IGListAdapter+UICollectionView.m @@ -18,6 +18,12 @@ #import "IGListAdapterInternal.h" +@interface IGListAdapter () + +@property (nonatomic, strong) NSMapTable *configurationToSectionController; + +@end + @implementation IGListAdapter (UICollectionView) #pragma mark - UICollectionViewDataSource @@ -278,7 +284,35 @@ - (UIContextMenuConfiguration *)collectionView:(UICollectionView *)collectionVie } IGListSectionController * sectionController = [self sectionControllerForSection:indexPath.section]; - return [sectionController contextMenuConfigurationForItemAtIndex:indexPath.item point:point]; + + UIContextMenuConfiguration *configuration = [sectionController contextMenuConfigurationForItemAtIndex:indexPath.item point:point]; + if (configuration) { + if (!self.configurationToSectionController) { + self.configurationToSectionController = [NSMapTable weakToWeakObjectsMapTable]; + } + [self.configurationToSectionController setObject:configuration forKey:sectionController]; + } + return nil; +} + +- (UITargetedPreview *)collectionView:(UICollectionView *)collectionView previewForHighlightingContextMenuWithConfiguration:(UIContextMenuConfiguration *)configuration API_AVAILABLE(ios(13.0)){ + id collectionViewDelegate = self.collectionViewDelegate; + if ([collectionViewDelegate respondsToSelector:@selector(collectionView:previewForHighlightingContextMenuWithConfiguration:)]) { + return [collectionViewDelegate collectionView:collectionView previewForHighlightingContextMenuWithConfiguration:configuration]; + } + + IGListSectionController * sectionController = [self.configurationToSectionController objectForKey:configuration]; + return [sectionController previewForHighlightingContextMenuWithConfiguration:configuration]; +} + +- (UITargetedPreview *)collectionView:(UICollectionView *)collectionView previewForDismissingContextMenuWithConfiguration:(UIContextMenuConfiguration *)configuration API_AVAILABLE(ios(13.0)){ + id collectionViewDelegate = self.collectionViewDelegate; + if ([collectionViewDelegate respondsToSelector:@selector(collectionView:previewForDismissingContextMenuWithConfiguration:)]) { + return [collectionViewDelegate collectionView:collectionView previewForDismissingContextMenuWithConfiguration:configuration]; + } + + IGListSectionController * sectionController = [self.configurationToSectionController objectForKey:configuration]; + return [sectionController previewForDismissingContextMenuWithConfiguration:configuration]; } #endif diff --git a/Source/IGListKit/Internal/IGListAdapterProxy.m b/Source/IGListKit/Internal/IGListAdapterProxy.m index 8f4b51968..7186bc228 100644 --- a/Source/IGListKit/Internal/IGListAdapterProxy.m +++ b/Source/IGListKit/Internal/IGListAdapterProxy.m @@ -34,6 +34,8 @@ static BOOL isInterceptedSelector(SEL sel) { sel == @selector(collectionView:didHighlightItemAtIndexPath:) || sel == @selector(collectionView:didUnhighlightItemAtIndexPath:) || sel == @selector(collectionView:contextMenuConfigurationForItemAtIndexPath:point:) || + sel == @selector(collectionView:previewForHighlightingContextMenuWithConfiguration:) || + sel == @selector(collectionView:previewForDismissingContextMenuWithConfiguration:) || // UICollectionViewDelegateFlowLayout sel == @selector(collectionView:layout:sizeForItemAtIndexPath:) || sel == @selector(collectionView:layout:insetForSectionAtIndex:) ||