forked from organicmaps/organicmaps
[iOS] basic guides subscription flow and UI
https://jira.mail.ru/browse/MAPSME-10941 https://jira.mail.ru/browse/MAPSME-10942 https://jira.mail.ru/browse/MAPSME-10943 https://jira.mail.ru/browse/MAPSME-10945
This commit is contained in:
parent
36d2e88292
commit
3026187949
33 changed files with 963 additions and 119 deletions
|
@ -97,8 +97,8 @@
|
|||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="T1l-r7-y0s">
|
||||
<rect key="frame" x="0.0" y="0.0" width="116" height="35"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SAVE $38" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Udv-PO-OUs">
|
||||
<rect key="frame" x="0.0" y="7" width="116" height="21"/>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SAVE $38" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="12" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Udv-PO-OUs">
|
||||
<rect key="frame" x="4" y="7" width="108" height="21"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="18"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
|
@ -109,8 +109,8 @@
|
|||
<constraint firstAttribute="height" constant="35" id="1hc-rF-WeJ"/>
|
||||
<constraint firstAttribute="width" constant="116" id="MmH-NQ-a79"/>
|
||||
<constraint firstItem="Udv-PO-OUs" firstAttribute="centerY" secondItem="T1l-r7-y0s" secondAttribute="centerY" id="Rc1-MY-abl"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Udv-PO-OUs" secondAttribute="trailing" id="Ugx-X0-X5n"/>
|
||||
<constraint firstItem="Udv-PO-OUs" firstAttribute="leading" secondItem="T1l-r7-y0s" secondAttribute="leading" id="ftl-Dn-UeW"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Udv-PO-OUs" secondAttribute="trailing" constant="4" id="Ugx-X0-X5n"/>
|
||||
<constraint firstItem="Udv-PO-OUs" firstAttribute="leading" secondItem="T1l-r7-y0s" secondAttribute="leading" constant="4" id="ftl-Dn-UeW"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
|
||||
|
|
|
@ -2,10 +2,15 @@ class BookmarksSubscriptionViewController: MWMViewController {
|
|||
@IBOutlet private var annualView: UIView!
|
||||
@IBOutlet private var monthlyView: UIView!
|
||||
@IBOutlet private var gradientView: GradientView!
|
||||
@IBOutlet var scrollView: UIScrollView!
|
||||
|
||||
@IBOutlet private var scrollView: UIScrollView!
|
||||
@IBOutlet private var continueButton: UIButton!
|
||||
|
||||
private let annualViewController = BookmarksSubscriptionCellViewController()
|
||||
private let monthlyViewController = BookmarksSubscriptionCellViewController()
|
||||
private var priceFormatter: NumberFormatter?
|
||||
private var monthlySubscription: ISubscription?
|
||||
private var annualSubscription: ISubscription?
|
||||
private var selectedSubscription: ISubscription?
|
||||
|
||||
var onSubscribe: MWMVoidBlock?
|
||||
var onCancel: MWMVoidBlock?
|
||||
|
@ -35,20 +40,52 @@ class BookmarksSubscriptionViewController: MWMViewController {
|
|||
|
||||
annualViewController.config(title: L("annual_subscription_title"),
|
||||
subtitle: L("annual_subscription_message"),
|
||||
price: "$29.99",
|
||||
image: UIImage(named: "bookmarksSubscriptionYear")!,
|
||||
discount: "SAVE $38")
|
||||
price: "",
|
||||
image: UIImage(named: "bookmarksSubscriptionYear")!)
|
||||
monthlyViewController.config(title: L("montly_subscription_title"),
|
||||
subtitle: L("montly_subscription_message"),
|
||||
price: "$3.99",
|
||||
price: "",
|
||||
image: UIImage(named: "bookmarksSubscriptionMonth")!)
|
||||
annualViewController.setSelected(true, animated: false)
|
||||
continueButton.setTitle(L("current_location_unknown_continue_button").uppercased(), for: .normal)
|
||||
InAppPurchase.bookmarksSubscriptionManager.addListener(self)
|
||||
InAppPurchase.bookmarksSubscriptionManager.getAvailableSubscriptions { [weak self] (subscriptions, error) in
|
||||
guard let subscriptions = subscriptions, subscriptions.count == 2 else {
|
||||
// TODO: hande error
|
||||
return
|
||||
}
|
||||
|
||||
self?.monthlySubscription = subscriptions[0]
|
||||
self?.annualSubscription = subscriptions[1]
|
||||
self?.selectedSubscription = self?.annualSubscription
|
||||
|
||||
let s = subscriptions[0]
|
||||
let formatter = NumberFormatter()
|
||||
formatter.locale = s.priceLocale
|
||||
formatter.numberStyle = .currency
|
||||
|
||||
let monthlyPrice = subscriptions[0].price
|
||||
let annualPrice = subscriptions[1].price
|
||||
let discount = monthlyPrice.multiplying(by: 12).subtracting(annualPrice)
|
||||
let discountString = formatter.string(from: discount)
|
||||
|
||||
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: (discountString != nil) ? "- \(discountString!)" : nil)
|
||||
}
|
||||
}
|
||||
|
||||
@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)
|
||||
|
@ -58,16 +95,54 @@ class BookmarksSubscriptionViewController: MWMViewController {
|
|||
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)
|
||||
}
|
||||
|
||||
@IBAction func onContinue(_ sender: UIButton) {
|
||||
onSubscribe?()
|
||||
MWMBookmarksManager.shared().ping { [weak self] (success) in
|
||||
guard success else {
|
||||
// self?.loadingView.isHidden = true
|
||||
let errorDialog = BookmarksSubscriptionFailViewController { [weak self] in
|
||||
self?.dismiss(animated: true)
|
||||
}
|
||||
self?.present(errorDialog, animated: true)
|
||||
return
|
||||
}
|
||||
|
||||
guard let subscription = self?.selectedSubscription else {
|
||||
return
|
||||
}
|
||||
|
||||
InAppPurchase.bookmarksSubscriptionManager.subscribe(to: subscription)
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func onClose(_ sender: UIButton) {
|
||||
onCancel?()
|
||||
}
|
||||
}
|
||||
|
||||
extension BookmarksSubscriptionViewController: SubscriptionManagerListener {
|
||||
func didFailToSubscribe(_ subscription: ISubscription, error: Error?) {
|
||||
|
||||
}
|
||||
|
||||
func didSubsribe(_ subscription: ISubscription) {
|
||||
onSubscribe?()
|
||||
}
|
||||
|
||||
func didFailToValidate(_ subscription: ISubscription, error: Error?) {
|
||||
|
||||
}
|
||||
|
||||
func didDefer(_ subscription: ISubscription) {
|
||||
|
||||
}
|
||||
|
||||
func validationError() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="BookmarksSubscriptionViewController" customModule="maps_me" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="annualView" destination="Bae-oL-ekX" id="l9n-u0-LNW"/>
|
||||
<outlet property="continueButton" destination="neX-0h-hs4" id="kQw-7y-Igs"/>
|
||||
<outlet property="gradientView" destination="BcI-3g-iCI" id="Rmd-LB-Rl5"/>
|
||||
<outlet property="monthlyView" destination="Jpy-cA-wCv" id="6yi-OC-MrD"/>
|
||||
<outlet property="scrollView" destination="q5w-jW-Chn" id="dMR-TM-gMC"/>
|
||||
|
@ -49,6 +50,7 @@
|
|||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="bold24"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="native_screen_subscription_title"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Every kind of journey. Whether alone or with friends, hiking or sunbathing" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vzD-qz-Fwt">
|
||||
|
@ -59,6 +61,7 @@
|
|||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular14"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="native_screen_subscription_message"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<scrollView multipleTouchEnabled="YES" contentMode="scaleToFill" bounces="NO" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" bouncesZoom="NO" translatesAutoresizingMaskIntoConstraints="NO" id="q5w-jW-Chn">
|
||||
|
@ -151,6 +154,7 @@
|
|||
<userDefinedRuntimeAttribute type="string" keyPath="textColorHighlightedName" value="linkBlueHighlighted"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium14"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="linkBlue"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="restore_subscription"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</button>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="justified" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tWZ-GP-RxW">
|
||||
|
@ -162,9 +166,10 @@
|
|||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular9"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackHintText"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="subscription_terms_guides"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="awa-we-Pjk" userLabel="TermsOfUse">
|
||||
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="awa-we-Pjk" userLabel="TermsOfUse">
|
||||
<rect key="frame" x="20" y="625.66666666666663" width="66" height="44"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="welcome_storyboard.button_next2"/>
|
||||
|
@ -179,9 +184,10 @@
|
|||
<userDefinedRuntimeAttribute type="string" keyPath="textColorHighlightedName" value="blackHintText"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium10"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="blackSecondaryText"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="terms_of_use"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</button>
|
||||
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="60B-kT-Eev" userLabel="PrivacyPolicy">
|
||||
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" horizontalCompressionResistancePriority="749" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="60B-kT-Eev" userLabel="PrivacyPolicy">
|
||||
<rect key="frame" x="325" y="625.66666666666663" width="69" height="44"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="welcome_storyboard.button_next2"/>
|
||||
|
@ -196,6 +202,7 @@
|
|||
<userDefinedRuntimeAttribute type="string" keyPath="textColorHighlightedName" value="blackHintText"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium10"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="blackSecondaryText"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="privacy_policy"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="v0Z-5m-unD">
|
||||
|
@ -233,6 +240,7 @@
|
|||
<constraint firstAttribute="trailing" secondItem="bOS-sQ-rkD" secondAttribute="trailing" constant="16" id="UBz-JQ-dSq"/>
|
||||
<constraint firstAttribute="trailing" secondItem="neX-0h-hs4" secondAttribute="trailing" constant="50" id="UTD-bj-67L"/>
|
||||
<constraint firstAttribute="trailing" secondItem="v0Z-5m-unD" secondAttribute="trailing" constant="8" id="aj5-SM-A2m"/>
|
||||
<constraint firstItem="60B-kT-Eev" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="awa-we-Pjk" secondAttribute="trailing" constant="16" id="bOW-rf-yBR"/>
|
||||
<constraint firstItem="neX-0h-hs4" firstAttribute="top" secondItem="q5w-jW-Chn" secondAttribute="bottom" constant="34" id="cZ6-hC-ePD"/>
|
||||
<constraint firstItem="q5w-jW-Chn" firstAttribute="top" secondItem="vzD-qz-Fwt" secondAttribute="bottom" constant="34" id="esu-FS-r9d"/>
|
||||
<constraint firstItem="vzD-qz-Fwt" firstAttribute="top" secondItem="bOS-sQ-rkD" secondAttribute="bottom" constant="16" id="f5X-2e-9pD"/>
|
||||
|
|
|
@ -146,14 +146,14 @@ final class CatalogWebViewController: WebViewController {
|
|||
override func webView(_ webView: WKWebView,
|
||||
decidePolicyFor navigationAction: WKNavigationAction,
|
||||
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
|
||||
let subscribePath = "/mobilefront/subscribe"
|
||||
let subscribePath = "subscribe"
|
||||
guard let url = navigationAction.request.url,
|
||||
url.scheme == "mapsme" || url.path == "/mobilefront/buy_kml" || url.path == subscribePath else {
|
||||
url.scheme == "mapsme" || url.path.contains("buy_kml") || url.path.contains(subscribePath) else {
|
||||
super.webView(webView, decidePolicyFor: navigationAction, decisionHandler: decisionHandler)
|
||||
return
|
||||
}
|
||||
|
||||
if url.path == subscribePath {
|
||||
if url.path.contains(subscribePath) {
|
||||
showSubscribe()
|
||||
decisionHandler(.cancel);
|
||||
return
|
||||
|
@ -407,6 +407,11 @@ private func logToPushWoosh(_ categoryInfo: CatalogCategoryInfo) {
|
|||
}
|
||||
|
||||
extension CatalogWebViewController: PaidRouteViewControllerDelegate {
|
||||
func didCompleteSubscription(_ viewController: PaidRouteViewController) {
|
||||
dismiss(animated: true)
|
||||
self.webView.reload()
|
||||
}
|
||||
|
||||
func didCompletePurchase(_ viewController: PaidRouteViewController) {
|
||||
dismiss(animated: true)
|
||||
download()
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
class BookmarksSubscriptionExpiredViewController: UIViewController {
|
||||
private let transitioning = FadeTransitioning<AlertPresentationController>()
|
||||
private let onSubscribe: MWMVoidBlock
|
||||
private let onDelete: MWMVoidBlock
|
||||
|
||||
init(onSubscribe: @escaping MWMVoidBlock, onDelete: @escaping MWMVoidBlock) {
|
||||
self.onSubscribe = onSubscribe
|
||||
self.onDelete = onDelete
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
}
|
||||
|
||||
@IBAction func onSubscribe(_ sender: UIButton) {
|
||||
onSubscribe()
|
||||
}
|
||||
|
||||
@IBAction func onDelete(_ sender: UIButton) {
|
||||
onDelete()
|
||||
}
|
||||
|
||||
override var transitioningDelegate: UIViewControllerTransitioningDelegate? {
|
||||
get { return transitioning }
|
||||
set { }
|
||||
}
|
||||
|
||||
override var modalPresentationStyle: UIModalPresentationStyle {
|
||||
get { return .custom }
|
||||
set { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina6_1" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="BookmarksSubscriptionExpiredViewController" customModule="maps_me" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="view" destination="Kxh-WQ-Arx" id="tq9-Vt-1LI"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="Kxh-WQ-Arx">
|
||||
<rect key="frame" x="0.0" y="0.0" width="284" height="451"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="bookmarksSubscriptionFail" translatesAutoresizingMaskIntoConstraints="NO" id="aPq-P8-sA5">
|
||||
<rect key="frame" x="68.5" y="16" width="147" height="134"/>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Your subscription has expired" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D7k-iL-1r7">
|
||||
<rect key="frame" x="16" y="166" width="252" height="50.5"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="21"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="renewal_screen_title"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="bold22"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7V3-cv-Cng" userLabel="Continue">
|
||||
<rect key="frame" x="16" y="327.5" width="252" height="50"/>
|
||||
<color key="backgroundColor" red="0.1176470588" green="0.58823529409999997" blue="0.94117647059999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="welcome_storyboard.button_next2"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="Rot-Pv-ARQ"/>
|
||||
<constraint firstAttribute="width" constant="252" id="X61-iJ-2T3"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
|
||||
<state key="normal" title="Yes, renew">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorHighlightedName" value="white"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium16"/>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
|
||||
<integer key="value" value="6"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="white"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="linkBlue"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="backgroundHighlightedColorName" value="linkBlueHighlighted"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="renewal_screen_button_restore"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="onSubscribe:" destination="-1" eventType="touchUpInside" id="gD5-39-MrO"/>
|
||||
</connections>
|
||||
</button>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="All the guides downloaded by subscription are going to be deleted. Want to resume the subscription and keep them?" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="CJe-NE-j8c">
|
||||
<rect key="frame" x="16" y="232.5" width="252" height="67"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<color key="textColor" white="0.0" alpha="0.39696596750000002" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="renewal_screen_message"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular14"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackSecondaryText"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OOr-Od-TtY" userLabel="Continue">
|
||||
<rect key="frame" x="16" y="385" width="252" height="50"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="welcome_storyboard.button_next2"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="2LI-gb-Fn0"/>
|
||||
<constraint firstAttribute="width" constant="252" id="jfm-1O-kSp"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
|
||||
<state key="normal" title="No, delete guides">
|
||||
<color key="titleColor" red="0.89926690924657537" green="0.2245826198630137" blue="0.12863869863013699" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="red"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorHighlightedName" value="red"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium16"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="renewal_screen_button_cancel"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="onDelete:" destination="-1" eventType="touchUpInside" id="eeP-V8-6eN"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="CJe-NE-j8c" secondAttribute="trailing" constant="16" id="38y-Kp-ZMN"/>
|
||||
<constraint firstItem="OOr-Od-TtY" firstAttribute="top" secondItem="7V3-cv-Cng" secondAttribute="bottom" constant="7.5" id="4aF-aL-QKM"/>
|
||||
<constraint firstItem="D7k-iL-1r7" firstAttribute="leading" secondItem="Kxh-WQ-Arx" secondAttribute="leading" constant="16" id="G00-iU-ukK"/>
|
||||
<constraint firstItem="7V3-cv-Cng" firstAttribute="leading" secondItem="Kxh-WQ-Arx" secondAttribute="leading" constant="16" id="Grl-YJ-uxW"/>
|
||||
<constraint firstItem="OOr-Od-TtY" firstAttribute="bottom" secondItem="Kxh-WQ-Arx" secondAttribute="bottom" constant="-16" id="J7A-Za-4yU"/>
|
||||
<constraint firstItem="7V3-cv-Cng" firstAttribute="top" secondItem="CJe-NE-j8c" secondAttribute="bottom" constant="28" id="JBU-ma-ZKg"/>
|
||||
<constraint firstItem="aPq-P8-sA5" firstAttribute="top" secondItem="Kxh-WQ-Arx" secondAttribute="top" constant="16" id="PHv-UT-sgZ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="OOr-Od-TtY" secondAttribute="trailing" constant="16" id="fzm-1o-YTA"/>
|
||||
<constraint firstAttribute="trailing" secondItem="D7k-iL-1r7" secondAttribute="trailing" constant="16" id="j7z-Hs-gUN"/>
|
||||
<constraint firstItem="D7k-iL-1r7" firstAttribute="top" secondItem="aPq-P8-sA5" secondAttribute="bottom" constant="16" id="nBZ-uV-0ff"/>
|
||||
<constraint firstItem="aPq-P8-sA5" firstAttribute="centerX" secondItem="Kxh-WQ-Arx" secondAttribute="centerX" id="ppy-5i-VNe"/>
|
||||
<constraint firstAttribute="trailing" secondItem="7V3-cv-Cng" secondAttribute="trailing" constant="16" id="pvx-Yq-qWi"/>
|
||||
<constraint firstItem="OOr-Od-TtY" firstAttribute="leading" secondItem="Kxh-WQ-Arx" secondAttribute="leading" constant="16" id="qqt-Wo-V1H"/>
|
||||
<constraint firstItem="CJe-NE-j8c" firstAttribute="top" secondItem="D7k-iL-1r7" secondAttribute="bottom" constant="16" id="xPs-dz-pQq"/>
|
||||
<constraint firstItem="CJe-NE-j8c" firstAttribute="leading" secondItem="Kxh-WQ-Arx" secondAttribute="leading" constant="16" id="ygS-eh-ahG"/>
|
||||
</constraints>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<viewLayoutGuide key="safeArea" id="vAr-wN-cIR"/>
|
||||
<point key="canvasLocation" x="46.376811594202906" y="191.18303571428569"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="bookmarksSubscriptionFail" width="147" height="134"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -0,0 +1,31 @@
|
|||
class BookmarksSubscriptionFailViewController: UIViewController {
|
||||
private let transitioning = FadeTransitioning<AlertPresentationController>()
|
||||
private let onOk: MWMVoidBlock
|
||||
|
||||
init(onOk: @escaping MWMVoidBlock) {
|
||||
self.onOk = onOk
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
}
|
||||
|
||||
@IBAction func onOk(_ sender: UIButton) {
|
||||
onOk()
|
||||
}
|
||||
|
||||
override var transitioningDelegate: UIViewControllerTransitioningDelegate? {
|
||||
get { return transitioning }
|
||||
set { }
|
||||
}
|
||||
|
||||
override var modalPresentationStyle: UIModalPresentationStyle {
|
||||
get { return .custom }
|
||||
set { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="BookmarksSubscriptionFailViewController" customModule="maps_me" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="view" destination="LxW-jP-dXy" id="LjI-6j-3V1"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="LxW-jP-dXy">
|
||||
<rect key="frame" x="0.0" y="0.0" width="284" height="343"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="bookmarksSubscriptionFail" translatesAutoresizingMaskIntoConstraints="NO" id="QsQ-Qr-kgU">
|
||||
<rect key="frame" x="68.5" y="16" width="147" height="134"/>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Purchase has failed" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BQC-4m-6q5">
|
||||
<rect key="frame" x="16" y="166" width="252" height="25.5"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="21"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="subscription_error_ping_title"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="bold22"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="N2j-Or-SOC" userLabel="Continue">
|
||||
<rect key="frame" x="16" y="269" width="252" height="50"/>
|
||||
<color key="backgroundColor" red="0.1176470588" green="0.58823529409999997" blue="0.94117647059999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="welcome_storyboard.button_next2"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="8lg-7m-LsE"/>
|
||||
<constraint firstAttribute="width" constant="252" id="R62-U1-Ob4"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
|
||||
<state key="normal" title="Got It!">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorHighlightedName" value="white"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium14"/>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
|
||||
<integer key="value" value="6"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="white"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="linkBlue"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="backgroundHighlightedColorName" value="linkBlueHighlighted"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="subscription_error_button"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="onOk:" destination="-1" eventType="touchUpInside" id="TOs-X1-qKX"/>
|
||||
</connections>
|
||||
</button>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="The service is currently unavailable in your region. Please try again later." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lrT-fS-BfP">
|
||||
<rect key="frame" x="16" y="207.5" width="252" height="33.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<color key="textColor" white="0.0" alpha="0.39696596750000002" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="subscription_error_message"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular14"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackSecondaryText"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="QsQ-Qr-kgU" firstAttribute="top" secondItem="LxW-jP-dXy" secondAttribute="top" constant="16" id="8Bi-kX-LCG"/>
|
||||
<constraint firstAttribute="bottom" secondItem="N2j-Or-SOC" secondAttribute="bottom" constant="24" id="AWo-J4-6A9"/>
|
||||
<constraint firstItem="N2j-Or-SOC" firstAttribute="top" secondItem="lrT-fS-BfP" secondAttribute="bottom" constant="28" id="E4s-tH-edG"/>
|
||||
<constraint firstItem="BQC-4m-6q5" firstAttribute="leading" secondItem="LxW-jP-dXy" secondAttribute="leading" constant="16" id="IWo-M7-dRf"/>
|
||||
<constraint firstItem="QsQ-Qr-kgU" firstAttribute="centerX" secondItem="LxW-jP-dXy" secondAttribute="centerX" id="Kuw-sI-C7B"/>
|
||||
<constraint firstAttribute="trailing" secondItem="BQC-4m-6q5" secondAttribute="trailing" constant="16" id="ZmH-bY-Gbh"/>
|
||||
<constraint firstItem="lrT-fS-BfP" firstAttribute="leading" secondItem="LxW-jP-dXy" secondAttribute="leading" constant="16" id="bHj-RY-p3j"/>
|
||||
<constraint firstAttribute="trailing" secondItem="N2j-Or-SOC" secondAttribute="trailing" constant="16" id="gMq-ke-Kd8"/>
|
||||
<constraint firstItem="lrT-fS-BfP" firstAttribute="top" secondItem="BQC-4m-6q5" secondAttribute="bottom" constant="16" id="j5K-I7-Qrv"/>
|
||||
<constraint firstItem="N2j-Or-SOC" firstAttribute="leading" secondItem="LxW-jP-dXy" secondAttribute="leading" constant="16" id="lJM-4J-pzP"/>
|
||||
<constraint firstAttribute="trailing" secondItem="lrT-fS-BfP" secondAttribute="trailing" constant="16" id="mIZ-Xr-mbT"/>
|
||||
<constraint firstItem="BQC-4m-6q5" firstAttribute="top" secondItem="QsQ-Qr-kgU" secondAttribute="bottom" constant="16" id="ptg-2t-gke"/>
|
||||
</constraints>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<viewLayoutGuide key="safeArea" id="Eiv-TN-MZz"/>
|
||||
<point key="canvasLocation" x="46.399999999999999" y="155.17241379310346"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="bookmarksSubscriptionFail" width="147" height="134"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -0,0 +1,31 @@
|
|||
class BookmarksSubscriptionSuccessViewController: UIViewController {
|
||||
private let transitioning = FadeTransitioning<AlertPresentationController>()
|
||||
private let onOk: MWMVoidBlock
|
||||
|
||||
init(onOk: @escaping MWMVoidBlock) {
|
||||
self.onOk = onOk
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
}
|
||||
|
||||
@IBAction func onOk(_ sender: UIButton) {
|
||||
onOk()
|
||||
}
|
||||
|
||||
override var transitioningDelegate: UIViewControllerTransitioningDelegate? {
|
||||
get { return transitioning }
|
||||
set { }
|
||||
}
|
||||
|
||||
override var modalPresentationStyle: UIModalPresentationStyle {
|
||||
get { return .custom }
|
||||
set { }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="BookmarksSubscriptionSuccessViewController" customModule="maps_me" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="284" height="312"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="bookmarksSubscriptionSuccess" translatesAutoresizingMaskIntoConstraints="NO" id="HMq-ZE-y4q">
|
||||
<rect key="frame" x="61" y="16" width="162" height="117"/>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Woo-hoo!" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Dfb-YF-W7t">
|
||||
<rect key="frame" x="16" y="149" width="252" height="25.5"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="21"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="subscription_success_dialog_title"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="bold22"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Dxe-ly-peO" userLabel="Continue">
|
||||
<rect key="frame" x="16" y="238" width="252" height="50"/>
|
||||
<color key="backgroundColor" red="0.1176470588" green="0.58823529409999997" blue="0.94117647059999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="welcome_storyboard.button_next2"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="EGP-Ml-g0E"/>
|
||||
<constraint firstAttribute="width" constant="252" id="MMa-iX-Xh3"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
|
||||
<state key="normal" title="Got It!">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorHighlightedName" value="white"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium14"/>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
|
||||
<integer key="value" value="6"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="white"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="linkBlue"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="backgroundHighlightedColorName" value="linkBlueHighlighted"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="button_layer_got_it"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="onOk:" destination="-1" eventType="touchUpInside" id="8k3-cf-DxU"/>
|
||||
</connections>
|
||||
</button>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="You've got a subscription!" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="nK1-v6-zGB">
|
||||
<rect key="frame" x="16" y="190.5" width="252" height="19.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" white="0.0" alpha="0.39696596746575341" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="subscription_success_dialog_message"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular16"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackSecondaryText"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="HMq-ZE-y4q" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="16" id="8Lj-ZZ-PuR"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Dxe-ly-peO" secondAttribute="bottom" constant="24" id="9bq-s2-Dkn"/>
|
||||
<constraint firstItem="nK1-v6-zGB" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="16" id="EVN-be-2i8"/>
|
||||
<constraint firstItem="Dfb-YF-W7t" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="16" id="IB5-D8-Fsk"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Dxe-ly-peO" secondAttribute="trailing" constant="16" id="P2S-OM-Ixz"/>
|
||||
<constraint firstItem="Dxe-ly-peO" firstAttribute="top" secondItem="nK1-v6-zGB" secondAttribute="bottom" constant="28" id="SVl-wW-lpU"/>
|
||||
<constraint firstAttribute="trailing" secondItem="nK1-v6-zGB" secondAttribute="trailing" constant="16" id="Saj-tD-1qF"/>
|
||||
<constraint firstItem="HMq-ZE-y4q" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="djl-dn-ORl"/>
|
||||
<constraint firstItem="Dfb-YF-W7t" firstAttribute="top" secondItem="HMq-ZE-y4q" secondAttribute="bottom" constant="16" id="pvA-rU-yBZ"/>
|
||||
<constraint firstItem="nK1-v6-zGB" firstAttribute="top" secondItem="Dfb-YF-W7t" secondAttribute="bottom" constant="16" id="vco-Rr-q5P"/>
|
||||
<constraint firstItem="Dxe-ly-peO" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="16" id="wLc-Ie-YbN"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Dfb-YF-W7t" secondAttribute="trailing" constant="16" id="zT1-DD-slJ"/>
|
||||
</constraints>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
|
||||
<point key="canvasLocation" x="47.200000000000003" y="143.02848575712144"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="bookmarksSubscriptionSuccess" width="162" height="117"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -1,5 +1,8 @@
|
|||
import SafariServices
|
||||
|
||||
protocol PaidRouteViewControllerDelegate: AnyObject {
|
||||
func didCompletePurchase(_ viewController: PaidRouteViewController)
|
||||
func didCompleteSubscription(_ viewController: PaidRouteViewController)
|
||||
func didCancelPurchase(_ viewController: PaidRouteViewController)
|
||||
}
|
||||
|
||||
|
@ -8,8 +11,8 @@ class PaidRouteViewController: MWMViewController {
|
|||
@IBOutlet weak var productNameLabel: UILabel!
|
||||
@IBOutlet weak var routeTitleLabel: UILabel!
|
||||
@IBOutlet weak var routeAuthorLabel: UILabel!
|
||||
@IBOutlet weak var subscribeButton: UIButton!
|
||||
@IBOutlet weak var buyButton: UIButton!
|
||||
@IBOutlet weak var cancelButton: UIButton!
|
||||
@IBOutlet weak var loadingIndicator: UIActivityIndicatorView!
|
||||
@IBOutlet weak var loadingView: UIView!
|
||||
|
||||
|
@ -22,7 +25,13 @@ class PaidRouteViewController: MWMViewController {
|
|||
private let imageUrl: URL?
|
||||
|
||||
private var product: IStoreProduct?
|
||||
private var subscription: ISubscription?
|
||||
private let subscriptionManager: SubscriptionManager
|
||||
|
||||
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
||||
get { return [.portrait] }
|
||||
}
|
||||
|
||||
init(name: String,
|
||||
author: String?,
|
||||
imageUrl: URL?,
|
||||
|
@ -33,35 +42,71 @@ class PaidRouteViewController: MWMViewController {
|
|||
self.imageUrl = imageUrl
|
||||
self.purchase = purchase
|
||||
self.statistics = statistics
|
||||
self.subscriptionManager = InAppPurchase.bookmarksSubscriptionManager
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
self.subscriptionManager.addListener(self)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
subscriptionManager.removeListener(self)
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
buyButton.layer.borderColor = UIColor.linkBlue()?.cgColor
|
||||
routeTitleLabel.text = name
|
||||
routeAuthorLabel.text = author
|
||||
if let url = imageUrl {
|
||||
previewImageView.wi_setImage(with: url, transitionDuration: kDefaultAnimationDuration)
|
||||
}
|
||||
|
||||
purchase.requestStoreProduct { [weak self] (product, error) in
|
||||
var product: IStoreProduct?
|
||||
var subscriptions: [ISubscription]?
|
||||
|
||||
let dispatchGroup = DispatchGroup()
|
||||
dispatchGroup.enter()
|
||||
purchase.requestStoreProduct { (p, error) in
|
||||
product = p
|
||||
dispatchGroup.leave()
|
||||
}
|
||||
|
||||
dispatchGroup.enter()
|
||||
subscriptionManager.getAvailableSubscriptions { (s, error) in
|
||||
subscriptions = s
|
||||
dispatchGroup.leave()
|
||||
}
|
||||
|
||||
dispatchGroup.notify(queue: .main) { [weak self] in
|
||||
self?.loadingIndicator.stopAnimating()
|
||||
guard let product = product else {
|
||||
guard let product = product, let subscriptions = subscriptions else {
|
||||
MWMAlertViewController.activeAlert().presentInfoAlert(L("price_error_title"),
|
||||
text: L("price_error_subtitle"))
|
||||
if let s = self { s.delegate?.didCancelPurchase(s) }
|
||||
return
|
||||
}
|
||||
self?.productNameLabel.text = product.localizedName
|
||||
self?.buyButton.setTitle(String(coreFormat: L("buy_btn"), arguments: [product.formattedPrice]),
|
||||
for: .normal)
|
||||
self?.buyButton.isEnabled = true
|
||||
self?.buyButton.setTitle(String(coreFormat: L("buy_btn"), arguments: [product.formattedPrice]), for: .normal)
|
||||
self?.buyButton.isHidden = false
|
||||
|
||||
let idx = Int(arc4random() % 2)
|
||||
let s = subscriptions[idx]
|
||||
|
||||
let formatter = NumberFormatter()
|
||||
formatter.locale = s.priceLocale
|
||||
formatter.numberStyle = .currency
|
||||
|
||||
let titleFormat = L((s.period == .year) ? "buy_btn_for_subscription_ios_only_year" : "buy_btn_for_subscription_ios_only_mo")
|
||||
let title = String(coreFormat: titleFormat, arguments: [formatter.string(from: s.price) ?? ""])
|
||||
self?.subscribeButton.setTitle(title, for: .normal)
|
||||
self?.subscribeButton.isEnabled = true
|
||||
self?.subscription = s
|
||||
}
|
||||
|
||||
statistics.logPreviewShow()
|
||||
}
|
||||
|
||||
|
@ -69,41 +114,118 @@ class PaidRouteViewController: MWMViewController {
|
|||
return .lightContent
|
||||
}
|
||||
|
||||
private func pingServer(_ completion: @escaping (_ success: Bool) -> Void) {
|
||||
MWMBookmarksManager.shared().ping { (success) in
|
||||
completion(success)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Event handlers
|
||||
|
||||
@IBAction func onBuy(_ sender: UIButton) {
|
||||
statistics.logPay()
|
||||
loadingView.isHidden = false
|
||||
purchase.makePayment({ [weak self] (code, error) in
|
||||
self?.loadingView.isHidden = true
|
||||
switch(code) {
|
||||
case .success:
|
||||
self?.statistics.logPaymentSuccess()
|
||||
self?.statistics.logValidationSuccess()
|
||||
if let s = self { s.delegate?.didCompletePurchase(s) }
|
||||
case .userCancelled:
|
||||
// do nothing
|
||||
break
|
||||
case .error:
|
||||
if let err = error as? RoutePurchaseError {
|
||||
switch err {
|
||||
case .paymentError:
|
||||
self?.statistics.logPaymentError("")
|
||||
case .validationFailed:
|
||||
fallthrough
|
||||
case .validationError:
|
||||
self?.statistics.logPaymentSuccess()
|
||||
self?.statistics.logValidationError(err == .validationFailed ? 0 : 2)
|
||||
}
|
||||
pingServer { [weak self] (success) in
|
||||
guard success else {
|
||||
self?.loadingView.isHidden = true
|
||||
let errorDialog = BookmarksSubscriptionFailViewController { [weak self] in
|
||||
self?.dismiss(animated: true)
|
||||
}
|
||||
MWMAlertViewController.activeAlert().presentInfoAlert(L("bookmarks_convert_error_title"),
|
||||
text: L("purchase_error_subtitle"))
|
||||
self?.present(errorDialog, animated: true)
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
self?.purchase.makePayment({ [weak self] (code, error) in
|
||||
self?.loadingView.isHidden = true
|
||||
switch(code) {
|
||||
case .success:
|
||||
self?.statistics.logPaymentSuccess()
|
||||
self?.statistics.logValidationSuccess()
|
||||
if let s = self { s.delegate?.didCompletePurchase(s) }
|
||||
case .userCancelled:
|
||||
// do nothing
|
||||
break
|
||||
case .error:
|
||||
if let err = error as? RoutePurchaseError {
|
||||
switch err {
|
||||
case .paymentError:
|
||||
self?.statistics.logPaymentError("")
|
||||
case .validationFailed:
|
||||
fallthrough
|
||||
case .validationError:
|
||||
self?.statistics.logPaymentSuccess()
|
||||
self?.statistics.logValidationError(err == .validationFailed ? 0 : 2)
|
||||
}
|
||||
}
|
||||
MWMAlertViewController.activeAlert().presentInfoAlert(L("bookmarks_convert_error_title"),
|
||||
text: L("purchase_error_subtitle"))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func onSubscribe(_ sender: UIButton) {
|
||||
guard let subscription = subscription else {
|
||||
assertionFailure("Subscription can't be nil")
|
||||
return
|
||||
}
|
||||
|
||||
loadingView.isHidden = false
|
||||
pingServer { [weak self] (success) in
|
||||
guard success else {
|
||||
self?.loadingView.isHidden = true
|
||||
let errorDialog = BookmarksSubscriptionFailViewController { [weak self] in
|
||||
self?.dismiss(animated: true)
|
||||
}
|
||||
self?.present(errorDialog, animated: true)
|
||||
return
|
||||
}
|
||||
|
||||
self?.subscriptionManager.subscribe(to: subscription)
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func onCancel(_ sender: UIButton) {
|
||||
statistics.logCancel()
|
||||
delegate?.didCancelPurchase(self)
|
||||
}
|
||||
|
||||
@IBAction func onTerms(_ sender: UIButton) {
|
||||
guard let url = URL(string: MWMAuthorizationViewModel.termsOfUseLink()) else { return }
|
||||
let safari = SFSafariViewController(url: url)
|
||||
self.present(safari, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@IBAction func onPrivacy(_ sender: UIButton) {
|
||||
guard let url = URL(string: MWMAuthorizationViewModel.privacyPolicyLink()) else { return }
|
||||
let safari = SFSafariViewController(url: url)
|
||||
self.present(safari, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
extension PaidRouteViewController : SubscriptionManagerListener {
|
||||
func didFailToSubscribe(_ subscription: ISubscription, error: Error?) {
|
||||
loadingView.isHidden = true
|
||||
}
|
||||
|
||||
func didSubsribe(_ subscription: ISubscription) {
|
||||
loadingView.isHidden = true
|
||||
delegate?.didCompleteSubscription(self)
|
||||
let successDialog = BookmarksSubscriptionSuccessViewController { [weak self] in
|
||||
self?.dismiss(animated: true)
|
||||
}
|
||||
present(successDialog, animated: true)
|
||||
}
|
||||
|
||||
func didFailToValidate(_ subscription: ISubscription, error: Error?) {
|
||||
loadingView.isHidden = true
|
||||
}
|
||||
|
||||
func didDefer(_ subscription: ISubscription) {
|
||||
loadingView.isHidden = true
|
||||
}
|
||||
|
||||
func validationError() {
|
||||
loadingView.isHidden = true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,48 +1,48 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="landscape">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="PaidRouteViewController" customModule="maps_me" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="buyButton" destination="1XW-gh-X68" id="cow-ZC-jpu"/>
|
||||
<outlet property="cancelButton" destination="Y4X-z8-enR" id="mDn-Yz-e77"/>
|
||||
<outlet property="buyButton" destination="Y4X-z8-enR" id="mDn-Yz-e77"/>
|
||||
<outlet property="loadingIndicator" destination="Yat-hc-p6d" id="8aX-Nj-New"/>
|
||||
<outlet property="loadingView" destination="I10-rL-z9q" id="27n-ZW-Q7a"/>
|
||||
<outlet property="previewImageView" destination="wJO-dJ-F8G" id="s2t-aS-INP"/>
|
||||
<outlet property="productNameLabel" destination="Pwv-EO-6fY" id="U5q-xr-CyD"/>
|
||||
<outlet property="routeAuthorLabel" destination="H6m-mO-TFt" id="GE3-sO-eOC"/>
|
||||
<outlet property="routeTitleLabel" destination="4PP-cK-o7Y" id="Nez-Ie-dZl"/>
|
||||
<outlet property="subscribeButton" destination="1XW-gh-X68" id="cow-ZC-jpu"/>
|
||||
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" verticalCompressionResistancePriority="749" image="img_guides_placeholder" translatesAutoresizingMaskIntoConstraints="NO" id="1jX-9f-swC">
|
||||
<rect key="frame" x="0.0" y="-151" width="347" height="526"/>
|
||||
<rect key="frame" x="0.0" y="-328" width="375" height="568.5"/>
|
||||
<color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="1jX-9f-swC" secondAttribute="height" multiplier="500:758" id="ZSu-8v-nw1"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="wJO-dJ-F8G">
|
||||
<rect key="frame" x="0.0" y="0.0" width="347" height="375"/>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="wJO-dJ-F8G">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="240.5"/>
|
||||
</imageView>
|
||||
<view contentMode="scaleToFill" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" translatesAutoresizingMaskIntoConstraints="NO" id="pbL-bL-mXm">
|
||||
<rect key="frame" x="347" y="0.0" width="320" height="375"/>
|
||||
<rect key="frame" x="0.0" y="240.5" width="375" height="426.5"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="752" text="..." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Pwv-EO-6fY">
|
||||
<rect key="frame" x="24" y="24" width="272" height="17"/>
|
||||
<rect key="frame" x="24" y="24" width="327" height="17"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
|
||||
<color key="textColor" white="0.0" alpha="0.37553510273972601" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
|
@ -52,7 +52,7 @@
|
|||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="YlO-Qt-ILN">
|
||||
<rect key="frame" x="0.0" y="57" width="320" height="1"/>
|
||||
<rect key="frame" x="0.0" y="57" width="375" height="1"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.1210134845890411" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="1" id="LSa-3h-jdQ"/>
|
||||
|
@ -62,7 +62,7 @@
|
|||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="751" text="Have a dinner with Hemingway and Castro in Havana" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4PP-cK-o7Y">
|
||||
<rect key="frame" x="24" y="74" width="272" height="79"/>
|
||||
<rect key="frame" x="24" y="74" width="327" height="53"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="22"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
|
@ -73,7 +73,7 @@
|
|||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="752" text="by Julio Mulio" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="H6m-mO-TFt">
|
||||
<rect key="frame" x="24" y="169" width="272" height="17"/>
|
||||
<rect key="frame" x="24" y="143" width="327" height="17"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<color key="textColor" white="0.0" alpha="0.87625749143835618" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
|
@ -84,7 +84,7 @@
|
|||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" verticalCompressionResistancePriority="751" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1XW-gh-X68" userLabel="Download Bookmarks">
|
||||
<rect key="frame" x="24" y="249" width="272" height="48"/>
|
||||
<rect key="frame" x="24" y="184" width="327" height="48"/>
|
||||
<color key="backgroundColor" red="0.11764705882352941" green="0.58823529411764708" blue="0.94117647058823528" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="48" id="d2Y-HN-jxk"/>
|
||||
|
@ -105,17 +105,17 @@
|
|||
<userDefinedRuntimeAttribute type="string" keyPath="backgroundHighlightedColorName" value="linkBlueHighlighted"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="onBuy:" destination="-1" eventType="touchUpInside" id="qe7-u9-2lq"/>
|
||||
<action selector="onSubscribe:" destination="-1" eventType="touchUpInside" id="vKT-Jw-oYb"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" verticalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Y4X-z8-enR" userLabel="Cancel">
|
||||
<rect key="frame" x="24" y="307" width="272" height="48"/>
|
||||
<button hidden="YES" opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" verticalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Y4X-z8-enR" userLabel="Buy">
|
||||
<rect key="frame" x="24" y="242" width="327" height="48"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="48" id="bWF-O1-9Gw"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
|
||||
<state key="normal" title="CANCEL">
|
||||
<state key="normal" title="Buy">
|
||||
<color key="titleColor" red="0.11764705882352941" green="0.58823529411764708" blue="0.94117647058823528" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
|
@ -123,18 +123,76 @@
|
|||
<userDefinedRuntimeAttribute type="string" keyPath="textColorHighlightedName" value="linkBlueHighlighted"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium14"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="linkBlue"/>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="layer.borderWidth">
|
||||
<integer key="value" value="1"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
|
||||
<integer key="value" value="8"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="onCancel:" destination="-1" eventType="touchUpInside" id="Aiq-i7-muw"/>
|
||||
<action selector="onBuy:" destination="-1" eventType="touchUpInside" id="2iV-Mk-Qcg"/>
|
||||
</connections>
|
||||
</button>
|
||||
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" animating="YES" style="white" translatesAutoresizingMaskIntoConstraints="NO" id="Yat-hc-p6d">
|
||||
<rect key="frame" x="150" y="263" width="20" height="20"/>
|
||||
<rect key="frame" x="177.5" y="198" width="20" height="20"/>
|
||||
</activityIndicatorView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="justified" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ikF-tk-1jf">
|
||||
<rect key="frame" x="20" y="322" width="335" height="64.5"/>
|
||||
<string key="text">Payment will be charged to your iTunes account at confirmation of purchase. The subscription will automatically renew unless auto-renew is turned off at least 24 hours before the end of the current period. Your account will be charged according to your plan for renewal within 24 hours prior to the end of the current period. You can manage or turn off auto-renew in your Apple ID account settings at any time of your purchase.</string>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="9"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="subscription_terms"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular9"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="afE-a3-MQI">
|
||||
<rect key="frame" x="20" y="386.5" width="64" height="32"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="32" id="gYt-Pg-xeh"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="10"/>
|
||||
<state key="normal" title="Terms of Use">
|
||||
<color key="titleColor" white="0.33896576909169757" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="blackSecondaryText"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorHighlightedName" value="blackHintText"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="terms_of_use"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium10"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="onTerms:" destination="-1" eventType="touchUpInside" id="9bk-bP-2bT"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tUc-za-PqS">
|
||||
<rect key="frame" x="288" y="386" width="67" height="32"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="32" id="nHF-aZ-Dei"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="10"/>
|
||||
<state key="normal" title="Privacy Policy">
|
||||
<color key="titleColor" white="0.33896576909999998" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="blackSecondaryText"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorHighlightedName" value="blackHintText"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="privacy_policy"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium10"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="onPrivacy:" destination="-1" eventType="touchUpInside" id="E7z-WW-KLD"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="1XW-gh-X68" firstAttribute="top" secondItem="H6m-mO-TFt" secondAttribute="bottom" constant="24" id="1nC-WD-vB2"/>
|
||||
<constraint firstItem="tUc-za-PqS" firstAttribute="top" secondItem="ikF-tk-1jf" secondAttribute="bottom" constant="-0.5" id="2eY-eY-1sc"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ikF-tk-1jf" secondAttribute="trailing" constant="20" id="2tF-nx-UZd"/>
|
||||
<constraint firstAttribute="trailing" secondItem="4PP-cK-o7Y" secondAttribute="trailing" constant="24" id="4xL-CV-ajm"/>
|
||||
<constraint firstItem="Yat-hc-p6d" firstAttribute="centerX" secondItem="1XW-gh-X68" secondAttribute="centerX" id="5f5-9e-OVx"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Y4X-z8-enR" secondAttribute="bottom" constant="20" id="6Nn-2Z-pMJ"/>
|
||||
|
@ -144,16 +202,23 @@
|
|||
<constraint firstItem="Y4X-z8-enR" firstAttribute="top" secondItem="1XW-gh-X68" secondAttribute="bottom" constant="10" id="J37-yJ-FbX"/>
|
||||
<constraint firstAttribute="trailing" secondItem="H6m-mO-TFt" secondAttribute="trailing" constant="24" id="LdF-m9-WSx"/>
|
||||
<constraint firstItem="1XW-gh-X68" firstAttribute="leading" secondItem="pbL-bL-mXm" secondAttribute="leading" constant="24" id="LjP-ao-BSn"/>
|
||||
<constraint firstItem="afE-a3-MQI" firstAttribute="leading" secondItem="pbL-bL-mXm" secondAttribute="leading" constant="20" id="OBq-CH-Zpa"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="Y4X-z8-enR" secondAttribute="bottom" constant="20" id="OVB-BO-VES"/>
|
||||
<constraint firstItem="4PP-cK-o7Y" firstAttribute="leading" secondItem="pbL-bL-mXm" secondAttribute="leading" constant="24" id="OZR-83-PnQ"/>
|
||||
<constraint firstItem="Pwv-EO-6fY" firstAttribute="leading" secondItem="pbL-bL-mXm" secondAttribute="leading" constant="24" id="Tef-z9-YKR"/>
|
||||
<constraint firstItem="ikF-tk-1jf" firstAttribute="leading" secondItem="pbL-bL-mXm" secondAttribute="leading" constant="20" id="ToO-K0-28K"/>
|
||||
<constraint firstItem="ikF-tk-1jf" firstAttribute="top" secondItem="Y4X-z8-enR" secondAttribute="bottom" constant="32" id="UPO-vm-fov"/>
|
||||
<constraint firstItem="H6m-mO-TFt" firstAttribute="top" secondItem="4PP-cK-o7Y" secondAttribute="bottom" constant="16" id="VUK-J3-9b6"/>
|
||||
<constraint firstAttribute="bottom" secondItem="afE-a3-MQI" secondAttribute="bottom" constant="8" id="Vs1-l6-wPB"/>
|
||||
<constraint firstItem="4PP-cK-o7Y" firstAttribute="top" secondItem="YlO-Qt-ILN" secondAttribute="bottom" constant="16" id="X0e-7m-70r"/>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="320" id="XFv-Yx-Vqq"/>
|
||||
<constraint firstItem="YlO-Qt-ILN" firstAttribute="leading" secondItem="pbL-bL-mXm" secondAttribute="leading" id="Xg6-LW-vkM"/>
|
||||
<constraint firstItem="afE-a3-MQI" firstAttribute="top" secondItem="ikF-tk-1jf" secondAttribute="bottom" id="Z7z-mj-Nhj"/>
|
||||
<constraint firstAttribute="trailing" secondItem="YlO-Qt-ILN" secondAttribute="trailing" id="ZBb-Do-uIF"/>
|
||||
<constraint firstItem="Y4X-z8-enR" firstAttribute="leading" secondItem="pbL-bL-mXm" secondAttribute="leading" constant="24" id="ZhJ-OI-Xmb"/>
|
||||
<constraint firstItem="tUc-za-PqS" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="afE-a3-MQI" secondAttribute="trailing" constant="8" id="kDq-QT-7G7"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Y4X-z8-enR" secondAttribute="trailing" constant="24" id="pkv-4M-Hkz"/>
|
||||
<constraint firstAttribute="trailing" secondItem="tUc-za-PqS" secondAttribute="trailing" constant="20" id="rAI-Ah-Nuq"/>
|
||||
<constraint firstItem="Pwv-EO-6fY" firstAttribute="top" secondItem="pbL-bL-mXm" secondAttribute="top" constant="24" id="rXv-4V-rsi"/>
|
||||
<constraint firstAttribute="trailing" secondItem="1XW-gh-X68" secondAttribute="trailing" constant="24" id="rZ9-Tb-hR9"/>
|
||||
<constraint firstItem="YlO-Qt-ILN" firstAttribute="top" secondItem="Pwv-EO-6fY" secondAttribute="bottom" constant="16" id="tMZ-C2-gJP"/>
|
||||
|
@ -190,23 +255,42 @@
|
|||
<variation key="heightClass=regular-widthClass=compact">
|
||||
<mask key="constraints">
|
||||
<include reference="1nC-WD-vB2"/>
|
||||
<include reference="HyU-X4-NLs"/>
|
||||
<include reference="OVB-BO-VES"/>
|
||||
<exclude reference="HyU-X4-NLs"/>
|
||||
<exclude reference="OVB-BO-VES"/>
|
||||
</mask>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular">
|
||||
<mask key="constraints">
|
||||
<include reference="1nC-WD-vB2"/>
|
||||
<include reference="HyU-X4-NLs"/>
|
||||
<include reference="OVB-BO-VES"/>
|
||||
<exclude reference="HyU-X4-NLs"/>
|
||||
<exclude reference="OVB-BO-VES"/>
|
||||
</mask>
|
||||
</variation>
|
||||
</view>
|
||||
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cG9-gK-iOG">
|
||||
<rect key="frame" x="333" y="30" width="32" height="32"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="32" id="6l2-ll-cL4"/>
|
||||
<constraint firstAttribute="width" constant="32" id="g23-yb-Dr8"/>
|
||||
</constraints>
|
||||
<state key="normal" image="ic_close_spinner"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
|
||||
<integer key="value" value="16"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="tintColorName" value="linkBlue"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="onCancel:" destination="-1" eventType="touchUpInside" id="qqu-Pr-Tyn"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="I10-rL-z9q">
|
||||
<rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<subviews>
|
||||
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" animating="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="m8U-2p-bdf">
|
||||
<rect key="frame" x="315" y="169" width="37" height="37"/>
|
||||
<rect key="frame" x="169" y="315" width="37" height="37"/>
|
||||
<color key="color" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</activityIndicatorView>
|
||||
</subviews>
|
||||
|
@ -224,22 +308,24 @@
|
|||
<constraints>
|
||||
<constraint firstItem="1jX-9f-swC" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="0as-MJ-IuO"/>
|
||||
<constraint firstItem="I10-rL-z9q" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="1ok-WA-uNG"/>
|
||||
<constraint firstItem="pbL-bL-mXm" firstAttribute="top" secondItem="wJO-dJ-F8G" secondAttribute="bottom" id="2lg-Fd-ggP"/>
|
||||
<constraint firstItem="wJO-dJ-F8G" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="3sj-tj-YDX"/>
|
||||
<constraint firstAttribute="trailing" secondItem="wJO-dJ-F8G" secondAttribute="trailing" id="7vQ-mS-aXd"/>
|
||||
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="cG9-gK-iOG" secondAttribute="trailing" constant="10" id="BYt-6e-15L"/>
|
||||
<constraint firstItem="I10-rL-z9q" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" id="Gtb-Sq-SC0"/>
|
||||
<constraint firstItem="fnl-2z-Ty3" firstAttribute="bottom" secondItem="pbL-bL-mXm" secondAttribute="bottom" id="Lrf-Mc-vHX"/>
|
||||
<constraint firstAttribute="bottom" secondItem="1jX-9f-swC" secondAttribute="bottom" id="M6z-RM-5RE"/>
|
||||
<constraint firstItem="pbL-bL-mXm" firstAttribute="leading" secondItem="1jX-9f-swC" secondAttribute="trailing" id="Xht-Dc-57g"/>
|
||||
<constraint firstItem="wJO-dJ-F8G" firstAttribute="bottom" secondItem="1jX-9f-swC" secondAttribute="bottom" id="Yzc-lV-S0m"/>
|
||||
<constraint firstAttribute="trailing" secondItem="1jX-9f-swC" secondAttribute="trailing" id="ZKR-uE-TDM"/>
|
||||
<constraint firstAttribute="bottom" secondItem="I10-rL-z9q" secondAttribute="bottom" id="b85-Qx-MiP"/>
|
||||
<constraint firstItem="wJO-dJ-F8G" firstAttribute="trailing" secondItem="1jX-9f-swC" secondAttribute="trailing" id="cgA-qO-qjx"/>
|
||||
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="pbL-bL-mXm" secondAttribute="trailing" id="ezH-PS-MTK"/>
|
||||
<constraint firstItem="wJO-dJ-F8G" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" id="f00-G7-pcI"/>
|
||||
<constraint firstItem="1jX-9f-swC" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" id="gJB-J9-Wvt"/>
|
||||
<constraint firstItem="pbL-bL-mXm" firstAttribute="top" secondItem="1jX-9f-swC" secondAttribute="bottom" id="mbr-U9-QqH"/>
|
||||
<constraint firstItem="pbL-bL-mXm" firstAttribute="top" relation="greaterThanOrEqual" secondItem="fnl-2z-Ty3" secondAttribute="top" id="mcX-zM-axH"/>
|
||||
<constraint firstItem="pbL-bL-mXm" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" id="pel-8r-WlL"/>
|
||||
<constraint firstItem="wJO-dJ-F8G" firstAttribute="leading" secondItem="1jX-9f-swC" secondAttribute="leading" id="pv1-4b-pAr"/>
|
||||
<constraint firstAttribute="trailing" secondItem="I10-rL-z9q" secondAttribute="trailing" id="qDe-SK-EBd"/>
|
||||
<constraint firstItem="cG9-gK-iOG" firstAttribute="top" secondItem="fnl-2z-Ty3" secondAttribute="top" constant="10" id="rgT-al-yRC"/>
|
||||
<constraint firstItem="pbL-bL-mXm" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="skf-ew-o90"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
|
||||
|
@ -248,50 +334,51 @@
|
|||
</userDefinedRuntimeAttributes>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="0as-MJ-IuO"/>
|
||||
<exclude reference="M6z-RM-5RE"/>
|
||||
<exclude reference="ZKR-uE-TDM"/>
|
||||
<exclude reference="Xht-Dc-57g"/>
|
||||
<exclude reference="mbr-U9-QqH"/>
|
||||
<exclude reference="mcX-zM-axH"/>
|
||||
<exclude reference="pel-8r-WlL"/>
|
||||
<exclude reference="skf-ew-o90"/>
|
||||
<exclude reference="0as-MJ-IuO"/>
|
||||
<exclude reference="M6z-RM-5RE"/>
|
||||
<exclude reference="ZKR-uE-TDM"/>
|
||||
</mask>
|
||||
</variation>
|
||||
<variation key="heightClass=compact-widthClass=compact">
|
||||
<mask key="constraints">
|
||||
<include reference="M6z-RM-5RE"/>
|
||||
<include reference="Xht-Dc-57g"/>
|
||||
<include reference="skf-ew-o90"/>
|
||||
<include reference="M6z-RM-5RE"/>
|
||||
</mask>
|
||||
</variation>
|
||||
<variation key="heightClass=compact-widthClass=regular">
|
||||
<mask key="constraints">
|
||||
<include reference="M6z-RM-5RE"/>
|
||||
<include reference="Xht-Dc-57g"/>
|
||||
<include reference="skf-ew-o90"/>
|
||||
<include reference="M6z-RM-5RE"/>
|
||||
</mask>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=compact">
|
||||
<mask key="constraints">
|
||||
<include reference="ZKR-uE-TDM"/>
|
||||
<include reference="mbr-U9-QqH"/>
|
||||
<include reference="mcX-zM-axH"/>
|
||||
<include reference="pel-8r-WlL"/>
|
||||
<include reference="ZKR-uE-TDM"/>
|
||||
</mask>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular">
|
||||
<mask key="constraints">
|
||||
<include reference="ZKR-uE-TDM"/>
|
||||
<include reference="mbr-U9-QqH"/>
|
||||
<include reference="mcX-zM-axH"/>
|
||||
<include reference="pel-8r-WlL"/>
|
||||
<include reference="ZKR-uE-TDM"/>
|
||||
</mask>
|
||||
</variation>
|
||||
<point key="canvasLocation" x="136.80000000000001" y="150.67466266866569"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="ic_close_spinner" width="28" height="28"/>
|
||||
<image name="img_guides_placeholder" width="500" height="758"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
|
|
@ -248,7 +248,7 @@ using namespace osm_auth_ios;
|
|||
[UNUserNotificationCenter currentNotificationCenter].delegate = self.notificationManager;
|
||||
|
||||
if ([MWMFrameworkHelper isWiFiConnected]) {
|
||||
[[SubscriptionManager shared] validate];
|
||||
[[InAppPurchase adsRemovalSubscriptionManager] validate];
|
||||
self.pendingTransactionHandler = [InAppPurchase pendingTransactionsHandler];
|
||||
__weak __typeof(self) ws = self;
|
||||
[self.pendingTransactionHandler handlePendingTransactions:^(PendingTransactionsStatus) {
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef void (^LoadTagsCompletionBlock)(NSArray<MWMTagGroup *> * _Nullable tags, NSInteger maxTagsNumber);
|
||||
typedef void (^PingCompletionBlock)(BOOL success);
|
||||
|
||||
@interface MWMBookmarksManager : NSObject
|
||||
|
||||
|
@ -93,6 +94,7 @@ typedef void (^LoadTagsCompletionBlock)(NSArray<MWMTagGroup *> * _Nullable tags,
|
|||
- (void)uploadCategoryWithId:(MWMMarkGroupID)itemId
|
||||
progress:(_Nullable ProgressBlock)progress
|
||||
completion:(UploadCompletionBlock)completion;
|
||||
- (void)ping:(PingCompletionBlock)callback;
|
||||
|
||||
- (instancetype)init __attribute__((unavailable("call +manager instead")));
|
||||
- (instancetype)copy __attribute__((unavailable("call +manager instead")));
|
||||
|
|
|
@ -725,6 +725,12 @@ NSString * const CloudErrorToString(Cloud::SynchronizationResult result)
|
|||
}
|
||||
}
|
||||
|
||||
- (void)ping:(PingCompletionBlock)callback {
|
||||
self.bm.GetCatalog().Ping([callback] (bool success) {
|
||||
callback(success);
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Helpers
|
||||
|
||||
- (void)loopObservers:(void (^)(id<MWMBookmarksObserver> observer))block
|
||||
|
|
|
@ -35,6 +35,8 @@ final class InAppBilling: NSObject, IInAppBilling {
|
|||
}
|
||||
|
||||
deinit {
|
||||
productRequest?.cancel()
|
||||
productRequest?.delegate = nil
|
||||
SKPaymentQueue.default().remove(self)
|
||||
}
|
||||
|
||||
|
|
|
@ -15,11 +15,9 @@ final class PendingTransactionsHandler: IPendingTransactionsHandler {
|
|||
case .paid:
|
||||
purchaseValidation.validateReceipt("") { [weak self] in
|
||||
switch $0 {
|
||||
case .valid:
|
||||
case .valid, .notValid:
|
||||
completion(.success)
|
||||
self?.pendingTransaction.finishTransaction()
|
||||
case .notValid:
|
||||
fallthrough
|
||||
case .error:
|
||||
completion(.error)
|
||||
case .authError:
|
||||
|
|
|
@ -25,4 +25,16 @@ final class InAppPurchase: NSObject {
|
|||
static func inAppBilling() -> IInAppBilling {
|
||||
return InAppBilling()
|
||||
}
|
||||
|
||||
@objc static var adsRemovalSubscriptionManager: SubscriptionManager = {
|
||||
return SubscriptionManager(productIds: MWMPurchaseManager.productIds(),
|
||||
serverId: MWMPurchaseManager.adsRemovalServerId(),
|
||||
vendorId: MWMPurchaseManager.adsRemovalVendorId())
|
||||
} ()
|
||||
|
||||
@objc static var bookmarksSubscriptionManager: SubscriptionManager = {
|
||||
return SubscriptionManager(productIds: MWMPurchaseManager.bookmakrsProductIds(),
|
||||
serverId: MWMPurchaseManager.bookmarksSubscriptionServerId(),
|
||||
vendorId: MWMPurchaseManager.bookmarksSubscriptionVendorId())
|
||||
} ()
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@ typedef void (^StartTransactionCallback)(BOOL success, NSString * serverId);
|
|||
|
||||
@interface MWMPurchaseManager : NSObject
|
||||
|
||||
+ (NSString *)bookmarksSubscriptionServerId;
|
||||
+ (NSString *)bookmarksSubscriptionVendorId;
|
||||
+ (NSArray<NSString *> *)bookmakrsProductIds;
|
||||
+ (NSString *)adsRemovalServerId;
|
||||
+ (NSString *)adsRemovalVendorId;
|
||||
+ (NSArray<NSString *> *)productIds;
|
||||
|
@ -24,6 +27,7 @@ typedef void (^StartTransactionCallback)(BOOL success, NSString * serverId);
|
|||
+ (MWMPurchaseManager *)sharedManager;
|
||||
|
||||
- (void)validateReceipt:(NSString *)serverId
|
||||
vendorId:(NSString *)vendorId
|
||||
refreshReceipt:(BOOL)refresh
|
||||
callback:(ValidateReceiptCallback)callback;
|
||||
- (void)startTransaction:(NSString *)serverId callback:(StartTransactionCallback)callback;
|
||||
|
|
|
@ -10,11 +10,28 @@
|
|||
@property(nonatomic, copy) ValidateReceiptCallback callback;
|
||||
@property(nonatomic) SKReceiptRefreshRequest *receiptRequest;
|
||||
@property(nonatomic, copy) NSString * serverId;
|
||||
@property(nonatomic, copy) NSString * vendorId;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MWMPurchaseManager
|
||||
|
||||
+ (NSString *)bookmarksSubscriptionServerId
|
||||
{
|
||||
return @(BOOKMARKS_SUBSCRIPTION_SERVER_ID);
|
||||
}
|
||||
|
||||
+ (NSString *)bookmarksSubscriptionVendorId
|
||||
{
|
||||
return @(BOOKMARKS_SUBSCRIPTION_VENDOR);
|
||||
}
|
||||
|
||||
+ (NSArray *)bookmakrsProductIds
|
||||
{
|
||||
return @[@(BOOKMARKS_SUBSCRIPTION_YEARLY_PRODUCT_ID),
|
||||
@(BOOKMARKS_SUBSCRIPTION_MONTHLY_PRODUCT_ID)];
|
||||
}
|
||||
|
||||
+ (NSString *)adsRemovalServerId
|
||||
{
|
||||
return @(ADS_REMOVAL_SERVER_ID);
|
||||
|
@ -27,9 +44,9 @@
|
|||
|
||||
+ (NSArray *)productIds
|
||||
{
|
||||
return @[@(ADS_REMOVAL_WEEKLY_PRODUCT_ID),
|
||||
return @[@(ADS_REMOVAL_YEARLY_PRODUCT_ID),
|
||||
@(ADS_REMOVAL_MONTHLY_PRODUCT_ID),
|
||||
@(ADS_REMOVAL_YEARLY_PRODUCT_ID)];
|
||||
@(ADS_REMOVAL_WEEKLY_PRODUCT_ID)];
|
||||
}
|
||||
|
||||
+ (NSArray *)legacyProductIds
|
||||
|
@ -70,11 +87,13 @@
|
|||
}
|
||||
|
||||
- (void)validateReceipt:(NSString *)serverId
|
||||
vendorId:(NSString *)vendorId
|
||||
refreshReceipt:(BOOL)refresh
|
||||
callback:(ValidateReceiptCallback)callback
|
||||
{
|
||||
self.callback = callback;
|
||||
self.serverId = serverId;
|
||||
self.vendorId = vendorId;
|
||||
[self validateReceipt:refresh];
|
||||
}
|
||||
|
||||
|
@ -112,7 +131,7 @@
|
|||
Purchase::ValidationInfo vi;
|
||||
vi.m_receiptData = [receiptData base64EncodedStringWithOptions:0].UTF8String;
|
||||
vi.m_serverId = self.serverId.UTF8String;
|
||||
vi.m_vendorId = ADS_REMOVAL_VENDOR;
|
||||
vi.m_vendorId = self.vendorId.UTF8String;
|
||||
auto const accessToken = GetFramework().GetUser().GetAccessToken();
|
||||
GetFramework().GetPurchase()->Validate(vi, accessToken);
|
||||
}
|
||||
|
|
|
@ -7,20 +7,22 @@
|
|||
|
||||
@objc protocol ISubscription {
|
||||
var productId: String { get }
|
||||
var price: NSDecimalNumber? { get }
|
||||
var price: NSDecimalNumber { get }
|
||||
var priceLocale: Locale? { get }
|
||||
var period: SubscriptionPeriod { get }
|
||||
}
|
||||
|
||||
class Subscription: ISubscription {
|
||||
public static let productIds = MWMPurchaseManager.productIds()
|
||||
public static let productIds = MWMPurchaseManager.productIds() + MWMPurchaseManager.bookmakrsProductIds()
|
||||
public static let legacyProductIds = MWMPurchaseManager.legacyProductIds()
|
||||
private static let periodMap: [String: SubscriptionPeriod] = [productIds[0]: .week,
|
||||
private static let periodMap: [String: SubscriptionPeriod] = [productIds[0]: .year,
|
||||
productIds[1]: .month,
|
||||
productIds[2]: .year]
|
||||
productIds[2]: .week,
|
||||
productIds[3]: .year,
|
||||
productIds[4]: .month]
|
||||
var productId: String
|
||||
var period: SubscriptionPeriod
|
||||
var price: NSDecimalNumber?
|
||||
var price: NSDecimalNumber
|
||||
var priceLocale: Locale?
|
||||
|
||||
init(_ product: SKProduct) {
|
||||
|
|
|
@ -10,7 +10,7 @@ class SubscriptionManager: NSObject {
|
|||
typealias SuscriptionsCompletion = ([ISubscription]?, Error?) -> Void
|
||||
typealias RestorationCompletion = (MWMValidationResult) -> Void
|
||||
|
||||
@objc static var shared: SubscriptionManager = { return SubscriptionManager() }()
|
||||
// @objc static var shared: SubscriptionManager = { return SubscriptionManager() }()
|
||||
|
||||
private let paymentQueue = SKPaymentQueue.default()
|
||||
|
||||
|
@ -21,6 +21,17 @@ class SubscriptionManager: NSObject {
|
|||
private var listeners = NSHashTable<SubscriptionManagerListener>.weakObjects()
|
||||
private var restorationCallback: RestorationCompletion?
|
||||
|
||||
private var productIds: [String] = []
|
||||
private var serverId: String = ""
|
||||
private var vendorId: String = ""
|
||||
|
||||
convenience init(productIds: [String], serverId: String, vendorId: String) {
|
||||
self.init()
|
||||
self.productIds = productIds
|
||||
self.serverId = serverId
|
||||
self.vendorId = vendorId
|
||||
}
|
||||
|
||||
override private init() {
|
||||
super.init()
|
||||
paymentQueue.add(self)
|
||||
|
@ -36,7 +47,7 @@ class SubscriptionManager: NSObject {
|
|||
|
||||
@objc func getAvailableSubscriptions(_ completion: @escaping SuscriptionsCompletion){
|
||||
subscriptionsComplection = completion
|
||||
productsRequest = SKProductsRequest(productIdentifiers: Set(Subscription.productIds))
|
||||
productsRequest = SKProductsRequest(productIdentifiers: Set(productIds))
|
||||
productsRequest!.delegate = self
|
||||
productsRequest!.start()
|
||||
}
|
||||
|
@ -66,19 +77,18 @@ class SubscriptionManager: NSObject {
|
|||
|
||||
private func validate(_ refreshReceipt: Bool) {
|
||||
MWMPurchaseManager.shared()
|
||||
.validateReceipt(MWMPurchaseManager.adsRemovalServerId(),
|
||||
refreshReceipt: refreshReceipt) { (_, validationResult) in
|
||||
self.logEvents(validationResult)
|
||||
.validateReceipt(serverId, vendorId: vendorId, refreshReceipt: refreshReceipt) { [weak self] (_, validationResult) in
|
||||
self?.logEvents(validationResult)
|
||||
if validationResult == .valid || validationResult == .notValid {
|
||||
MWMPurchaseManager.shared().setAdsDisabled(validationResult == .valid)
|
||||
self.paymentQueue.transactions
|
||||
.filter { Subscription.productIds.contains($0.payment.productIdentifier) &&
|
||||
self?.paymentQueue.transactions
|
||||
.filter { self?.productIds.contains($0.payment.productIdentifier) ?? false &&
|
||||
($0.transactionState == .purchased || $0.transactionState == .restored) }
|
||||
.forEach { self.paymentQueue.finishTransaction($0) }
|
||||
.forEach { self?.paymentQueue.finishTransaction($0) }
|
||||
}
|
||||
|
||||
self.restorationCallback?(validationResult)
|
||||
self.restorationCallback = nil
|
||||
self?.restorationCallback?(validationResult)
|
||||
self?.restorationCallback = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +97,7 @@ class SubscriptionManager: NSObject {
|
|||
case .valid:
|
||||
Statistics.logEvent(kStatInappValidationSuccess)
|
||||
Statistics.logEvent(kStatInappProductDelivered,
|
||||
withParameters: [kStatVendor : MWMPurchaseManager.adsRemovalVendorId()])
|
||||
withParameters: [kStatVendor : vendorId])
|
||||
case .notValid:
|
||||
Statistics.logEvent(kStatInappValidationError, withParameters: [kStatErrorCode : 0])
|
||||
case .serverError:
|
||||
|
@ -108,14 +118,14 @@ extension SubscriptionManager: SKProductsRequestDelegate {
|
|||
}
|
||||
|
||||
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
|
||||
guard response.products.count == 3 else {
|
||||
guard response.products.count == productIds.count else {
|
||||
subscriptionsComplection?(nil, NSError(domain: "mapsme.subscriptions", code: -1, userInfo: nil))
|
||||
subscriptionsComplection = nil
|
||||
productsRequest = nil
|
||||
return
|
||||
}
|
||||
let subscriptions = response.products.map { Subscription($0) }
|
||||
.sorted { $0.period.rawValue > $1.period.rawValue }
|
||||
.sorted { $0.period.rawValue < $1.period.rawValue }
|
||||
products = Dictionary(uniqueKeysWithValues: response.products.map { ($0.productIdentifier, $0) })
|
||||
subscriptionsComplection?(subscriptions, nil)
|
||||
subscriptionsComplection = nil
|
||||
|
@ -126,7 +136,7 @@ extension SubscriptionManager: SKProductsRequestDelegate {
|
|||
extension SubscriptionManager: SKPaymentTransactionObserver {
|
||||
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
|
||||
let subscriptionTransactions = transactions.filter {
|
||||
Subscription.productIds.contains($0.payment.productIdentifier)
|
||||
productIds.contains($0.payment.productIdentifier)
|
||||
}
|
||||
subscriptionTransactions
|
||||
.filter { $0.transactionState == .failed }
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "mappyStickersV0219Copy.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "mappyStickersV0219Copy@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "mappyStickersV0219Copy@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "mappyStickersV0217.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -429,6 +429,12 @@
|
|||
47C3DB582268CDDB00DF6F91 /* DeeplinkInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C3DB572268CDD800DF6F91 /* DeeplinkInfoViewController.swift */; };
|
||||
47C7F9732191E15A00C2760C /* InAppBilling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C7F9722191E15A00C2760C /* InAppBilling.swift */; };
|
||||
47C7F97521930F5300C2760C /* IInAppBilling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C7F97421930F5300C2760C /* IInAppBilling.swift */; };
|
||||
47C8789022DF525A00A772DA /* BookmarksSubscriptionSuccessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8788E22DF525A00A772DA /* BookmarksSubscriptionSuccessViewController.swift */; };
|
||||
47C8789122DF525A00A772DA /* BookmarksSubscriptionSuccessViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 47C8788F22DF525A00A772DA /* BookmarksSubscriptionSuccessViewController.xib */; };
|
||||
47C8789922DF622400A772DA /* BookmarksSubscriptionFailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8789722DF622400A772DA /* BookmarksSubscriptionFailViewController.swift */; };
|
||||
47C8789A22DF622400A772DA /* BookmarksSubscriptionFailViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 47C8789822DF622400A772DA /* BookmarksSubscriptionFailViewController.xib */; };
|
||||
47C8789D22DF662700A772DA /* BookmarksSubscriptionExpiredViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8789B22DF662700A772DA /* BookmarksSubscriptionExpiredViewController.swift */; };
|
||||
47C8789E22DF662700A772DA /* BookmarksSubscriptionExpiredViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 47C8789C22DF662700A772DA /* BookmarksSubscriptionExpiredViewController.xib */; };
|
||||
47D0026721999DA900F651A2 /* PendingTransactionsHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47D0026621999DA900F651A2 /* PendingTransactionsHandler.swift */; };
|
||||
47DF72B922520CE20004AB10 /* MWMRoutingOptions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 474902D9224A54EC008D71E0 /* MWMRoutingOptions.mm */; };
|
||||
47DF72BB225356BF0004AB10 /* DrivingOptions.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 47DF72BA225356BF0004AB10 /* DrivingOptions.storyboard */; };
|
||||
|
@ -1525,6 +1531,12 @@
|
|||
47C7F9722191E15A00C2760C /* InAppBilling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppBilling.swift; sourceTree = "<group>"; };
|
||||
47C7F97421930F5300C2760C /* IInAppBilling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IInAppBilling.swift; sourceTree = "<group>"; };
|
||||
47C7F976219310D800C2760C /* IMWMPurchaseValidation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IMWMPurchaseValidation.h; sourceTree = "<group>"; };
|
||||
47C8788E22DF525A00A772DA /* BookmarksSubscriptionSuccessViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksSubscriptionSuccessViewController.swift; sourceTree = "<group>"; };
|
||||
47C8788F22DF525A00A772DA /* BookmarksSubscriptionSuccessViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BookmarksSubscriptionSuccessViewController.xib; sourceTree = "<group>"; };
|
||||
47C8789722DF622400A772DA /* BookmarksSubscriptionFailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksSubscriptionFailViewController.swift; sourceTree = "<group>"; };
|
||||
47C8789822DF622400A772DA /* BookmarksSubscriptionFailViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BookmarksSubscriptionFailViewController.xib; sourceTree = "<group>"; };
|
||||
47C8789B22DF662700A772DA /* BookmarksSubscriptionExpiredViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksSubscriptionExpiredViewController.swift; sourceTree = "<group>"; };
|
||||
47C8789C22DF662700A772DA /* BookmarksSubscriptionExpiredViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BookmarksSubscriptionExpiredViewController.xib; sourceTree = "<group>"; };
|
||||
47D0026621999DA900F651A2 /* PendingTransactionsHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PendingTransactionsHandler.swift; sourceTree = "<group>"; };
|
||||
47DF72BA225356BF0004AB10 /* DrivingOptions.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = DrivingOptions.storyboard; sourceTree = "<group>"; };
|
||||
47E3C71F21108E9F008B3B27 /* BookmarksLoadedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksLoadedViewController.swift; sourceTree = "<group>"; };
|
||||
|
@ -2209,7 +2221,7 @@
|
|||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
29B97314FDCFA39411CA2CEA = {
|
||||
29B97314FDCFA39411CA2CEA /* Maps */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
47AEF83F2231249E00D20538 /* categories_brands.txt */,
|
||||
|
@ -3572,6 +3584,21 @@
|
|||
path = WebImage;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
47C8788D22DF522B00A772DA /* Dialogs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
47E3C71F21108E9F008B3B27 /* BookmarksLoadedViewController.swift */,
|
||||
47E3C72021108E9F008B3B27 /* BookmarksLoadedViewController.xib */,
|
||||
47C8788E22DF525A00A772DA /* BookmarksSubscriptionSuccessViewController.swift */,
|
||||
47C8788F22DF525A00A772DA /* BookmarksSubscriptionSuccessViewController.xib */,
|
||||
47C8789722DF622400A772DA /* BookmarksSubscriptionFailViewController.swift */,
|
||||
47C8789822DF622400A772DA /* BookmarksSubscriptionFailViewController.xib */,
|
||||
47C8789B22DF662700A772DA /* BookmarksSubscriptionExpiredViewController.swift */,
|
||||
47C8789C22DF662700A772DA /* BookmarksSubscriptionExpiredViewController.xib */,
|
||||
);
|
||||
path = Dialogs;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
47E3C7232111E2F8008B3B27 /* Modal */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -3625,6 +3652,7 @@
|
|||
B32FE73D20D283D600EF7446 /* Catalog */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
47C8788D22DF522B00A772DA /* Dialogs */,
|
||||
B32FE73E20D2844600EF7446 /* DownloadedBookmarksViewController.swift */,
|
||||
B32FE73F20D2844600EF7446 /* DownloadedBookmarksViewController.xib */,
|
||||
B32FE74220D2B09600EF7446 /* CatalogWebViewController.swift */,
|
||||
|
@ -3633,8 +3661,6 @@
|
|||
B366130320D5D9BC00E7DC3E /* MWMCategory.m */,
|
||||
B366130820D5E2E000E7DC3E /* CatalogCategoryCell.swift */,
|
||||
B366130920D5E2E000E7DC3E /* CatalogCategoryCell.xib */,
|
||||
47E3C71F21108E9F008B3B27 /* BookmarksLoadedViewController.swift */,
|
||||
47E3C72021108E9F008B3B27 /* BookmarksLoadedViewController.xib */,
|
||||
470F5A592181DE7400754295 /* PaidRouteViewController.swift */,
|
||||
470F5A5A2181DE7400754295 /* PaidRouteViewController.xib */,
|
||||
45AC339022C4F57C004DC574 /* MWMUTM.h */,
|
||||
|
@ -4789,7 +4815,7 @@
|
|||
"en-GB",
|
||||
el,
|
||||
);
|
||||
mainGroup = 29B97314FDCFA39411CA2CEA;
|
||||
mainGroup = 29B97314FDCFA39411CA2CEA /* Maps */;
|
||||
productRefGroup = 19C28FACFE9D520D11CA2CBB /* Products */;
|
||||
projectDirPath = "";
|
||||
projectReferences = (
|
||||
|
@ -4969,6 +4995,7 @@
|
|||
34AB66711FC5AA330078E451 /* TransportTransitTrain.xib in Resources */,
|
||||
33046836219C5A4E0041F3A8 /* CategorySettings.storyboard in Resources */,
|
||||
34BBD6471F82649D0070CA50 /* GoogleSignIn.bundle in Resources */,
|
||||
47C8789A22DF622400A772DA /* BookmarksSubscriptionFailViewController.xib in Resources */,
|
||||
47DF72BB225356BF0004AB10 /* DrivingOptions.storyboard in Resources */,
|
||||
F6E2FE851E097BA00083EBEC /* MWMPlacePageOpeningHoursWeekDayView.xib in Resources */,
|
||||
F6E2FE941E097BA00083EBEC /* PlacePageTaxiCell.xib in Resources */,
|
||||
|
@ -5040,7 +5067,9 @@
|
|||
6741A97D1BF340DE002C974C /* synonyms.txt in Resources */,
|
||||
34E50DF31F6FCC41008EED49 /* UGCYourReviewCell.xib in Resources */,
|
||||
CDB4D4D7222D248900104869 /* CarPlayStoryboard.storyboard in Resources */,
|
||||
47C8789122DF525A00A772DA /* BookmarksSubscriptionSuccessViewController.xib in Resources */,
|
||||
3476B8E11BFDD33A00874594 /* tts-how-to-set-up-voice-img in Resources */,
|
||||
47C8789E22DF662700A772DA /* BookmarksSubscriptionExpiredViewController.xib in Resources */,
|
||||
3476B8DD1BFDD30B00874594 /* tts-how-to-set-up-voice.html in Resources */,
|
||||
6741A95D1BF340DE002C974C /* types.txt in Resources */,
|
||||
6741A94B1BF340DE002C974C /* unicode_blocks.txt in Resources */,
|
||||
|
@ -5183,6 +5212,7 @@
|
|||
F6E2FDEC1E097BA00083EBEC /* MWMOpeningHoursAddClosedTableViewCell.mm in Sources */,
|
||||
34BBD64C1F826DB10070CA50 /* AuthorizationViewController.swift in Sources */,
|
||||
F6E2FE101E097BA00083EBEC /* MWMOpeningHoursTableViewCell.mm in Sources */,
|
||||
47C8789D22DF662700A772DA /* BookmarksSubscriptionExpiredViewController.swift in Sources */,
|
||||
6741A9B01BF340DE002C974C /* MapsAppDelegate.mm in Sources */,
|
||||
4719A645219CBD65009F9AA7 /* IPendingTransactionsHandler.swift in Sources */,
|
||||
34F742321E0834F400AC1FD6 /* UIViewController+Navigation.mm in Sources */,
|
||||
|
@ -5357,6 +5387,7 @@
|
|||
3404F490202898CC0090E401 /* BMCModels.swift in Sources */,
|
||||
F6E2FD561E097BA00083EBEC /* MWMMapDownloaderButtonTableViewCell.mm in Sources */,
|
||||
CDB4D5002231412900104869 /* MapTemplateBuilder.swift in Sources */,
|
||||
47C8789022DF525A00A772DA /* BookmarksSubscriptionSuccessViewController.swift in Sources */,
|
||||
3462258F1DDC5DBA001E8752 /* MWMSearchNoResultsAlert.mm in Sources */,
|
||||
470F5A7D2189BB2F00754295 /* PaidRoutePurchase.swift in Sources */,
|
||||
34AB66171FC5AA320078E451 /* MWMiPhoneRoutePreview.m in Sources */,
|
||||
|
@ -5607,6 +5638,7 @@
|
|||
4710366522D3764600585272 /* BookmarksSubscriptionCellViewController.swift in Sources */,
|
||||
34E776101F14B165003040B3 /* VisibleArea.swift in Sources */,
|
||||
330473EA21F7440C00DC4AEA /* MWMHotelParams.mm in Sources */,
|
||||
47C8789922DF622400A772DA /* BookmarksSubscriptionFailViewController.swift in Sources */,
|
||||
3454D7D71E07F045004AF2AD /* UIKitCategories.mm in Sources */,
|
||||
47E6CB0B2178BA3600EA102B /* SearchBannerCell.swift in Sources */,
|
||||
34AB39C21D2BD8310021857D /* MWMStopButton.mm in Sources */,
|
||||
|
@ -5781,6 +5813,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = "maps.me dbg.entitlements";
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer: Aleksey Belousov (927TL2MZMM)";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = N9X2A789QT;
|
||||
"EXCLUDED_SOURCE_FILE_NAMES[sdk=iphonesimulator*]" = MetalContextFactory.mm;
|
||||
"EXCLUDED_SOURCE_FILE_NAMES[sdk=macosx*]" = MetalContextFactory.mm;
|
||||
|
@ -5803,7 +5836,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = "maps.me rel.entitlements";
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer: Aleksey Belousov (927TL2MZMM)";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = N9X2A789QT;
|
||||
"EXCLUDED_SOURCE_FILE_NAMES[sdk=iphonesimulator*]" = MetalContextFactory.mm;
|
||||
"EXCLUDED_SOURCE_FILE_NAMES[sdk=macosx*]" = MetalContextFactory.mm;
|
||||
|
|
|
@ -83,8 +83,8 @@ import SafariServices
|
|||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
SubscriptionManager.shared.addListener(self)
|
||||
SubscriptionManager.shared.getAvailableSubscriptions { (subscriptions, error) in
|
||||
InAppPurchase.adsRemovalSubscriptionManager.addListener(self)
|
||||
InAppPurchase.adsRemovalSubscriptionManager.getAvailableSubscriptions { (subscriptions, error) in
|
||||
self.subscriptions = subscriptions
|
||||
self.productsLoadingIndicator.stopAnimating()
|
||||
guard let subscriptions = subscriptions else {
|
||||
|
@ -127,7 +127,7 @@ import SafariServices
|
|||
}
|
||||
|
||||
deinit {
|
||||
SubscriptionManager.shared.removeListener(self)
|
||||
InAppPurchase.adsRemovalSubscriptionManager.removeListener(self)
|
||||
}
|
||||
|
||||
@IBAction func onClose(_ sender: Any) {
|
||||
|
@ -188,7 +188,7 @@ import SafariServices
|
|||
Statistics.logEvent(kStatInappSelect, withParameters: [kStatProduct : subscription.productId])
|
||||
Statistics.logEvent(kStatInappPay)
|
||||
showPurchaseProgress()
|
||||
SubscriptionManager.shared.subscribe(to: subscription)
|
||||
InAppPurchase.adsRemovalSubscriptionManager.subscribe(to: subscription)
|
||||
}
|
||||
|
||||
private func showPurchaseProgress() {
|
||||
|
|
|
@ -372,7 +372,7 @@ using namespace power_management;
|
|||
[self.restoreSubscriptionCell.progress startAnimating];
|
||||
self.restoringSubscription = YES;
|
||||
__weak auto s = self;
|
||||
[[SubscriptionManager shared] restore:^(MWMValidationResult result) {
|
||||
[[InAppPurchase adsRemovalSubscriptionManager] restore:^(MWMValidationResult result) {
|
||||
__strong auto self = s;
|
||||
self.restoringSubscription = NO;
|
||||
[self.restoreSubscriptionCell.progress stopAnimating];
|
||||
|
|
Loading…
Add table
Reference in a new issue