Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Talk pages - banner design review feedback #4384

Merged
merged 6 commits into from
Nov 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions Wikipedia/Code/TalkPageViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ class TalkPageViewController: ViewController {
if UIAccessibility.isVoiceOverRunning {
UIAccessibility.post(notification: UIAccessibility.Notification.announcement, argument: title)
} else {
WMFAlertManager.sharedInstance.showBottomAlertWithMessage(title, subtitle: subtitle, image: image, type: .normal, customTypeName: nil, dismissPreviousAlerts: true)
WMFAlertManager.sharedInstance.showBottomAlertWithMessage(title, subtitle: subtitle, image: image, type: .custom, customTypeName: "subscription-success", dismissPreviousAlerts: true)
}
}

Expand All @@ -492,7 +492,7 @@ class TalkPageViewController: ViewController {
if UIAccessibility.isVoiceOverRunning {
UIAccessibility.post(notification: UIAccessibility.Notification.announcement, argument: title)
} else {
WMFAlertManager.sharedInstance.showBottomAlertWithMessage(title, subtitle: nil, image: UIImage(systemName: "exclamationmark.circle"), type: .custom, customTypeName: "subscription", dismissPreviousAlerts: true)
WMFAlertManager.sharedInstance.showBottomAlertWithMessage(title, subtitle: nil, image: UIImage(systemName: "exclamationmark.circle"), type: .custom, customTypeName: "subscription-error", dismissPreviousAlerts: true)
}
}

Expand Down
4 changes: 3 additions & 1 deletion Wikipedia/Code/WMFAlertManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,14 @@ open class WMFAlertManager: NSObject, RMessageProtocol, Themeable {
if messageView.customTypeName == "connection" {
messageView.imageViewTintColor = theme.colors.error
messageView.buttonFont = UIFont.systemFont(ofSize: 14, weight: .semibold)
} else if messageView.customTypeName == "subscription" {
} else if messageView.customTypeName == "subscription-error" {
messageView.imageViewTintColor = theme.colors.warning
}
default:
messageView.titleTextColor = theme.colors.link
}

messageView.layer.shadowColor = theme.colors.shadow.cgColor
}

}
11 changes: 10 additions & 1 deletion Wikipedia/Third Party Code/RMessage/RMessageDefaultDesign.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,16 @@
"subTitleTextColor": "#222222",
"blurBackground": 0
},
"subscription": {
"subscription-success": {
"backgroundColor": "#F8F9FA",
"backgroundColorAlpha": 1.0,
"titleTextColor": "#222222",
"titleFontSize": 14,
"subTitleFontSize": 12,
"subTitleTextColor": "#222222",
"blurBackground": 0
},
"subscription-error": {
"backgroundColor": "#F8F9FA",
"backgroundColorAlpha": 1.0,
"titleTextColor": "#222222",
Expand Down
178 changes: 52 additions & 126 deletions Wikipedia/Third Party Code/RMessage/RMessageView.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ @interface RMessageView () <UIGestureRecognizerDelegate>
@property (nonatomic, weak) IBOutlet UIButton *button;
@property (nonatomic, weak) IBOutlet UIStackView *stackView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *titleSubtitleContainerViewLeadingConstraint;
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *titleSubtitleContainerViewCenterYConstraint;
@property (weak, nonatomic) IBOutlet UIImageView *closeImageView;

@property (nonatomic, strong) UIImageView *iconImageView;
Expand All @@ -53,19 +52,16 @@ @interface RMessageView () <UIGestureRecognizerDelegate>
/** The view controller this message is displayed in */
@property (nonatomic, strong) UIViewController *viewController;

/** The vertical space between the message view top to its view controller top */
@property (nonatomic, strong) NSLayoutConstraint *topToVCLayoutConstraint;
/** Activated for top banners only, this is the constraint that pins a banner to the top safe area */
@property (nonatomic, strong) NSLayoutConstraint *topToVCTopLayoutConstraint;

/** Activated for bottom banners only, this is the constraint that pins a banner to the bottom safe area */
@property (nonatomic, strong) NSLayoutConstraint *bottomToVCBottomLayoutConstraint;

@property (nonatomic, copy) void (^callback)(void);

@property (nonatomic, copy) void (^buttonCallback)(void);

/** The starting constant value that should be set for the topToVCTopLayoutConstraint when animating */
@property (nonatomic, assign) CGFloat topToVCStartConstant;

/** The final constant value that should be set for the topToVCTopLayoutConstraint when animating */
@property (nonatomic, assign) CGFloat topToVCFinalConstant;

@property (nonatomic, assign) CGFloat iconRelativeCornerRadius;
@property (nonatomic, assign) RMessageType messageType;
@property (nonatomic, copy) NSString *customTypeName;
Expand Down Expand Up @@ -139,7 +135,6 @@ + (UIViewController *)defaultViewController
}
UIViewController *presentedViewController = nil;
do {

if (![viewController.presentedViewController conformsToProtocol:@protocol(RMessageSuppressProtocol)]) {
presentedViewController = viewController.presentedViewController;
} else {
Expand All @@ -153,7 +148,12 @@ + (UIViewController *)defaultViewController
viewController = presentedViewController;
}
} while (presentedViewController != nil);
return viewController;

if ([viewController isKindOfClass:[UINavigationController class]]) {
return ((UINavigationController *)viewController).viewControllers.lastObject;
} else {
return viewController;
}
}

