Chromium Code Reviews| Index: ios/chrome/search_widget_extension/search_widget_view.mm |
| diff --git a/ios/chrome/search_widget_extension/search_widget_view.mm b/ios/chrome/search_widget_extension/search_widget_view.mm |
| index 42a7f8944092839ca1b6516dc943f9907ab0ea27..ddc6ed11ea7422e7f5e6e45dc4da314398020df1 100644 |
| --- a/ios/chrome/search_widget_extension/search_widget_view.mm |
| +++ b/ios/chrome/search_widget_extension/search_widget_view.mm |
| @@ -12,12 +12,11 @@ |
| namespace { |
| -const CGFloat kCursorHeight = 40; |
| -const CGFloat kCursorWidth = 2; |
| -const CGFloat kCursorHorizontalPadding = 10; |
| -const CGFloat kCursorVerticalPadding = 10; |
| -const CGFloat kFakeboxHorizontalPadding = 40; |
| -const CGFloat kFakeboxVerticalPadding = 40; |
| +const CGFloat kContentMargin = 16; |
| +const CGFloat kURLButtonMargin = 10; |
| +const CGFloat kActionButtonSize = 55; |
| +const CGFloat kIconSize = 35; |
| +const CGFloat kMaxContentSize = 421; |
| } // namespace |
| @@ -25,82 +24,339 @@ const CGFloat kFakeboxVerticalPadding = 40; |
| __weak id<SearchWidgetViewActionTarget> _target; |
|
stkhapugin
2017/05/04 13:12:08
nit: Since this is your only ivar, convert it to a
lody
2017/05/05 17:05:44
Done.
|
| } |
| +// The copied URL value. |
|
stkhapugin
2017/05/04 13:12:08
This comment is confusing to someone who's reading
lody
2017/05/05 17:05:43
Done.
|
| @property(nonatomic, copy) NSString* copiedURL; |
| +// The copied URL label containing the URL or a placeholder text. |
| @property(nonatomic, strong) UILabel* copiedURLLabel; |
| -@property(nonatomic, weak) UIView* cursor; |
| +// The copued URL title label containing the title of the copied URL button. |
| +@property(nonatomic, strong) UILabel* openCopiedURLTitleLabel; |
| +// The hairline view shown between the action and copied URL views. |
| +@property(nonatomic, strong) UIView* hairlineView; |
| +// The button shown when there is a copied URL to open. |
| +@property(nonatomic, strong) UIView* copiedButtonView; |
| +// The primary effect view of the widget. Add views here for a more opaque |
| +// appearance. |
| +@property(nonatomic, strong) UIVisualEffectView* primaryEffectView; |
| +// The secondary effect view of the widget. Add views here for a more |
| +// transparent appearance. |
| +@property(nonatomic, strong) UIVisualEffectView* secondaryEffectView; |
| +// The constraints to be activated when the copiedURL section is visible. |
| +@property(nonatomic, strong) |
| + NSArray<NSLayoutConstraint*>* visibleCopiedURLConstraints; |
| +// The constraints to be activated when the copiedURL section is hidden. |
| +@property(nonatomic, strong) |
| + NSArray<NSLayoutConstraint*>* hiddenCopiedURLConstraints; |
| -// Creates and adds a fake omnibox with blinking cursor to the view and sets the |
| -// class cursor property. |
| -- (void)addFakebox; |
| +// Sets up the widget UI. |
| +- (void)createUI; |
| + |
| +// Creates the view for the action buttons. |
|
stkhapugin
2017/05/04 13:12:09
Depending on your class comment's descriptiveness,
lody
2017/05/05 17:05:43
Acknowledged.
|
| +- (UIView*)createActionsView: |
|
stkhapugin
2017/05/04 13:12:08
This should be:
- (UIView*)newActionsView;
(you
lody
2017/05/05 17:05:43
Done.
|
| + (NSMutableArray<NSLayoutConstraint*>*)constraintArray; |
| + |
| +// Creates the view for the copiedURL section. |
| +- (void)createOpenCopiedURLView:(NSLayoutAnchor*)topAnchor |
|
stkhapugin
2017/05/04 13:12:09
This method must return a UIView. Also, if you nee
lody
2017/05/05 17:05:43
This does not create a single view, so returning o
|
| + constraintArray: |
| + (NSMutableArray<NSLayoutConstraint*>*)constraintArray; |
| @end |
| @implementation SearchWidgetView |
| +@synthesize copiedURLVisible = _copiedURLVisible; |
| @synthesize copiedURL = _copiedURL; |
| @synthesize copiedURLLabel = _copiedURLLabel; |
| +@synthesize openCopiedURLTitleLabel = _openCopiedURLTitleLabel; |
| +@synthesize hairlineView = _hairlineView; |
| +@synthesize copiedButtonView = _copiedButtonView; |
| +@synthesize primaryEffectView = _primaryEffectView; |
| +@synthesize secondaryEffectView = _secondaryEffectView; |
| +@synthesize visibleCopiedURLConstraints = _visibleCopiedURLConstraints; |
| +@synthesize hiddenCopiedURLConstraints = _hiddenCopiedURLConstraints; |
| -@synthesize cursor = _cursor; |
| +- (void)setCopiedURLVisible:(BOOL)copiedURLVisible { |
|
stkhapugin
2017/05/04 13:12:09
This should be below initWith...
lody
2017/05/05 17:05:43
Done.
|
| + _copiedURLVisible = copiedURLVisible; |
| + [self updateCopiedURLUI]; |
| +} |
| -- (instancetype)initWithActionTarget:(id<SearchWidgetViewActionTarget>)target { |
| +- (instancetype)initWithActionTarget:(id<SearchWidgetViewActionTarget>)target |
| + primaryVibrancyEffect:(UIVibrancyEffect*)primaryVibrancyEffect |
| + secondaryVibrancyEffect: |
| + (UIVibrancyEffect*)secondaryVibrancyEffect { |
| self = [super initWithFrame:CGRectZero]; |
| if (self) { |
| DCHECK(target); |
| _target = target; |
| - [self addFakebox]; |
| + _primaryEffectView = |
| + [[UIVisualEffectView alloc] initWithEffect:primaryVibrancyEffect]; |
| + _secondaryEffectView = |
| + [[UIVisualEffectView alloc] initWithEffect:secondaryVibrancyEffect]; |
| + _copiedURLVisible = YES; |
| + [self createUI]; |
| + [self updateCopiedURLUI]; |
| } |
| return self; |
| } |
| -- (void)addFakebox { |
| - UIView* fakebox = [[UIView alloc] initWithFrame:CGRectZero]; |
| +- (void)createUI { |
| + // Views added to different effect views need to be constrained to each other. |
| + // This is made easier by putting all the constraints into an array and |
| + // activating them all at once after adding all the views. |
| + NSMutableArray<NSLayoutConstraint*>* constraintArray = [NSMutableArray array]; |
|
stkhapugin
2017/05/04 13:12:08
This potentially gives you a small performance bum
lody
2017/05/05 17:05:43
As discussed, the passing around of constraints is
|
| - UIGestureRecognizer* tapRecognizer = |
| - [[UITapGestureRecognizer alloc] initWithTarget:_target |
| - action:@selector(openSearch:)]; |
| - |
| - [fakebox addGestureRecognizer:tapRecognizer]; |
| - [self addSubview:fakebox]; |
| - |
| - UIView* cursor = [[UIView alloc] initWithFrame:CGRectZero]; |
| - self.cursor = cursor; |
| - self.cursor.backgroundColor = [UIColor blueColor]; |
| - [fakebox addSubview:self.cursor]; |
| - |
| - [fakebox setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| - [self.cursor setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| - [NSLayoutConstraint activateConstraints:@[ |
| - [[fakebox leadingAnchor] constraintEqualToAnchor:self.leadingAnchor |
| - constant:kFakeboxHorizontalPadding], |
| - [[fakebox trailingAnchor] |
| - constraintEqualToAnchor:self.trailingAnchor |
| - constant:-kFakeboxHorizontalPadding], |
| - [[fakebox topAnchor] constraintEqualToAnchor:self.topAnchor |
| - constant:kFakeboxVerticalPadding], |
| - [[fakebox heightAnchor] |
| - constraintEqualToConstant:kCursorHeight + 2 * kCursorVerticalPadding], |
| - |
| - [[self.cursor widthAnchor] constraintEqualToConstant:kCursorWidth], |
| - [[self.cursor leadingAnchor] |
| - constraintEqualToAnchor:fakebox.leadingAnchor |
| - constant:kCursorHorizontalPadding], |
| - [[self.cursor heightAnchor] constraintEqualToConstant:kCursorHeight], |
| - [[self.cursor centerYAnchor] constraintEqualToAnchor:fakebox.centerYAnchor] |
| + for (UIVisualEffectView* effectView in |
| + @[ self.primaryEffectView, self.secondaryEffectView ]) { |
|
stkhapugin
2017/05/04 13:12:09
Please make this array a local variable for improv
lody
2017/05/05 17:05:44
(indentation is good, eyeballs are less good as se
|
| + [self addSubview:effectView]; |
| + effectView.translatesAutoresizingMaskIntoConstraints = NO; |
| + |
| + [constraintArray addObjectsFromArray:@[ |
|
stkhapugin
2017/05/04 13:12:08
There's a helper for this.
lody
2017/05/05 17:05:44
Done.
|
| + [self.leadingAnchor constraintEqualToAnchor:effectView.leadingAnchor], |
| + [self.trailingAnchor constraintEqualToAnchor:effectView.trailingAnchor], |
| + [self.topAnchor constraintEqualToAnchor:effectView.topAnchor], |
| + [self.bottomAnchor constraintEqualToAnchor:effectView.bottomAnchor] |
| + ]]; |
| + } |
| + |
| + UIView* actionsView = [self createActionsView:constraintArray]; |
| + |
| + [self createOpenCopiedURLView:actionsView.bottomAnchor |
| + constraintArray:constraintArray]; |
| + |
| + [NSLayoutConstraint activateConstraints:constraintArray]; |
| +} |
| + |
| +- (UIView*)createActionsView: |
| + (NSMutableArray<NSLayoutConstraint*>*)constraintArray { |
| + UIStackView* actionRow = [[UIStackView alloc] initWithArrangedSubviews:@[ |
| + [self createActionView:@"New Search" |
| + imageName:@"quick_action_search" |
| + actionSelector:@selector(openSearch:) |
| + constraintArray:constraintArray], |
| + [self createActionView:@"Incognito Search" |
| + imageName:@"quick_action_incognito_search" |
| + actionSelector:@selector(openIncognito:) |
| + constraintArray:constraintArray], |
| + [self createActionView:@"Voice Search" |
| + imageName:@"quick_action_voice_search" |
| + actionSelector:@selector(openVoice:) |
| + constraintArray:constraintArray], |
| + [self createActionView:@"Scan QR/Bar Code" |
| + imageName:@"quick_action_camera_search" |
| + actionSelector:@selector(openQRCode:) |
| + constraintArray:constraintArray], |
| + ]]; |
| + |
| + actionRow.axis = UILayoutConstraintAxisHorizontal; |
| + actionRow.alignment = UIStackViewAlignmentCenter; |
| + actionRow.distribution = UIStackViewDistributionEqualSpacing; |
| + actionRow.layoutMargins = |
| + UIEdgeInsetsMake(0, kContentMargin, 0, kContentMargin); |
| + actionRow.layoutMarginsRelativeArrangement = YES; |
| + actionRow.translatesAutoresizingMaskIntoConstraints = NO; |
| + |
| + [self.secondaryEffectView.contentView addSubview:actionRow]; |
| + |
| + // These constraints stretch the action row to the full width of the widget. |
| + // Their priority is < UILayoutPriorityRequired so that they can break when |
| + // the view is larger than kMaxContentSize. |
| + NSLayoutConstraint* actionsLeftConstraint = [actionRow.leftAnchor |
| + constraintEqualToAnchor:self.secondaryEffectView.leftAnchor]; |
| + actionsLeftConstraint.priority = UILayoutPriorityDefaultHigh; |
| + |
| + NSLayoutConstraint* actionsRightConstraint = [actionRow.rightAnchor |
| + constraintEqualToAnchor:self.secondaryEffectView.rightAnchor]; |
| + actionsRightConstraint.priority = UILayoutPriorityDefaultHigh; |
| + |
| + // This constraint sets the top alignment for the action row. Its priority is |
| + // < UILayoutPriorityRequired so that it can break in favor of the |
| + // centerYAnchor rule (on the next line) when the copiedURL section is hidden. |
| + NSLayoutConstraint* actionsTopConstraint = [actionRow.topAnchor |
| + constraintEqualToAnchor:self.secondaryEffectView.topAnchor |
| + constant:kContentMargin]; |
| + actionsTopConstraint.priority = UILayoutPriorityDefaultHigh; |
| + |
| + self.hiddenCopiedURLConstraints = @[ [actionRow.centerYAnchor |
| + constraintEqualToAnchor:self.secondaryEffectView.centerYAnchor] ]; |
| + |
| + [constraintArray addObjectsFromArray:@[ |
| + [actionRow.centerXAnchor |
| + constraintEqualToAnchor:self.secondaryEffectView.centerXAnchor], |
| + [actionRow.widthAnchor constraintLessThanOrEqualToConstant:kMaxContentSize], |
| + actionsLeftConstraint, |
| + actionsRightConstraint, |
| + actionsTopConstraint, |
| + ]]; |
| + |
| + return actionRow; |
| +} |
| + |
| +- (UIView*)createActionView:(NSString*)title |
|
stkhapugin
2017/05/04 13:12:09
This name should be:
newActionViewWithTitle: imag
lody
2017/05/05 17:05:43
Done.
|
| + imageName:(NSString*)imageName |
| + actionSelector:(SEL)actionSelector |
| + constraintArray: |
| + (NSMutableArray<NSLayoutConstraint*>*)constraintArray { |
| + UIView* circleView = [[UIView alloc] initWithFrame:CGRectZero]; |
| + circleView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.05]; |
| + circleView.layer.cornerRadius = kActionButtonSize / 2; |
| + |
| + [constraintArray addObjectsFromArray:@[ |
| + [circleView.widthAnchor constraintEqualToConstant:kActionButtonSize], |
| + [circleView.heightAnchor constraintEqualToConstant:kActionButtonSize] |
| + ]]; |
| + |
| + UILabel* labelView = [[UILabel alloc] initWithFrame:CGRectZero]; |
| + labelView.text = title; |
|
stkhapugin
2017/05/04 13:12:09
l10n?
lody
2017/05/05 17:05:43
Acknowledged.
|
| + labelView.numberOfLines = 2; |
|
stkhapugin
2017/05/04 13:12:09
also l10n?
lody
2017/05/05 17:05:43
Acknowledged.
|
| + labelView.textAlignment = NSTextAlignmentCenter; |
| + labelView.font = [UIFont systemFontOfSize:UIFont.smallSystemFontSize]; |
|
stkhapugin
2017/05/04 13:12:09
Does this work with gigantic dynamic type?
lody
2017/05/05 17:05:43
whoops, used the wrong api. It looks good now, I t
|
| + [labelView |
| + setContentCompressionResistancePriority:UILayoutPriorityRequired |
| + forAxis:UILayoutConstraintAxisVertical]; |
| + |
| + UIStackView* stack = |
| + [[UIStackView alloc] initWithArrangedSubviews:@[ circleView, labelView ]]; |
| + stack.axis = UILayoutConstraintAxisVertical; |
| + stack.spacing = 5; |
|
stkhapugin
2017/05/04 13:12:09
make a constant
lody
2017/05/05 17:05:43
Done.
|
| + stack.translatesAutoresizingMaskIntoConstraints = NO; |
| + [self addTapAction:actionSelector toView:stack]; |
|
stkhapugin
2017/05/04 13:12:08
Create a transparent UIButton and constrain to |st
lody
2017/05/05 17:05:44
Done.
|
| + |
| + UIImage* iconImage = [UIImage imageNamed:imageName]; |
| + UIImageView* icon = [[UIImageView alloc] initWithImage:iconImage]; |
| + icon.translatesAutoresizingMaskIntoConstraints = NO; |
| + |
| + [constraintArray addObjectsFromArray:@[ |
| + [icon.widthAnchor constraintEqualToConstant:kIconSize], |
| + [icon.heightAnchor constraintEqualToConstant:kIconSize], |
| + [icon.centerXAnchor constraintEqualToAnchor:circleView.centerXAnchor], |
| + [icon.centerYAnchor constraintEqualToAnchor:circleView.centerYAnchor], |
| ]]; |
| + [self.primaryEffectView.contentView addSubview:icon]; |
| + |
| + return stack; |
| +} |
| + |
| +- (void)createOpenCopiedURLView:(NSLayoutAnchor*)topAnchor |
| + constraintArray: |
| + (NSMutableArray<NSLayoutConstraint*>*)constraintArray { |
| + self.hairlineView = [[UIView alloc] initWithFrame:CGRectZero]; |
| + self.hairlineView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.05]; |
| + self.hairlineView.translatesAutoresizingMaskIntoConstraints = NO; |
| + [self.secondaryEffectView.contentView addSubview:self.hairlineView]; |
| + |
| + self.copiedButtonView = [[UIView alloc] initWithFrame:CGRectZero]; |
|
stkhapugin
2017/05/04 13:12:08
Just make this a UIButton to avoid having a gestur
lody
2017/05/05 17:05:43
Done.
|
| + self.copiedButtonView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.05]; |
| + self.copiedButtonView.layer.cornerRadius = 5; |
| + self.copiedButtonView.translatesAutoresizingMaskIntoConstraints = NO; |
| + [self.secondaryEffectView.contentView addSubview:self.copiedButtonView]; |
| + [self addTapAction:@selector(openCopiedURL:) toView:self.copiedButtonView]; |
| + |
| + self.openCopiedURLTitleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; |
| + self.openCopiedURLTitleLabel.textAlignment = NSTextAlignmentCenter; |
| + self.openCopiedURLTitleLabel.translatesAutoresizingMaskIntoConstraints = NO; |
| + self.openCopiedURLTitleLabel.font = [UIFont boldSystemFontOfSize:16]; |
| + [self.primaryEffectView.contentView addSubview:self.openCopiedURLTitleLabel]; |
| + |
| + self.copiedURLLabel = [[UILabel alloc] initWithFrame:CGRectZero]; |
| + self.copiedURLLabel.textAlignment = NSTextAlignmentCenter; |
| + self.copiedURLLabel.font = |
| + [UIFont systemFontOfSize:UIFont.smallSystemFontSize]; |
| + self.copiedURLLabel.translatesAutoresizingMaskIntoConstraints = NO; |
| + [self.secondaryEffectView.contentView addSubview:self.copiedURLLabel]; |
| + |
| + // |
| + // NSLayoutConstraint* hairlineTopAnchor = |
|
stkhapugin
2017/05/04 13:12:09
remove
lody
2017/05/05 17:05:43
Done.
|
| + // ; |
| + // hairlineTopAnchor.priority = UILayoutPriorityDefaultHigh; |
| + |
| + self.visibleCopiedURLConstraints = @[ |
| + [self.hairlineView.topAnchor constraintEqualToAnchor:topAnchor |
| + constant:kContentMargin], |
| + [self.hairlineView.leftAnchor |
| + constraintEqualToAnchor:self.secondaryEffectView.leftAnchor], |
| + [self.hairlineView.rightAnchor |
| + constraintEqualToAnchor:self.secondaryEffectView.rightAnchor], |
| + [self.hairlineView.heightAnchor constraintEqualToConstant:0.5], |
| + |
| + [self.copiedButtonView.centerXAnchor |
| + constraintEqualToAnchor:self.secondaryEffectView.centerXAnchor], |
| + [self.copiedButtonView.widthAnchor |
| + constraintEqualToAnchor:self.secondaryEffectView.widthAnchor |
| + constant:-2 * kContentMargin], |
| + [self.copiedButtonView.topAnchor |
| + constraintEqualToAnchor:self.hairlineView.bottomAnchor |
| + constant:12], |
| + [self.copiedButtonView.bottomAnchor |
| + constraintEqualToAnchor:self.secondaryEffectView.bottomAnchor |
| + constant:-kContentMargin], |
| + |
| + [self.openCopiedURLTitleLabel.centerXAnchor |
| + constraintEqualToAnchor:self.primaryEffectView.centerXAnchor], |
| + [self.openCopiedURLTitleLabel.topAnchor |
| + constraintEqualToAnchor:self.copiedButtonView.topAnchor |
| + constant:kURLButtonMargin], |
| + [self.openCopiedURLTitleLabel.widthAnchor |
| + constraintEqualToAnchor:self.copiedButtonView.widthAnchor |
| + constant:-kContentMargin * 2], |
| - [UIView animateWithDuration:0.3 |
| - delay:0.0 |
| - options:UIViewAnimationOptionRepeat | |
| - UIViewAnimationOptionAutoreverse |
| - animations:^{ |
| - self.cursor.alpha = 0.0f; |
| - } |
| - completion:nil]; |
| + [self.copiedURLLabel.centerXAnchor |
| + constraintEqualToAnchor:self.primaryEffectView.centerXAnchor], |
| + [self.copiedURLLabel.topAnchor |
| + constraintEqualToAnchor:self.openCopiedURLTitleLabel.bottomAnchor], |
| + [self.copiedURLLabel.widthAnchor |
| + constraintEqualToAnchor:self.openCopiedURLTitleLabel.widthAnchor], |
| + [self.copiedURLLabel.bottomAnchor |
| + constraintEqualToAnchor:self.copiedButtonView.bottomAnchor |
| + constant:-kURLButtonMargin], |
| + ]; |
| +} |
| + |
| +- (void)addTapAction:(SEL)action toView:(UIView*)view { |
|
stkhapugin
2017/05/04 13:12:08
With two comments above, you'll no longer need thi
lody
2017/05/05 17:05:43
Done.
|
| + UIGestureRecognizer* tapRecognizer = |
| + [[UITapGestureRecognizer alloc] initWithTarget:_target action:action]; |
| + [view addGestureRecognizer:tapRecognizer]; |
| +} |
| + |
| +- (void)updateCopiedURLUI { |
| + // If the copiedURL section is not visible, hide all the copiedURL section |
|
stkhapugin
2017/05/04 13:12:09
All of this logic belongs to controller layer, not
lody
2017/05/05 17:05:43
As seen offline, this is tbd.
|
| + // views and activate the correct constraint set. If it is visible, show the |
| + // views in function of whether there is or not a copied URL to show. |
| + |
| + if (!self.copiedURLVisible) { |
| + self.copiedURLLabel.hidden = YES; |
| + self.openCopiedURLTitleLabel.hidden = YES; |
| + self.hairlineView.hidden = YES; |
| + self.copiedButtonView.hidden = YES; |
| + [NSLayoutConstraint deactivateConstraints:self.visibleCopiedURLConstraints]; |
| + [NSLayoutConstraint activateConstraints:self.hiddenCopiedURLConstraints]; |
| + return; |
| + } |
| + |
| + self.copiedURLLabel.hidden = NO; |
| + self.openCopiedURLTitleLabel.hidden = NO; |
| + |
| + [NSLayoutConstraint deactivateConstraints:self.hiddenCopiedURLConstraints]; |
| + [NSLayoutConstraint activateConstraints:self.visibleCopiedURLConstraints]; |
| + |
| + if (self.copiedURL) { |
| + self.copiedButtonView.hidden = NO; |
| + self.hairlineView.hidden = YES; |
| + self.copiedURLLabel.text = self.copiedURL; |
| + self.openCopiedURLTitleLabel.alpha = 1; |
| + self.openCopiedURLTitleLabel.text = @"Open Copied Link"; |
|
stkhapugin
2017/05/04 13:12:08
localization?
lody
2017/05/05 17:05:43
I knew something was missing from the list of "thi
|
| + self.copiedURLLabel.alpha = 1; |
| + return; |
| + } |
| + |
| + self.copiedButtonView.hidden = YES; |
| + self.hairlineView.hidden = NO; |
| + self.copiedURLLabel.text = @"Links you copy will appear here."; |
|
stkhapugin
2017/05/04 13:12:09
l10n?
lody
2017/05/05 17:05:43
Acknowledged.
|
| + self.openCopiedURLTitleLabel.alpha = 0.5; |
| + self.openCopiedURLTitleLabel.text = @"No Copied Link"; |
|
stkhapugin
2017/05/04 13:12:09
l10n
lody
2017/05/05 17:05:43
Acknowledged.
|
| + self.copiedURLLabel.alpha = 0.5; |
| } |
| - (void)updateCopiedURL:(NSString*)copiedURL { |
| self.copiedURL = copiedURL; |
| - self.copiedURLLabel.text = copiedURL; |
| + [self updateCopiedURLUI]; |
| } |
| - |
| @end |