diff --git a/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionCellViewController.swift b/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionCellViewController.swift new file mode 100644 index 0000000000..c7c6bd6b06 --- /dev/null +++ b/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionCellViewController.swift @@ -0,0 +1,90 @@ +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 ? .linkBlue() : .blackPrimaryText() + self.subtitleLabel.textColor = selected ? .linkBlue() : .blackSecondaryText() + self.priceLabel.textColor = selected ? .linkBlue() : .blackPrimaryText() + self.contentView.backgroundColor = selected ? .linkBlueHighlighted() : .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 new file mode 100644 index 0000000000..37c7629c52 --- /dev/null +++ b/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionCellViewController.xib @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionViewController.swift b/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionViewController.swift new file mode 100644 index 0000000000..cf2e0a3c04 --- /dev/null +++ b/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionViewController.swift @@ -0,0 +1,73 @@ +class BookmarksSubscriptionViewController: MWMViewController { + @IBOutlet private var annualView: UIView! + @IBOutlet private var monthlyView: UIView! + @IBOutlet private var gradientView: GradientView! + @IBOutlet var scrollView: UIScrollView! + + private let annualViewController = BookmarksSubscriptionCellViewController() + private let monthlyViewController = BookmarksSubscriptionCellViewController() + + var onSubscribe: MWMVoidBlock? + var onCancel: MWMVoidBlock? + + override var supportedInterfaceOrientations: UIInterfaceOrientationMask { + get { return [.portrait] } + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + get { return UIColor.isNightMode() ? .lightContent : .default } + } + + 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: "$29.99", + image: UIImage(named: "bookmarksSubscriptionYear")!, + discount: "SAVE $38") + monthlyViewController.config(title: L("montly_subscription_title"), + subtitle: L("montly_subscription_message"), + price: "$3.99", + image: UIImage(named: "bookmarksSubscriptionMonth")!) + annualViewController.setSelected(true, animated: false) + } + + @IBAction func onAnnualViewTap(_ sender: UITapGestureRecognizer) { + guard !annualViewController.isSelected else { + return + } + annualViewController.setSelected(true, animated: true) + monthlyViewController.setSelected(false, animated: true) + scrollView.scrollRectToVisible(annualView.convert(annualView.bounds, to: scrollView), animated: true) + } + + @IBAction func onMonthlyViewTap(_ sender: UITapGestureRecognizer) { + guard !monthlyViewController.isSelected else { + return + } + annualViewController.setSelected(false, animated: true) + monthlyViewController.setSelected(true, animated: true) + scrollView.scrollRectToVisible(monthlyView.convert(monthlyView.bounds, to: scrollView), animated: true) + } + + @IBAction func onContinue(_ sender: UIButton) { + onSubscribe?() + } + + @IBAction func onClose(_ sender: UIButton) { + onCancel?() + } +} diff --git a/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionViewController.xib b/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionViewController.xib new file mode 100644 index 0000000000..7ef1867936 --- /dev/null +++ b/iphone/Maps/Bookmarks/Catalog/BookmarksSubscriptionViewController.xib @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iphone/Maps/Bookmarks/Catalog/CatalogWebViewController.swift b/iphone/Maps/Bookmarks/Catalog/CatalogWebViewController.swift index a75cfce133..3d8ea876bc 100644 --- a/iphone/Maps/Bookmarks/Catalog/CatalogWebViewController.swift +++ b/iphone/Maps/Bookmarks/Catalog/CatalogWebViewController.swift @@ -146,12 +146,19 @@ final class CatalogWebViewController: WebViewController { override func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { + let subscribePath = "/mobilefront/subscribe" guard let url = navigationAction.request.url, - url.scheme == "mapsme" || url.path == "/mobilefront/buy_kml" else { + url.scheme == "mapsme" || url.path == "/mobilefront/buy_kml" || url.path == subscribePath else { super.webView(webView, decidePolicyFor: navigationAction, decisionHandler: decisionHandler) return } + if url.path == subscribePath { + showSubscribe() + decisionHandler(.cancel); + return + } + processDeeplink(url) decisionHandler(.cancel); } @@ -180,6 +187,18 @@ final class CatalogWebViewController: WebViewController { loadingIndicator.stopAnimating() } + private func showSubscribe() { + let subscribeViewController = BookmarksSubscriptionViewController() + subscribeViewController.onSubscribe = { [weak self] in + self?.dismiss(animated: true) + } + subscribeViewController.onCancel = { [weak self] in + self?.dismiss(animated: true) + } + + present(subscribeViewController, animated: true) + } + private func buildHeaders(completion: @escaping ([String : String]?) -> Void) { billing.requestProducts(Set(MWMPurchaseManager.bookmarkInappIds()), completion: { (products, error) in var productsInfo: [String : [String: String]] = [:] diff --git a/iphone/Maps/Categories/UIColor+MapsMeColor.h b/iphone/Maps/Categories/UIColor+MapsMeColor.h index aec24dcf99..d53ed3629c 100644 --- a/iphone/Maps/Categories/UIColor+MapsMeColor.h +++ b/iphone/Maps/Categories/UIColor+MapsMeColor.h @@ -53,6 +53,9 @@ + (UIColor *)speedLimitWhite; + (UIColor *)speedLimitLightGray; + (UIColor *)speedLimitDarkGray; ++ (UIColor *)shadowColorBlue; ++ (UIColor *)shadowColorPurple; ++ (UIColor *)subscriptionCellBorder; + (UIColor *)colorWithName:(NSString *)colorName; + (UIColor *)colorFromHexString:(NSString *)hexString; diff --git a/iphone/Maps/Categories/UIColor+MapsMeColor.mm b/iphone/Maps/Categories/UIColor+MapsMeColor.mm index 6af1b83914..7f0d8d4f1b 100644 --- a/iphone/Maps/Categories/UIColor+MapsMeColor.mm +++ b/iphone/Maps/Categories/UIColor+MapsMeColor.mm @@ -395,4 +395,16 @@ UIColor * color(SEL cmd) return [UIColor colorWithRed:scaled(51) green:scaled(51) blue:scaled(50) alpha:alpha100]; } ++ (UIColor *)shadowColorBlue { + return [UIColor colorWithRed:scaled(5) green:scaled(70) blue:scaled(134) alpha:alpha100]; +} + ++ (UIColor *)shadowColorPurple { + return [UIColor colorWithRed:scaled(88) green:scaled(0) blue:scaled(153) alpha:alpha100]; +} + ++ (UIColor *)subscriptionCellBorder { + return [UIColor colorWithRed:scaled(174) green:scaled(184) blue:scaled(190) alpha:alpha100]; +} + @end diff --git a/iphone/Maps/Categories/UIView+Hierarchy.swift b/iphone/Maps/Categories/UIView+Hierarchy.swift index e76f07a676..9b1b672cc1 100644 --- a/iphone/Maps/Categories/UIView+Hierarchy.swift +++ b/iphone/Maps/Categories/UIView+Hierarchy.swift @@ -7,4 +7,14 @@ extension UIView { backgroundColor = UIColor.clear subviews.forEach { $0.clearTreeBackground() } } + + func alignToSuperview() { + translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + topAnchor.constraint(equalTo: superview!.topAnchor), + leftAnchor.constraint(equalTo: superview!.leftAnchor), + bottomAnchor.constraint(equalTo: superview!.bottomAnchor), + rightAnchor.constraint(equalTo: superview!.rightAnchor) + ]) + } } diff --git a/iphone/Maps/Classes/CustomViews/GradientView.swift b/iphone/Maps/Classes/CustomViews/GradientView.swift new file mode 100644 index 0000000000..76215c8000 --- /dev/null +++ b/iphone/Maps/Classes/CustomViews/GradientView.swift @@ -0,0 +1,50 @@ +@IBDesignable +class GradientView: UIView { + enum GradientDirection { + case horizontal + case vertical + } + + var gradientDirection: GradientDirection = .vertical { + didSet { + let angle = gradientDirection == .horizontal ? -CGFloat.pi / 2 : 0 + gradientLayer.transform = CATransform3DMakeRotation(angle, 0, 0, 1) + } + } + + @IBInspectable + var startColor: UIColor = .clear { + didSet { + updateColors() + } + } + + @IBInspectable + var endColor: UIColor = .lightGray { + didSet { + updateColors() + } + } + + private func updateColors() { + gradientLayer.colors = [startColor.cgColor, endColor.cgColor] + } + + override class var layerClass: AnyClass { + return CAGradientLayer.self + } + + var gradientLayer: CAGradientLayer { + return layer as! CAGradientLayer + } + + override init(frame: CGRect) { + super.init(frame: frame) + updateColors() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + updateColors() + } +} diff --git a/iphone/Maps/Images.xcassets/BookmarksSubscription/Contents.json b/iphone/Maps/Images.xcassets/BookmarksSubscription/Contents.json new file mode 100644 index 0000000000..da4a164c91 --- /dev/null +++ b/iphone/Maps/Images.xcassets/BookmarksSubscription/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionClose.imageset/Contents.json b/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionClose.imageset/Contents.json new file mode 100644 index 0000000000..c27d7741d3 --- /dev/null +++ b/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionClose.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "clear.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" + } +} \ No newline at end of file diff --git a/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionClose.imageset/clear.pdf b/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionClose.imageset/clear.pdf new file mode 100644 index 0000000000..5120f258f0 Binary files /dev/null and b/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionClose.imageset/clear.pdf differ diff --git a/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionMonth.imageset/Contents.json b/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionMonth.imageset/Contents.json new file mode 100644 index 0000000000..a0aae74d0e --- /dev/null +++ b/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionMonth.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Monthly_img.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionMonth.imageset/Monthly_img.pdf b/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionMonth.imageset/Monthly_img.pdf new file mode 100644 index 0000000000..8554f5dfb6 Binary files /dev/null and b/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionMonth.imageset/Monthly_img.pdf differ diff --git a/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionYear.imageset/Annual_img.pdf b/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionYear.imageset/Annual_img.pdf new file mode 100644 index 0000000000..4db45e45ef Binary files /dev/null and b/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionYear.imageset/Annual_img.pdf differ diff --git a/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionYear.imageset/Contents.json b/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionYear.imageset/Contents.json new file mode 100644 index 0000000000..5565ca1024 --- /dev/null +++ b/iphone/Maps/Images.xcassets/BookmarksSubscription/bookmarksSubscriptionYear.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Annual_img.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index 5eb00b767e..e9b7827a8a 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -355,7 +355,7 @@ 4577B28121F2066A00864FAC /* libvulkan_wrapper.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4577B28021F2066A00864FAC /* libvulkan_wrapper.a */; }; 4586D0C41F48121A00DF9CE5 /* libbsdiff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4586D0C31F48121A00DF9CE5 /* libbsdiff.a */; }; 4586D0E71F4813AB00DF9CE5 /* libmwm_diff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4586D0E61F4813AB00DF9CE5 /* libmwm_diff.a */; }; - 4598438621394CFD00F8CAB2 /* MetalPerformanceShaders.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4598438521394CFD00F8CAB2 /* MetalPerformanceShaders.framework */; }; + 4598438621394CFD00F8CAB2 /* MetalPerformanceShaders.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4598438521394CFD00F8CAB2 /* MetalPerformanceShaders.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 45A37B9E20B33F5E005FBDBB /* FBAudienceNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 45A37B9D20B33F5D005FBDBB /* FBAudienceNetwork.framework */; }; 45CBCCBA20590AAB006B55C2 /* libkml.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 45CBCCBB20590AAB006B55C2 /* libkml.a */; }; 45FFD65D1E965EBE00DB854E /* liblocal_ads.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 45FFD65C1E965EBE00DB854E /* liblocal_ads.a */; }; @@ -366,6 +366,8 @@ 470F5A5C2181DE7500754295 /* PaidRouteViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 470F5A5A2181DE7400754295 /* PaidRouteViewController.xib */; }; 470F5A7D2189BB2F00754295 /* PaidRoutePurchase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 470F5A7C2189BB2F00754295 /* PaidRoutePurchase.swift */; }; 470F5A7F2189C30800754295 /* InAppPurchase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 470F5A7E2189C30800754295 /* InAppPurchase.swift */; }; + 4710366522D3764600585272 /* BookmarksSubscriptionCellViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4710366322D3764600585272 /* BookmarksSubscriptionCellViewController.swift */; }; + 4710366622D3764600585272 /* BookmarksSubscriptionCellViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4710366422D3764600585272 /* BookmarksSubscriptionCellViewController.xib */; }; 4716EABA21A325310029B886 /* IPaidRouteStatistics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4716EAB921A325310029B886 /* IPaidRouteStatistics.swift */; }; 4716EAC121A6E0570029B886 /* BookmarksVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4716EAC021A6E0570029B886 /* BookmarksVC.xib */; }; 4719A643219CB61D009F9AA7 /* BillingPendingTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4719A642219CB61D009F9AA7 /* BillingPendingTransaction.swift */; }; @@ -376,6 +378,9 @@ 4726254921C27D4B00C7BAAD /* PlacePageDescriptionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4726254821C27D4B00C7BAAD /* PlacePageDescriptionViewController.swift */; }; 47289E5A2212DFFF002ABFC0 /* EditOnWebAlertViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47289E582212DFFF002ABFC0 /* EditOnWebAlertViewController.swift */; }; 47289E5B2212DFFF002ABFC0 /* EditOnWebAlertViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 47289E592212DFFF002ABFC0 /* EditOnWebAlertViewController.xib */; }; + 4728F69022CE430800E00028 /* BookmarksSubscriptionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4728F68E22CE430800E00028 /* BookmarksSubscriptionViewController.swift */; }; + 4728F69122CE430800E00028 /* BookmarksSubscriptionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4728F68F22CE430800E00028 /* BookmarksSubscriptionViewController.xib */; }; + 4728F69322CF89A400E00028 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4728F69222CF89A400E00028 /* GradientView.swift */; }; 472E3F472146BCD30020E412 /* SubscriptionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472E3F462146BCD30020E412 /* SubscriptionManager.swift */; }; 472E3F4A2146C4CD0020E412 /* MWMPurchaseManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 472E3F492146C4CD0020E412 /* MWMPurchaseManager.mm */; }; 472E3F4C2147D5700020E412 /* Subscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 472E3F4B2147D5700020E412 /* Subscription.swift */; }; @@ -569,8 +574,8 @@ BB25B1A71FB32767007276FA /* transit_colors.txt in Resources */ = {isa = PBXBuildFile; fileRef = BB25B1A51FB32767007276FA /* transit_colors.txt */; }; BB2C99B021B6AB4500F7371C /* libdescriptions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BB2C99AF21B6AB4500F7371C /* libdescriptions.a */; }; BB7626B61E85599C0031D71C /* icudt57l.dat in Resources */ = {isa = PBXBuildFile; fileRef = BB7626B41E8559980031D71C /* icudt57l.dat */; }; - BB8123CF212C264700ADE512 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB8123CD212C264700ADE512 /* Metal.framework */; }; - BB8123D0212C264700ADE512 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB8123CE212C264700ADE512 /* MetalKit.framework */; }; + BB8123CF212C264700ADE512 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB8123CD212C264700ADE512 /* Metal.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + BB8123D0212C264700ADE512 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB8123CE212C264700ADE512 /* MetalKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; BB8123D62130427E00ADE512 /* MetalContextFactory.mm in Sources */ = {isa = PBXBuildFile; fileRef = BB8123D52130427E00ADE512 /* MetalContextFactory.mm */; }; CD08887422B7ABB400C1368D /* MWMDiscoveryCollectionView.mm in Sources */ = {isa = PBXBuildFile; fileRef = CD08887322B7ABB400C1368D /* MWMDiscoveryCollectionView.mm */; }; CD6E8677226774C700D1EDF7 /* CPConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD6E8676226774C700D1EDF7 /* CPConstants.swift */; }; @@ -1431,6 +1436,8 @@ 470F5A5A2181DE7400754295 /* PaidRouteViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PaidRouteViewController.xib; sourceTree = ""; }; 470F5A7C2189BB2F00754295 /* PaidRoutePurchase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaidRoutePurchase.swift; sourceTree = ""; }; 470F5A7E2189C30800754295 /* InAppPurchase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppPurchase.swift; sourceTree = ""; }; + 4710366322D3764600585272 /* BookmarksSubscriptionCellViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksSubscriptionCellViewController.swift; sourceTree = ""; }; + 4710366422D3764600585272 /* BookmarksSubscriptionCellViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BookmarksSubscriptionCellViewController.xib; sourceTree = ""; }; 4716EAB921A325310029B886 /* IPaidRouteStatistics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPaidRouteStatistics.swift; sourceTree = ""; }; 4716EAC021A6E0570029B886 /* BookmarksVC.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BookmarksVC.xib; sourceTree = ""; }; 4716EACA21B01C270029B886 /* MWMUGCReviewSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMUGCReviewSource.h; sourceTree = ""; }; @@ -1442,6 +1449,9 @@ 4726254821C27D4B00C7BAAD /* PlacePageDescriptionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlacePageDescriptionViewController.swift; sourceTree = ""; }; 47289E582212DFFF002ABFC0 /* EditOnWebAlertViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditOnWebAlertViewController.swift; sourceTree = ""; }; 47289E592212DFFF002ABFC0 /* EditOnWebAlertViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = EditOnWebAlertViewController.xib; sourceTree = ""; }; + 4728F68E22CE430800E00028 /* BookmarksSubscriptionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksSubscriptionViewController.swift; sourceTree = ""; }; + 4728F68F22CE430800E00028 /* BookmarksSubscriptionViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BookmarksSubscriptionViewController.xib; sourceTree = ""; }; + 4728F69222CF89A400E00028 /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GradientView.swift; path = CustomViews/GradientView.swift; sourceTree = ""; }; 472E3F462146BCD30020E412 /* SubscriptionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionManager.swift; sourceTree = ""; }; 472E3F482146C4CD0020E412 /* MWMPurchaseManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMPurchaseManager.h; sourceTree = ""; }; 472E3F492146C4CD0020E412 /* MWMPurchaseManager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMPurchaseManager.mm; sourceTree = ""; }; @@ -3586,6 +3596,7 @@ 34BC72091B0DECAE0012A34B /* MapViewControls */, 34AB65C41FC5AA320078E451 /* NavigationDashboard */, 479EE9492292FB03009DEBA6 /* ActivityIndicator.swift */, + 4728F69222CF89A400E00028 /* GradientView.swift */, ); name = "Custom Views"; sourceTree = ""; @@ -3606,6 +3617,10 @@ 470F5A592181DE7400754295 /* PaidRouteViewController.swift */, 470F5A5A2181DE7400754295 /* PaidRouteViewController.xib */, 45AC339022C4F57C004DC574 /* MWMUTM.h */, + 4728F68E22CE430800E00028 /* BookmarksSubscriptionViewController.swift */, + 4728F68F22CE430800E00028 /* BookmarksSubscriptionViewController.xib */, + 4710366322D3764600585272 /* BookmarksSubscriptionCellViewController.swift */, + 4710366422D3764600585272 /* BookmarksSubscriptionCellViewController.xib */, ); path = Catalog; sourceTree = ""; @@ -4801,6 +4816,7 @@ F61757F11FC731F5000AD0D0 /* DiscoveryOnlineTemplateCell.xib in Resources */, 6741A95B1BF340DE002C974C /* 06_code2000.ttf in Resources */, F603E05E1FDE9703006B84D6 /* DiscoverySearchCollectionHolderCell.xib in Resources */, + 4710366622D3764600585272 /* BookmarksSubscriptionCellViewController.xib in Resources */, 6741A99F1BF340DE002C974C /* 07_roboto_medium.ttf in Resources */, F6E2FE6D1E097BA00083EBEC /* _MWMOHHeaderCell.xib in Resources */, F6E2FE701E097BA00083EBEC /* _MWMOHSubCell.xib in Resources */, @@ -4811,6 +4827,7 @@ F65D1E1A20E4F11600FE31DD /* ugc_migration in Resources */, F6E2FEAF1E097BA00083EBEC /* _MWMPPPExternalTitle.xib in Resources */, F6E2FEB21E097BA00083EBEC /* _MWMPPPSchedule.xib in Resources */, + 4728F69122CE430800E00028 /* BookmarksSubscriptionViewController.xib in Resources */, F6E2FEB51E097BA00083EBEC /* _MWMPPPSpace.xib in Resources */, F6E2FEB81E097BA00083EBEC /* _MWMPPPSubtitle.xib in Resources */, 4554B6EE1E55F0F30084017F /* drules_proto_vehicle_dark.bin in Resources */, @@ -5392,6 +5409,7 @@ 4767CDC120B477BA00BD8166 /* WelcomeViewController.swift in Sources */, 34E7761F1F14DB48003040B3 /* PlacePageArea.swift in Sources */, 346DB82E1E5C4F6700E3123E /* GalleryItemViewController.swift in Sources */, + 4728F69322CF89A400E00028 /* GradientView.swift in Sources */, 340475561E081A4600C92850 /* Statistics.mm in Sources */, CD96C71722A7B5DE00DB7CFE /* MWMDiscoveryCityGalleryObjects.mm in Sources */, F6381BF61CD12045004CA943 /* LocaleTranslator.mm in Sources */, @@ -5560,6 +5578,7 @@ 340475651E081A4600C92850 /* MWMRouter.mm in Sources */, 47E3C72F2111F472008B3B27 /* CoverVerticalModalTransitioning.swift in Sources */, 346DB83D1E5C4F6700E3123E /* GalleryModel.swift in Sources */, + 4710366522D3764600585272 /* BookmarksSubscriptionCellViewController.swift in Sources */, 34E776101F14B165003040B3 /* VisibleArea.swift in Sources */, 330473EA21F7440C00DC4AEA /* MWMHotelParams.mm in Sources */, 3454D7D71E07F045004AF2AD /* UIKitCategories.mm in Sources */, @@ -5568,6 +5587,7 @@ 3488B01A1E9D0B230068AFD8 /* UIColor+Modifications.swift in Sources */, 34E50DD81F6FCAB1008EED49 /* UGCSummaryRatingCell.swift in Sources */, 6741AA281BF340DE002C974C /* MWMAlert.mm in Sources */, + 4728F69022CE430800E00028 /* BookmarksSubscriptionViewController.swift in Sources */, F6E2FF571E097BA00083EBEC /* MWMMobileInternetViewController.mm in Sources */, 4797A4E22270997E00D3A984 /* DeepLinkHelper.mm in Sources */, 47B06E0021BAAC270094CCAD /* GeoZoneTracker.swift in Sources */,