/**
Expand Down Expand Up @@ -437,45 +437,44 @@ - (void)setupDesign
[self setupTitleLabel];
[self setupSubTitleLabel];
[self setupButton];

if (self.messagePosition != RMessagePositionBottom) {
self.layer.shadowOffset = CGSizeMake(0, 2);
} else {
self.layer.shadowOffset = CGSizeMake(0, -2);
}
self.layer.shadowRadius = 5;
self.layer.shadowOpacity = 1.0;

self.clipsToBounds = NO;
}

- (void)setupLayout
{
self.translatesAutoresizingMaskIntoConstraints = NO;

// Add RMessage to superview and prepare the ending y position constants
[self layoutMessageForPresentation];
[self setupLabelPreferredMaxLayoutWidth];
// Add RMessage to superview
[self addToSuperviewForPresentation];

// Prepare the starting y position constants
if (self.messagePosition != RMessagePositionBottom) {
[self layoutIfNeeded];
self.topToVCStartConstant = -self.bounds.size.height;
self.topToVCLayoutConstraint = [NSLayoutConstraint constraintWithItem:self
self.topToVCTopLayoutConstraint = [NSLayoutConstraint constraintWithItem:self.superview
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.superview
toItem:self
attribute:NSLayoutAttributeTop
multiplier:1.f
constant:self.topToVCStartConstant];
constant:0.f];
} else {
self.topToVCStartConstant = 0;
self.topToVCLayoutConstraint = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeTop
self.bottomToVCBottomLayoutConstraint = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.superview.safeAreaLayoutGuide
toItem:self.superview
attribute:NSLayoutAttributeBottom
multiplier:1.f
constant:0.f];
}

NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.superview
attribute:NSLayoutAttributeCenterX
multiplier:1.f
constant:0.f];
NSLayoutConstraint *leadingConstraint = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
Expand All @@ -489,11 +488,20 @@ - (void)setupLayout
toItem:self.superview
attribute:NSLayoutAttributeTrailing
multiplier:1.f

constant:0.f];
[[self class]
activateConstraints:@[centerXConstraint, leadingConstraint, trailingConstraint, self.topToVCLayoutConstraint]
inSuperview:self.superview];
if (self.messagePosition != RMessagePositionBottom) {
[[self class] activateConstraints:@[leadingConstraint, trailingConstraint, self.topToVCTopLayoutConstraint] inSuperview:self];
} else {
[[self class] activateConstraints:@[leadingConstraint, trailingConstraint, self.bottomToVCBottomLayoutConstraint] inSuperview:self];
}
if (self.shouldBlurBackground) [self setupBlurBackground];

// Initially set it off screen
[self setNeedsLayout];
[self layoutIfNeeded];
self.topToVCTopLayoutConstraint.constant = self.bounds.size.height - [self customVerticalOffset];
self.bottomToVCBottomLayoutConstraint.constant = self.bounds.size.height - [self customVerticalOffset];
}

- (void)setupBackgroundImageViewWithImage:(UIImage *)image
Expand Down Expand Up @@ -540,14 +548,6 @@ - (void)setupBlurBackground
[[self class] activateConstraints:vConstraints inSuperview:self];
}

- (void)setupLabelPreferredMaxLayoutWidth
{
CGFloat iconImageWidthAndPadding = 0.f;
if (_iconImage) iconImageWidthAndPadding = _iconImage.size.width + 15.f;
_titleLabel.preferredMaxLayoutWidth = self.superview.bounds.size.width - iconImageWidthAndPadding - 30.f;
_subtitleLabel.preferredMaxLayoutWidth = _titleLabel.preferredMaxLayoutWidth;
}

- (void)executeMessageViewCallBack
{
if (self.callback) self.callback();
Expand All @@ -574,6 +574,7 @@ - (void)layoutSubviews
if (self.iconRelativeCornerRadius > 0) {
self.iconImageView.layer.cornerRadius = self.iconRelativeCornerRadius * self.iconImageView.bounds.size.width;
}
[self setPositioningConstraintsAndLayout];
}

- (void)setupDesignDefaults
Expand Down Expand Up @@ -847,85 +848,9 @@ - (void)present
}
}

- (void)layoutMessageForPresentation
- (void)addToSuperviewForPresentation
{
if ([self.viewController isKindOfClass:[UINavigationController class]] ||
[self.viewController.parentViewController isKindOfClass:[UINavigationController class]]) {
[self layoutMessageForNavigationControllerPresentation];
} else {
[self layoutMessageForStandardPresentation];
}
}

- (void)layoutMessageForNavigationControllerPresentation
{
self.titleSubtitleContainerViewCenterYConstraint.constant = 0.f;

UINavigationController *messageNavigationController;

if ([self.viewController isKindOfClass:[UINavigationController class]]) {
messageNavigationController = (UINavigationController *)self.viewController;
} else {
messageNavigationController = (UINavigationController *)self.viewController.parentViewController;
}

BOOL messageNavigationBarHidden =
[RMessageView isNavigationBarHiddenForNavigationController:messageNavigationController];

if (self.messagePosition != RMessagePositionBottom) {
if (!messageNavigationBarHidden && self.messagePosition == RMessagePositionTop) {
// Present from below nav bar when presenting from the top and navigation bar is present

if ([messageNavigationController isKindOfClass:[UINavigationController class]] && [messageNavigationController.topViewController isKindOfClass:[TalkPageTopicComposeViewController class]]) {
[messageNavigationController.view insertSubview:self aboveSubview:messageNavigationController.navigationBar];
self.topToVCFinalConstant = [self customVerticalOffset];
return;
}

[messageNavigationController.view insertSubview:self belowSubview:messageNavigationController.navigationBar];

/* If view controller edges dont extend under top bars (navigation bar in our case) we must not factor in the
navigation bar frame when animating RMessage's final position */
if ([[self class] viewControllerEdgesExtendUnderTopBars:messageNavigationController]) {
self.topToVCFinalConstant = [UIApplication sharedApplication].statusBarFrame.size.height +
messageNavigationController.navigationBar.bounds.size.height +
[self customVerticalOffset];
} else {
self.topToVCFinalConstant = [self customVerticalOffset];
}

} else {
/* Navigation bar hidden or being asked to present as nav bar overlay, so present above status bar and/or
navigation bar */
self.topToVCFinalConstant = [self customVerticalOffset];
self.titleSubtitleContainerViewCenterYConstraint.constant =
[UIApplication sharedApplication].statusBarFrame.size.height / 2.f;
[self.viewController.view addSubview:self];
}
} else {
// Present from bottom
[self layoutIfNeeded];
CGFloat offset = -self.bounds.size.height - [self customVerticalOffset];
if (messageNavigationController && !messageNavigationController.isToolbarHidden) {
// If tool bar present animate above toolbar
offset -= messageNavigationController.toolbar.bounds.size.height;
}
self.topToVCFinalConstant = offset;
[self.viewController.view addSubview:self];
}
}

- (void)layoutMessageForStandardPresentation
{
[self layoutIfNeeded];
if (self.messagePosition == RMessagePositionBottom) {
self.topToVCFinalConstant = -self.bounds.size.height - [self customVerticalOffset];
} else {
self.topToVCFinalConstant = [self customVerticalOffset];
self.titleSubtitleContainerViewCenterYConstraint.constant =
[UIApplication sharedApplication].statusBarFrame.size.height / 2.f;
}
[self.viewController.view addSubview:self];
}

- (void)animateMessage
Expand All @@ -945,8 +870,7 @@ - (void)animateMessage
[self.delegate messageViewIsPresenting:self];
}
if (!self.shouldBlurBackground) self.alpha = self.messageOpacity;
self.topToVCLayoutConstraint.constant = self.topToVCFinalConstant;
[self.superview layoutIfNeeded];
[self setPositioningConstraintsAndLayout];
}
completion:^(BOOL finished) {
self.isPresenting = NO;
Expand All @@ -958,6 +882,12 @@ - (void)animateMessage
});
}

- (void)setPositioningConstraintsAndLayout {
self.topToVCTopLayoutConstraint.constant = 0 + [self customVerticalOffset];
self.bottomToVCBottomLayoutConstraint.constant = 0 + [self customVerticalOffset];
[self.superview layoutIfNeeded];
}

- (void)dismiss
{
[self dismissWithCompletion:nil];
Expand All @@ -972,7 +902,8 @@ - (void)dismissWithCompletion:(void (^)(void))completionBlock
[UIView animateWithDuration:kRMessageAnimationDuration
animations:^{
if (!self.shouldBlurBackground) self.alpha = 0.f;
self.topToVCLayoutConstraint.constant = self.topToVCStartConstant;
self.topToVCTopLayoutConstraint.constant = self.bounds.size.height - [self customVerticalOffset];
self.bottomToVCBottomLayoutConstraint.constant = self.bounds.size.height - [self customVerticalOffset];
[self.superview layoutIfNeeded];
}
completion:^(BOOL finished) {
Expand All @@ -990,11 +921,6 @@ - (void)dismissWithCompletion:(void (^)(void))completionBlock
- (void)interfaceDidRotate
{
if (self.isPresenting) [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(dismiss) object:self];

// On completion of UI rotation recalculate positioning
[self layoutMessageForPresentation];
[self setupLabelPreferredMaxLayoutWidth];
self.topToVCLayoutConstraint.constant = self.topToVCFinalConstant;
}

/**
Expand Down