Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(267)

Unified Diff: ios/chrome/share_extension/share_view_controller.mm

Issue 2586713002: Upstream code and resources for Chrome on iOS extensions. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ios/chrome/share_extension/share_view_controller.h ('k') | ios/chrome/share_extension/ui_util.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ios/chrome/share_extension/share_view_controller.mm
diff --git a/ios/chrome/share_extension/share_view_controller.mm b/ios/chrome/share_extension/share_view_controller.mm
new file mode 100644
index 0000000000000000000000000000000000000000..cfd96dd90ff60adbffcf114b6b902b6e09a8191b
--- /dev/null
+++ b/ios/chrome/share_extension/share_view_controller.mm
@@ -0,0 +1,298 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <MobileCoreServices/MobileCoreServices.h>
+
+#import "ios/chrome/share_extension/share_view_controller.h"
+
+#import "base/ios/block_types.h"
+#import "base/mac/foundation_util.h"
+#import "ios/chrome/common/app_group/app_group_constants.h"
+#import "ios/chrome/share_extension/share_extension_view.h"
+#import "ios/chrome/share_extension/ui_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+// Type for completion handler to fetch the components of the share items.
+// |idResponse| type depends on the element beeing fetched.
+using ItemBlock = void (^)(id idResponse, NSError* error);
+
+namespace {
+
+// Minimum size around the widget
+const CGFloat kShareExtensionMargin = 15;
+const CGFloat kShareExtensionMaxWidth = 390;
+// Clip the last separator out of the table view.
+const CGFloat kScreenShotWidth = 100;
+const CGFloat kScreenShotHeight = 100;
+const CGFloat kAnimationDuration = 0.3;
+const CGFloat kMediumAlpha = 0.5;
+
+} // namespace
+
+@interface ShareViewController ()<ShareExtensionViewActionTarget> {
+ // This constraint the center of the widget to be vertically in the center
+ // of the the screen. It has to be modified for the dismissal animation.
+ NSLayoutConstraint* _centerYConstraint;
+
+ NSURL* _shareURL;
+ NSString* _shareTitle;
+ NSExtensionItem* _shareItem;
+}
+
+@property(nonatomic, weak) UIView* maskView;
+@property(nonatomic, weak) ShareExtensionView* shareView;
+@property(nonatomic, assign) app_group::ShareExtensionItemType itemType;
+
+// Creates a files in |app_group::ShareExtensionItemsFolder()| containing a
+// serialized NSDictionary.
+// If |cancel| is true, |actionType| is ignored.
+- (void)queueActionItemURL:(NSURL*)URL
+ title:(NSString*)title
+ action:(app_group::ShareExtensionItemType)actionType
+ cancel:(BOOL)cancel
+ completion:(ProceduralBlock)completion;
+
+// Loads all the shared elements from the extension context and update the UI.
+- (void)loadElementsFromContext;
+
+// Performs a fade in animation for the whole widget.
+- (void)fadeIn;
+
+// Sets constaints to the widget so that margin are at least
+// kShareExtensionMargin points and widget width is closest up to
+// kShareExtensionMaxWidth points.
+- (void)constrainWidgetWidth;
+
+@end
+
+@implementation ShareViewController
+
+@synthesize maskView = _maskView;
+@synthesize shareView = _shareView;
+@synthesize itemType = _itemType;
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ // This view shadows the screen under the share extension.
+ UIView* maskView = [[UIView alloc] initWithFrame:CGRectZero];
+ [self setMaskView:maskView];
+ [self.maskView
+ setBackgroundColor:[UIColor colorWithWhite:0 alpha:kMediumAlpha]];
+ [self.view addSubview:self.maskView];
+ ui_util::ConstrainAllSidesOfViewToView(self.view, self.maskView);
+
+ // This view is the main view of the share extension.
+ ShareExtensionView* shareView =
+ [[ShareExtensionView alloc] initWithActionTarget:self];
+ [self setShareView:shareView];
+ [self.view addSubview:self.shareView];
+
+ [self constrainWidgetWidth];
+
+ // Center the widget in the screen.
+ _centerYConstraint = [[shareView centerYAnchor]
+ constraintEqualToAnchor:[self.view centerYAnchor]];
+ [_centerYConstraint setActive:YES];
+ [[[shareView centerXAnchor] constraintEqualToAnchor:[self.view centerXAnchor]]
+ setActive:YES];
+
+ [self.maskView setTranslatesAutoresizingMaskIntoConstraints:NO];
+ [self.shareView setTranslatesAutoresizingMaskIntoConstraints:NO];
+
+ [self loadElementsFromContext];
+ [self fadeIn];
+}
+
+- (void)constrainWidgetWidth {
+ // Setting the constraints.
+ NSDictionary* views = @{ @"share" : self.shareView };
+
+ NSDictionary* metrics = @{
+ @"margin" : @(kShareExtensionMargin),
+ @"maxWidth" : @(kShareExtensionMaxWidth),
+ };
+
+ NSArray* constraints = @[
+ // Sets the margin around the share extension.
+ @"H:|-(>=margin)-[share(<=maxWidth)]-(>=margin)-|",
+ // If the screen is too small, reduce width of widget.
+ @"H:[share(==maxWidth@900)]",
+ ];
+
+ for (NSString* constraint : constraints) {
+ [NSLayoutConstraint
+ activateConstraints:[NSLayoutConstraint
+ constraintsWithVisualFormat:constraint
+ options:0
+ metrics:metrics
+ views:views]];
+ }
+
+ // |self.shareView| must be as large as possible and in the center of the
+ // screen.
+ [self.shareView
+ setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh
+ forAxis:UILayoutConstraintAxisHorizontal];
+}
+
+- (void)fadeIn {
+ // Fade in animation.
+ [self.maskView setAlpha:0];
+ [self.shareView setAlpha:0];
+ [UIView animateWithDuration:kAnimationDuration
+ animations:^{
+ [self.maskView setAlpha:kMediumAlpha];
+ [self.shareView setAlpha:1];
+ }];
+}
+
+- (void)loadElementsFromContext {
+ NSString* typeURL = static_cast<NSString*>(kUTTypeURL);
+ for (NSExtensionItem* item in self.extensionContext.inputItems) {
+ for (NSItemProvider* itemProvider in item.attachments) {
+ if ([itemProvider hasItemConformingToTypeIdentifier:typeURL]) {
+ ItemBlock URLCompletion = ^(id idURL, NSError* error) {
+ NSURL* URL = static_cast<NSURL*>(idURL);
+ dispatch_async(dispatch_get_main_queue(), ^{
+ _shareItem = [item copy];
+ _shareURL = [URL copy];
+ _shareTitle = [[[item attributedContentText] string] copy];
+ if ([_shareTitle length] == 0) {
+ _shareTitle = [URL host];
+ }
+ [self.shareView setURL:URL];
+ [self.shareView setTitle:_shareTitle];
+ });
+
+ };
+ [itemProvider loadItemForTypeIdentifier:typeURL
+ options:nil
+ completionHandler:URLCompletion];
+ NSDictionary* imageOptions = @{
+ NSItemProviderPreferredImageSizeKey : [NSValue
+ valueWithCGSize:CGSizeMake(kScreenShotWidth, kScreenShotHeight)]
+ };
+ ItemBlock ImageCompletion = ^(id item, NSError* error) {
+
+ UIImage* image = static_cast<UIImage*>(item);
+ if (image) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self.shareView setScreenshot:image];
+ });
+ }
+
+ };
+ [itemProvider loadPreviewImageWithOptions:imageOptions
+ completionHandler:ImageCompletion];
+ }
+ }
+ }
+}
+
+- (void)dismissAndReturnItem:(NSExtensionItem*)item {
+ // Set the Y center constraints so the whole extension slides up out of the
+ // screen. Constant is relative to the center of the screen.
+ [_centerYConstraint setConstant:-(self.view.frame.size.height +
+ self.shareView.frame.size.height) /
+ 2];
+ [UIView animateWithDuration:kAnimationDuration
+ animations:^{
+ [self.maskView setAlpha:0];
+ [self.view layoutIfNeeded];
+ }
+ completion:^(BOOL finished) {
+ NSArray* returnItem = item ? @[ item ] : @[];
+ [self.extensionContext completeRequestReturningItems:returnItem
+ completionHandler:nil];
+ }];
+}
+
+- (void)queueActionItemURL:(NSURL*)URL
+ title:(NSString*)title
+ action:(app_group::ShareExtensionItemType)actionType
+ cancel:(BOOL)cancel
+ completion:(ProceduralBlock)completion {
+ NSURL* readingListURL = app_group::ShareExtensionItemsFolder();
+ if (![[NSFileManager defaultManager]
+ fileExistsAtPath:[readingListURL path]]) {
+ [[NSFileManager defaultManager] createDirectoryAtPath:[readingListURL path]
+ withIntermediateDirectories:YES
+ attributes:nil
+ error:nil];
+ }
+ NSDate* date = [NSDate date];
+ NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
+ // This format sorts files by alphabetical order.
+ [dateFormatter setDateFormat:@"yyyy-MM-dd-HH-mm-ss.SSSSSS"];
+ NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
+ [dateFormatter setTimeZone:timeZone];
+ NSString* dateString = [dateFormatter stringFromDate:date];
+ NSURL* fileURL =
+ [readingListURL URLByAppendingPathComponent:dateString isDirectory:NO];
+
+ NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
+ if (URL)
+ [dict setObject:URL forKey:app_group::kShareItemURL];
+ if (title)
+ [dict setObject:title forKey:app_group::kShareItemTitle];
+ [dict setObject:date forKey:app_group::kShareItemDate];
+
+ if (!cancel) {
+ NSNumber* entryType = [NSNumber numberWithInteger:actionType];
+ [dict setObject:entryType forKey:app_group::kShareItemType];
+ }
+
+ [dict setValue:[NSNumber numberWithBool:cancel]
+ forKey:app_group::kShareItemCancel];
+ NSData* data = [NSKeyedArchiver archivedDataWithRootObject:dict];
+ [[NSFileManager defaultManager] createFileAtPath:[fileURL path]
+ contents:data
+ attributes:nil];
+ if (completion) {
+ completion();
+ }
+}
+
+#pragma mark - ShareExtensionViewActionTarget
+
+- (void)shareExtensionViewDidSelectCancel:(id)sender {
+ [self queueActionItemURL:nil
+ title:nil
+ action:app_group::READING_LIST_ITEM // Ignored
+ cancel:YES
+ completion:^{
+ [self dismissAndReturnItem:nil];
+ }];
+}
+
+- (void)shareExtensionViewDidSelectAddToReadingList:(id)sender {
+ [self queueActionItemURL:_shareURL
+ title:_shareTitle
+ action:app_group::READING_LIST_ITEM
+ cancel:NO
+ completion:^{
+ [self dismissAndReturnItem:_shareItem];
+ }];
+}
+
+- (void)shareExtensionViewDidSelectAddToBookmarks:(id)sender {
+ [self queueActionItemURL:_shareURL
+ title:_shareTitle
+ action:app_group::BOOKMARK_ITEM
+ cancel:NO
+ completion:^{
+ [self dismissAndReturnItem:_shareItem];
+ }];
+}
+
+- (void)shareExtensionView:(id)sender
+ typeChanged:(app_group::ShareExtensionItemType)type {
+ [self setItemType:type];
+}
+
+@end
« no previous file with comments | « ios/chrome/share_extension/share_view_controller.h ('k') | ios/chrome/share_extension/ui_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698