From 670f7447ce081f6d050439102eb1e92a8241f68c Mon Sep 17 00:00:00 2001 From: Alexander Boriskov Date: Fri, 11 Oct 2019 18:11:46 +0300 Subject: [PATCH] [iOS] Sightseeing subscription screen https://jira.mail.ru/browse/MAPSME-12085 --- .../Catalog/BookmarksSubscriptionButton.swift | 41 ++ ...kmarksSubscriptionCellViewController.swift | 90 ---- ...ookmarksSubscriptionCellViewController.xib | 149 ------- .../BookmarksSubscriptionViewController.swift | 126 +++--- .../BookmarksSubscriptionViewController.xib | 386 ++++++++++++------ ...marksSubscriptionSuccessViewController.xib | 11 +- .../Catalog/PaidRouteViewController.swift | 2 +- iphone/Maps/Categories/UIColor+MapsMeColor.h | 4 + iphone/Maps/Categories/UIColor+MapsMeColor.mm | 32 +- iphone/Maps/Categories/UIFont+MapsMeFonts.h | 1 + iphone/Maps/Categories/UIFont+MapsMeFonts.mm | 1 + .../Categories/UIView+RuntimeAttributes.m | 4 + .../Core/InappPurchase/InAppPurchase.swift | 4 +- .../Subscriptions/SubscriptionManager.swift | 18 +- .../Combined Shape.png | Bin 0 -> 309 bytes .../Combined Shape@2x.png | Bin 0 -> 535 bytes .../Combined Shape@3x.png | Bin 0 -> 746 bytes .../Contents.json | 23 ++ .../Contents.json | 23 ++ .../Mask Group.png | Bin 0 -> 22841 bytes .../Mask Group@2x.png | Bin 0 -> 52408 bytes .../Mask Group@3x.png | Bin 0 -> 88420 bytes .../Contents.json | 23 ++ .../Group 9.png | Bin 0 -> 45981 bytes .../Group 9@2x.png | Bin 0 -> 117536 bytes .../Group 9@3x.png | Bin 0 -> 191347 bytes iphone/Maps/Maps.xcodeproj/project.pbxproj | 12 +- 27 files changed, 487 insertions(+), 463 deletions(-) create mode 100644 iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionButton.swift delete mode 100644 iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionCellViewController.swift delete mode 100644 iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionCellViewController.xib create mode 100644 iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionBullet.imageset/Combined Shape.png create mode 100644 iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionBullet.imageset/Combined Shape@2x.png create mode 100644 iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionBullet.imageset/Combined Shape@3x.png create mode 100644 iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionBullet.imageset/Contents.json create mode 100644 iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionFooter.imageset/Contents.json create mode 100644 iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionFooter.imageset/Mask Group.png create mode 100644 iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionFooter.imageset/Mask Group@2x.png create mode 100644 iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionFooter.imageset/Mask Group@3x.png create mode 100644 iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionHeader.imageset/Contents.json create mode 100644 iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionHeader.imageset/Group 9.png create mode 100644 iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionHeader.imageset/Group 9@2x.png create mode 100644 iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionHeader.imageset/Group 9@3x.png diff --git a/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionButton.swift b/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionButton.swift new file mode 100644 index 0000000000..17b576a19c --- /dev/null +++ b/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionButton.swift @@ -0,0 +1,41 @@ +import UIKit + +class BookmarksSubscriptionButton: UIButton { + private let descriptionLabel = UILabel() + private let priceLabel = UILabel() + + override func awakeFromNib() { + addSubview(descriptionLabel) + addSubview(priceLabel) + + descriptionLabel.translatesAutoresizingMaskIntoConstraints = false + priceLabel.translatesAutoresizingMaskIntoConstraints = false + + priceLabel.font = UIFont.semibold16() + priceLabel.textAlignment = .right; + descriptionLabel.font = UIFont.semibold16() + + descriptionLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true + descriptionLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 16).isActive = true + priceLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true + priceLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -16).isActive = true + + setTitle("", for: .normal) + } + + override func setTitleColor(_ color: UIColor?, for state: UIControlState) { + super.setTitleColor(color, for: state) + descriptionLabel.textColor = color + priceLabel.textColor = color + } + + override func setTitle(_ title: String?, for state: UIControlState) { + super.setTitle("", for: state); + } + + func config(title: String, price: String, enabled: Bool) { + descriptionLabel.text = title + priceLabel.text = price + self.isEnabled = enabled + } +} diff --git a/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionCellViewController.swift b/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionCellViewController.swift deleted file mode 100644 index 7e3a91f8b1..0000000000 --- a/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionCellViewController.swift +++ /dev/null @@ -1,90 +0,0 @@ -class BookmarksSubscriptionCellViewController: UIViewController { - @IBOutlet private var subtitleLabel: UILabel! - @IBOutlet private var titleLabel: UILabel! - @IBOutlet private var priceLabel: UILabel! - @IBOutlet private var discountView: UIView! - @IBOutlet private var discountLabel: UILabel! - @IBOutlet private var imageView: UIImageView! - @IBOutlet private var containerView: UIView! - @IBOutlet private var contentView: UIView! - - private(set) var isSelected = false - - override func viewDidLoad() { - super.viewDidLoad() - if !UIColor.isNightMode() { - setupShadow(containerView, color: .shadowColorBlue()) - setupShadow(discountView, color: .shadowColorPurple()) - } - contentView.layer.borderColor = UIColor.subscriptionCellBorder().cgColor - setSelected(false, animated: false) - } - - func setSelected(_ selected: Bool, animated: Bool = false) { - isSelected = selected - let setSelectedClosure = { [unowned self] in - self.titleLabel.textColor = selected ? .subscriptionCellTitle() : .blackSecondaryText() - self.subtitleLabel.textColor = selected ? .linkBlue() : .blackSecondaryText() - self.priceLabel.textColor = selected ? .subscriptionCellTitle() : .blackSecondaryText() - self.contentView.backgroundColor = selected ? .subscriptionCellBackground() : .clear - self.containerView.backgroundColor = selected ? .white() : .clear - } - - if animated { - UIView.animate(withDuration: kDefaultAnimationDuration) { - setSelectedClosure() - } - animateBorder(contentView, show: !selected) - if !UIColor.isNightMode() { - animateShadow(containerView, opacity: selected ? 0.5 : 0) - animateShadow(discountView, opacity: selected ? 0.62 : 0) - } - } else { - setSelectedClosure() - contentView.layer.borderWidth = selected ? 0 : 1 - if !UIColor.isNightMode() { - containerView.layer.shadowOpacity = selected ? 0.5 : 0 - discountView.layer.shadowOpacity = selected ? 0.62 : 0 - } - } - } - - func config(title: String, subtitle: String, price: String, image: UIImage, discount: String? = nil) { - titleLabel.text = title - subtitleLabel.text = subtitle - priceLabel.text = price - imageView.image = image - - guard let discount = discount else { - discountView.isHidden = true - return - } - - discountLabel.text = discount - discountView.isHidden = false - } - - private func setupShadow(_ view: UIView, color: UIColor) { - view.layer.shadowRadius = 4 - view.layer.shadowOffset = CGSize(width: 0, height: 2) - view.layer.shadowColor = color.cgColor - } - - private func animateShadow(_ view: UIView, opacity: Float) { - let shadowOpacityKey = "shadowOpacity" - let animation = CABasicAnimation(keyPath: shadowOpacityKey) - animation.fromValue = view.layer.shadowOpacity - animation.duration = kDefaultAnimationDuration - view.layer.add(animation, forKey: shadowOpacityKey) - view.layer.shadowOpacity = opacity - } - - private func animateBorder(_ view: UIView, show: Bool) { - let borderWidthKey = "borderWidth" - let animation = CABasicAnimation(keyPath: borderWidthKey) - animation.fromValue = view.layer.borderWidth - animation.duration = kDefaultAnimationDuration - view.layer.add(animation, forKey: borderWidthKey) - view.layer.borderWidth = show ? 1 : 0 - } -} diff --git a/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionCellViewController.xib b/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionCellViewController.xib deleted file mode 100644 index f108d7c90a..0000000000 --- a/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionCellViewController.xib +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionViewController.swift b/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionViewController.swift index 65170314a1..aa3378ba02 100644 --- a/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionViewController.swift +++ b/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionViewController.swift @@ -1,19 +1,21 @@ import SafariServices @objc class BookmarksSubscriptionViewController: MWMViewController { - @IBOutlet private var annualView: UIView! - @IBOutlet private var monthlyView: UIView! - @IBOutlet private var gradientView: GradientView! - @IBOutlet private var scrollView: UIScrollView! - @IBOutlet private var continueButton: UIButton! - @IBOutlet var loadingView: UIView! - - private let annualViewController = BookmarksSubscriptionCellViewController() - private let monthlyViewController = BookmarksSubscriptionCellViewController() + //MARK: outlets + @IBOutlet private var annualSubscriptionButton: BookmarksSubscriptionButton! + @IBOutlet private var annualDiscountView: UIView! + @IBOutlet private var annualDiscountLabel: UILabel! + @IBOutlet private var monthlySubscriptionButton: BookmarksSubscriptionButton! + @IBOutlet private var loadingView: UIView! + + //MARK: locals private var priceFormatter: NumberFormatter? private var monthlySubscription: ISubscription? private var annualSubscription: ISubscription? - private var selectedSubscription: ISubscription? + + //MARK: dependency + private let subscriptionManager: ISubscriptionManager = InAppPurchase.bookmarksSubscriptionManager + private let bookmarksManager: MWMBookmarksManager = MWMBookmarksManager.shared() @objc var onSubscribe: MWMVoidBlock? @objc var onCancel: MWMVoidBlock? @@ -29,7 +31,7 @@ import SafariServices override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) - InAppPurchase.bookmarksSubscriptionManager.addListener(self) + subscriptionManager.addListener(self) } required init?(coder aDecoder: NSCoder) { @@ -37,53 +39,40 @@ import SafariServices } deinit { - InAppPurchase.bookmarksSubscriptionManager.removeListener(self) + subscriptionManager.removeListener(self) } override func viewDidLoad() { super.viewDidLoad() - gradientView.isHidden = UIColor.isNightMode() - - addChildViewController(annualViewController) - annualView.addSubview(annualViewController.view) - annualViewController.view.alignToSuperview() - annualViewController.didMove(toParentViewController: self) - - addChildViewController(monthlyViewController) - monthlyView.addSubview(monthlyViewController.view) - monthlyViewController.view.alignToSuperview() - monthlyViewController.didMove(toParentViewController: self) - - annualViewController.config(title: L("annual_subscription_title"), - subtitle: L("annual_subscription_message"), - price: "...", - image: UIImage(named: "bookmarksSubscriptionYear")!, - discount: "...") - monthlyViewController.config(title: L("montly_subscription_title"), - subtitle: L("montly_subscription_message"), - price: "...", - image: UIImage(named: "bookmarksSubscriptionMonth")!) - annualViewController.setSelected(true, animated: false) - continueButton.setTitle(L("current_location_unknown_continue_button").uppercased(), for: .normal) - continueButton.isEnabled = false - scrollView.isUserInteractionEnabled = false - + annualSubscriptionButton.config(title: L("annual_subscription_title"), + price: "...", + enabled: false) + monthlySubscriptionButton.config(title: L("montly_subscription_title"), + price: "...", + enabled: false) + + if !UIColor.isNightMode() { + annualDiscountView.layer.shadowRadius = 4 + annualDiscountView.layer.shadowOffset = CGSize(width: 0, height: 2) + annualDiscountView.layer.shadowColor = UIColor.blackHintText().cgColor + annualDiscountView.layer.shadowOpacity = 0.62 + } + annualDiscountView.isHidden = true + Statistics.logEvent(kStatInappShow, withParameters: [kStatVendor: MWMPurchaseManager.bookmarksSubscriptionVendorId(), kStatPurchase: MWMPurchaseManager.bookmarksSubscriptionServerId(), kStatProduct: BOOKMARKS_SUBSCRIPTION_YEARLY_PRODUCT_ID, kStatFrom: source], with: .realtime) - InAppPurchase.bookmarksSubscriptionManager.getAvailableSubscriptions { [weak self] (subscriptions, error) in + subscriptionManager.getAvailableSubscriptions { [weak self] (subscriptions, error) in guard let subscriptions = subscriptions, subscriptions.count == 2 else { MWMAlertViewController.activeAlert().presentInfoAlert(L("price_error_title"), text: L("price_error_subtitle")) self?.onCancel?() return } - self?.monthlySubscription = subscriptions[0] self?.annualSubscription = subscriptions[1] - self?.selectedSubscription = self?.annualSubscription let s = subscriptions[0] let formatter = NumberFormatter() @@ -96,49 +85,30 @@ import SafariServices let twelveMonthPrice = monthlyPrice.multiplying(by: 12) let discount = twelveMonthPrice.subtracting(annualPrice).dividing(by: twelveMonthPrice).multiplying(by: 100) - self?.monthlyViewController.config(title: L("montly_subscription_title"), - subtitle: L("montly_subscription_message"), - price: formatter.string(from: monthlyPrice) ?? "", - image: UIImage(named: "bookmarksSubscriptionMonth")!) - self?.annualViewController.config(title: L("annual_subscription_title"), - subtitle: L("annual_subscription_message"), - price: formatter.string(from: annualPrice) ?? "", - image: UIImage(named: "bookmarksSubscriptionYear")!, - discount: "- \(discount.rounding(accordingToBehavior: nil).intValue) %") - self?.continueButton.isEnabled = true - self?.scrollView.isUserInteractionEnabled = true + self?.annualSubscriptionButton.config(title: L("annual_subscription_title"), + price: formatter.string(from: annualPrice) ?? "", + enabled: true) + self?.monthlySubscriptionButton.config(title: L("montly_subscription_title"), + price: formatter.string(from: monthlyPrice) ?? "", + enabled: true) + self?.annualDiscountView.isHidden = false + self?.annualDiscountLabel.text = "- \(discount.rounding(accordingToBehavior: nil).intValue) %" } } - @IBAction func onAnnualViewTap(_ sender: UITapGestureRecognizer) { - guard !annualViewController.isSelected else { - return - } - selectedSubscription = annualSubscription - annualViewController.setSelected(true, animated: true) - monthlyViewController.setSelected(false, animated: true) - scrollView.scrollRectToVisible(annualView.convert(annualView.bounds, to: scrollView), animated: true) - Statistics.logEvent(kStatInappSelect, withParameters: [kStatProduct: selectedSubscription!.productId, - kStatPurchase: MWMPurchaseManager.bookmarksSubscriptionServerId()]) + @IBAction func onAnnualButtonTap(_ sender: UIButton) { + purchase(sender: sender, subscription: annualSubscription) } - @IBAction func onMonthlyViewTap(_ sender: UITapGestureRecognizer) { - guard !monthlyViewController.isSelected else { - return - } - selectedSubscription = monthlySubscription - annualViewController.setSelected(false, animated: true) - monthlyViewController.setSelected(true, animated: true) - scrollView.scrollRectToVisible(monthlyView.convert(monthlyView.bounds, to: scrollView), animated: true) - Statistics.logEvent(kStatInappSelect, withParameters: [kStatProduct: selectedSubscription!.productId, - kStatPurchase: MWMPurchaseManager.bookmarksSubscriptionServerId()]) + @IBAction func onMonthlyButtonTap(_ sender: UIButton) { + purchase(sender: sender, subscription: monthlySubscription) } - @IBAction func onContinue(_ sender: UIButton) { + private func purchase(sender: UIButton, subscription: ISubscription?) { signup(anchor: sender) { [weak self] success in guard success else { return } self?.loadingView.isHidden = false - MWMBookmarksManager.shared().ping { success in + self?.bookmarksManager.ping { success in guard success else { self?.loadingView.isHidden = true let errorDialog = BookmarksSubscriptionFailViewController { [weak self] in @@ -148,11 +118,11 @@ import SafariServices return } - guard let subscription = self?.selectedSubscription else { + guard let subscription = subscription else { return } - InAppPurchase.bookmarksSubscriptionManager.subscribe(to: subscription) + self?.subscriptionManager.subscribe(to: subscription) } } Statistics.logEvent(kStatInappPay, withParameters: [kStatPurchase: MWMPurchaseManager.bookmarksSubscriptionServerId()], @@ -164,7 +134,7 @@ import SafariServices signup(anchor: sender) { [weak self] (success) in guard success else { return } self?.loadingView.isHidden = false - InAppPurchase.bookmarksSubscriptionManager.restore { result in + self?.subscriptionManager.restore { result in self?.loadingView.isHidden = true let alertText: String switch result { @@ -223,7 +193,7 @@ extension BookmarksSubscriptionViewController: SubscriptionManagerListener { func didSubscribe(_ subscription: ISubscription) { MWMPurchaseManager.setBookmarksSubscriptionActive(true) - MWMBookmarksManager.shared().resetInvalidCategories() + bookmarksManager.resetInvalidCategories() } func didDefer(_ subscription: ISubscription) { diff --git a/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionViewController.xib b/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionViewController.xib index ef4657e304..efc01f386e 100644 --- a/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionViewController.xib +++ b/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionViewController.xib @@ -1,23 +1,20 @@ - - - - + + - + - - - + + + - - + @@ -26,122 +23,237 @@ - + - - - - - - - - - - - - + - + + + + + + + - + + + + + - - - - - - - - - - + - - - - + + + + + + + + + + + + + +