Commit cb1356b9 authored by edchin's avatar edchin Committed by Commit Bot

[ios] Separately handle sync vs async drops in tab grid

Handles synchronous localObject drops differently from
asynchronous drops from another app.

Bug: 1128531, 1128656
Change-Id: I45b124f1f8bb887a465a753e40a9fa5cc74c5e78
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2438011
Commit-Queue: Mark Cogan <marq@chromium.org>
Reviewed-by: default avatarMark Cogan <marq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#811653}
parent 698ab388
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
@property(nonatomic, weak) UIImage* snapshot; @property(nonatomic, weak) UIImage* snapshot;
@property(nonatomic, copy) NSString* title; @property(nonatomic, copy) NSString* title;
@property(nonatomic, assign) BOOL titleHidden; @property(nonatomic, assign) BOOL titleHidden;
@property(nonatomic, readonly) UIBezierPath* visiblePath; @property(nonatomic, readonly) UIDragPreviewParameters* dragPreviewParameters;
@end @end
// A GridCell for use in animated transitions that only shows selection state // A GridCell for use in animated transitions that only shows selection state
......
...@@ -255,10 +255,13 @@ void PositionView(UIView* view, CGPoint point) { ...@@ -255,10 +255,13 @@ void PositionView(UIView* view, CGPoint point) {
_titleHidden = titleHidden; _titleHidden = titleHidden;
} }
- (UIBezierPath*)visiblePath { - (UIDragPreviewParameters*)dragPreviewParameters {
return [UIBezierPath UIBezierPath* visiblePath = [UIBezierPath
bezierPathWithRoundedRect:self.bounds bezierPathWithRoundedRect:self.bounds
cornerRadius:self.contentView.layer.cornerRadius]; cornerRadius:self.contentView.layer.cornerRadius];
UIDragPreviewParameters* params = [[UIDragPreviewParameters alloc] init];
params.visiblePath = visiblePath;
return params;
} }
#pragma mark - Private #pragma mark - Private
......
...@@ -25,10 +25,21 @@ ...@@ -25,10 +25,21 @@
// Tells the receiver to incorporate the |dragItem| into the model layer at the // Tells the receiver to incorporate the |dragItem| into the model layer at the
// |destinationIndex|. |fromSameCollection| is an indication that the operation // |destinationIndex|. |fromSameCollection| is an indication that the operation
// is a reorder within the same collection. // is a reorder within the same collection. |dragItem| must have a localObject,
// which means the item is dragged from within the same app.
- (void)dropItem:(UIDragItem*)dragItem - (void)dropItem:(UIDragItem*)dragItem
toIndex:(NSUInteger)destinationIndex toIndex:(NSUInteger)destinationIndex
fromSameCollection:(BOOL)fromSameCollection; fromSameCollection:(BOOL)fromSameCollection;
// Tells the receiver to asynchronously extract data from |itemProvider| into
// the model layer at the |destinationIndex|. |placeholderContext| is used to
// delete the placeholder once the item is ready to be inserted into the model
// layer.
- (void)dropItemFromProvider:(NSItemProvider*)itemProvider
toIndex:(NSUInteger)destinationIndex
placeholderContext:
(id<UICollectionViewDropPlaceholderContext>)placeholderContext;
@end @end
#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_DRAG_DROP_HANDLER_H_ #endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_DRAG_DROP_HANDLER_H_
...@@ -438,11 +438,9 @@ NSIndexPath* CreateIndexPath(NSInteger index) { ...@@ -438,11 +438,9 @@ NSIndexPath* CreateIndexPath(NSInteger index) {
- (UIDragPreviewParameters*)collectionView:(UICollectionView*)collectionView - (UIDragPreviewParameters*)collectionView:(UICollectionView*)collectionView
dragPreviewParametersForItemAtIndexPath:(NSIndexPath*)indexPath { dragPreviewParametersForItemAtIndexPath:(NSIndexPath*)indexPath {
UIDragPreviewParameters* params = [[UIDragPreviewParameters alloc] init]; GridCell* gridCell = base::mac::ObjCCastStrict<GridCell>(
GridCell* cell = base::mac::ObjCCastStrict<GridCell>(
[self.collectionView cellForItemAtIndexPath:indexPath]); [self.collectionView cellForItemAtIndexPath:indexPath]);
params.visiblePath = cell.visiblePath; return gridCell.dragPreviewParameters;
return params;
} }
#pragma mark - UICollectionViewDropDelegate #pragma mark - UICollectionViewDropDelegate
...@@ -471,21 +469,52 @@ NSIndexPath* CreateIndexPath(NSInteger index) { ...@@ -471,21 +469,52 @@ NSIndexPath* CreateIndexPath(NSInteger index) {
(id<UICollectionViewDropCoordinator>)coordinator { (id<UICollectionViewDropCoordinator>)coordinator {
id<UICollectionViewDropItem> item = coordinator.items.firstObject; id<UICollectionViewDropItem> item = coordinator.items.firstObject;
NSIndexPath* dropIndexPath = coordinator.destinationIndexPath; // Append to the end of the collection, unless drop index is specified.
if (!dropIndexPath) { NSUInteger destinationIndex = self.items.count;
dropIndexPath = [NSIndexPath indexPathForItem:(self.items.count - 1) if (item.sourceIndexPath) {
inSection:0]; // The sourceIndexPath is non-nil if the drop item is from this same
// collection view. Move to last position rather than appending if this is a
// reorder operation.
destinationIndex = self.items.count - 1;
}
if (coordinator.destinationIndexPath) {
destinationIndex =
base::checked_cast<NSUInteger>(coordinator.destinationIndexPath.item);
} }
NSIndexPath* dropIndexPath = [NSIndexPath indexPathForItem:destinationIndex
inSection:0];
NSUInteger destinationIndex = // Drop synchronously if local object is available.
base::checked_cast<NSUInteger>(dropIndexPath.item); if (item.dragItem.localObject) {
[coordinator dropItem:item.dragItem toItemAtIndexPath:dropIndexPath]; [coordinator dropItem:item.dragItem toItemAtIndexPath:dropIndexPath];
// The sourceIndexPath is non-nil if the drop item is from this same
// TODO(crbug.com/1095200): Handle the edge case that two windows are // collection view.
// simultaneously dragging and dropping.
[self.dragDropHandler dropItem:item.dragItem [self.dragDropHandler dropItem:item.dragItem
toIndex:destinationIndex toIndex:destinationIndex
fromSameCollection:collectionView.hasActiveDrag]; fromSameCollection:(item.sourceIndexPath != nil)];
return;
}
// Drop asynchronously if local object is not available.
UICollectionViewDropPlaceholder* placeholder =
[[UICollectionViewDropPlaceholder alloc]
initWithInsertionIndexPath:dropIndexPath
reuseIdentifier:kCellIdentifier];
placeholder.cellUpdateHandler = ^(UICollectionViewCell* placeholderCell) {
GridCell* gridCell = base::mac::ObjCCastStrict<GridCell>(placeholderCell);
gridCell.theme = self.theme;
};
placeholder.previewParametersProvider =
^UIDragPreviewParameters*(UICollectionViewCell* placeholderCell) {
GridCell* gridCell = base::mac::ObjCCastStrict<GridCell>(placeholderCell);
return gridCell.dragPreviewParameters;
};
id<UICollectionViewDropPlaceholderContext> context =
[coordinator dropItem:item.dragItem toPlaceholder:placeholder];
[self.dragDropHandler dropItemFromProvider:item.dragItem.itemProvider
toIndex:destinationIndex
placeholderContext:context];
} }
#pragma mark - UIScrollViewDelegate #pragma mark - UIScrollViewDelegate
......
...@@ -465,11 +465,17 @@ web::WebState* GetWebStateWithId(WebStateList* web_state_list, ...@@ -465,11 +465,17 @@ web::WebState* GetWebStateWithId(WebStateList* web_state_list,
withURL:net::GURLWithNSURL(droppedURL)]; withURL:net::GURLWithNSURL(droppedURL)];
return; return;
} }
}
- (void)dropItemFromProvider:(NSItemProvider*)itemProvider
toIndex:(NSUInteger)destinationIndex
placeholderContext:
(id<UICollectionViewDropPlaceholderContext>)placeholderContext {
if (![itemProvider canLoadObjectOfClass:[NSURL class]]) {
[placeholderContext deletePlaceholder];
return;
}
// Handle URLs from other apps asynchronously, as synchronous is not possible
// with NSItemProvider.
NSItemProvider* itemProvider = dragItem.itemProvider;
if ([itemProvider canLoadObjectOfClass:[NSURL class]]) {
// The parameter type has changed with Xcode 12 SDK. // The parameter type has changed with Xcode 12 SDK.
// TODO(crbug.com/1098318): Remove this once Xcode 11 support is dropped. // TODO(crbug.com/1098318): Remove this once Xcode 11 support is dropped.
#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 #if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
...@@ -480,16 +486,13 @@ web::WebState* GetWebStateWithId(WebStateList* web_state_list, ...@@ -480,16 +486,13 @@ web::WebState* GetWebStateWithId(WebStateList* web_state_list,
auto loadHandler = ^(providerType providedItem, NSError* error) { auto loadHandler = ^(providerType providedItem, NSError* error) {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[placeholderContext deletePlaceholder];
NSURL* droppedURL = static_cast<NSURL*>(providedItem); NSURL* droppedURL = static_cast<NSURL*>(providedItem);
[self insertNewItemAtIndex:destinationIndex [self insertNewItemAtIndex:destinationIndex
withURL:net::GURLWithNSURL(droppedURL)]; withURL:net::GURLWithNSURL(droppedURL)];
}); });
}; };
[itemProvider loadObjectOfClass:[NSURL class] completionHandler:loadHandler];
[itemProvider loadObjectOfClass:[NSURL class]
completionHandler:loadHandler];
return;
}
} }
#pragma mark - GridImageDataSource #pragma mark - GridImageDataSource
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment