Commit 4f15e58a by Dmitry Stepanets

Merge branch 'feature/IOS-288-subscription-popup' into develop

parents 26b4dba9 40069501
......@@ -192,6 +192,7 @@
CDD0F1E52572425200CF5017 /* SF-Pro.ttf in Resources */ = {isa = PBXBuildFile; fileRef = CDD0F1E42572425200CF5017 /* SF-Pro.ttf */; };
CDD0F1E82572429E00CF5017 /* AppFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDD0F1E72572429E00CF5017 /* AppFont.swift */; };
CDD0F1EE25725BCF00CF5017 /* ThemeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDD0F1ED25725BCF00CF5017 /* ThemeManager.swift */; };
CDD4C43A271971AC0025481A /* SubscriptionPopUpViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDD4C439271971AC0025481A /* SubscriptionPopUpViewController.swift */; };
CDD75F0D25DE68B10099ACDB /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = CDD75F0F25DE68B10099ACDB /* Localizable.strings */; };
CDDCD50726809F6D00E089AD /* ShortsSwipeHelperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDCD50626809F6D00E089AD /* ShortsSwipeHelperView.swift */; };
CDDCD5092680C18B00E089AD /* ShortsUnreadNudgeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDDCD5082680C18B00E089AD /* ShortsUnreadNudgeView.swift */; };
......@@ -553,6 +554,7 @@
CDD0F1E42572425200CF5017 /* SF-Pro.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SF-Pro.ttf"; sourceTree = "<group>"; };
CDD0F1E72572429E00CF5017 /* AppFont.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppFont.swift; sourceTree = "<group>"; };
CDD0F1ED25725BCF00CF5017 /* ThemeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeManager.swift; sourceTree = "<group>"; };
CDD4C439271971AC0025481A /* SubscriptionPopUpViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionPopUpViewController.swift; sourceTree = "<group>"; };
CDD75F0E25DE68B10099ACDB /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
CDDCD50626809F6D00E089AD /* ShortsSwipeHelperView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortsSwipeHelperView.swift; sourceTree = "<group>"; };
CDDCD5082680C18B00E089AD /* ShortsUnreadNudgeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortsUnreadNudgeView.swift; sourceTree = "<group>"; };
......@@ -1564,6 +1566,7 @@
CE6E410426EBA3B4009829AE /* Views */,
CE6E410226EBA3B0009829AE /* SubscriptionStoreViewController.swift */,
CE6E410526EBA3EB009829AE /* SubscriptionOverviewViewController.swift */,
CDD4C439271971AC0025481A /* SubscriptionPopUpViewController.swift */,
);
path = Subscriptions;
sourceTree = "<group>";
......@@ -2274,6 +2277,7 @@
CDC6125725E7AB1A00188DA7 /* TodayAirQualityCell.swift in Sources */,
CD8B60AE263819400055CB3F /* NWSAlertViewController.swift in Sources */,
CE6E410326EBA3B0009829AE /* SubscriptionStoreViewController.swift in Sources */,
CDD4C43A271971AC0025481A /* SubscriptionPopUpViewController.swift in Sources */,
CD593BCF2608A50900C93428 /* ForecastHourlyCell.swift in Sources */,
CDB0D4CC2670D12F0081C773 /* TodayShortsCell.swift in Sources */,
CD1DDD332602305200AC62B2 /* ForecastInfoCell.swift in Sources */,
......
......@@ -8,26 +8,38 @@
import UIKit
import OneWeatherCore
class SubscriptionCoordinator: Coordinator {
class SubscriptionCoordinator: NSObject, Coordinator {
//Private
private let parentViewController: UIViewController
private let storeManager: StoreManager
private let viewModel: SubscriptionViewModel
private var activeViewController: UIViewController?
//Public
public var childCoordinators = [Coordinator]()
public var parentCoordinator: Coordinator?
private let storeManager: StoreManager
public init(parentViewController: UIViewController, storeManager: StoreManager = StoreManager.shared) {
self.parentViewController = parentViewController
self.storeManager = storeManager
self.viewModel = SubscriptionViewModel(storeManager: storeManager)
super.init()
self.viewModel.delegate = self
}
public func start() {
let viewModel = SubscriptionViewModel(storeManager: storeManager)
let vc = SubscriptionStoreViewController(coordinator: self, viewModel: viewModel)
self.parentViewController.present(vc, animated: true)
activeViewController = SubscriptionStoreViewController(viewModel: self.viewModel)
self.parentViewController.present(activeViewController!, animated: true)
}
public func openOverview() {
public func startPopUp() {
activeViewController = SubscriptionPopUpViewController(viewModel: self.viewModel)
self.parentViewController.present(activeViewController!, animated: true)
}
private func openOverview() {
let overviewCoordinator = SubscriptionOverviewCoordinator(parentViewController: self.parentViewController)
overviewCoordinator.parentCoordinator = self
childCoordinators.append(overviewCoordinator)
......@@ -38,3 +50,14 @@ class SubscriptionCoordinator: Coordinator {
parentCoordinator?.childDidFinish(child: self)
}
}
//MARK: Subscription View Model
extension SubscriptionCoordinator: SubscriptionViewModelDelegate {
func viewModel(_ vm: SubscriptionViewModel, finishedSubscriptionPurchaseWithResult result: Bool) {
if result {
self.activeViewController?.dismiss(animated: true, completion: {
self.openOverview()
})
}
}
}
......@@ -15,7 +15,7 @@ protocol TodayCoordinatorDelegate: AnyObject {
class TodayCoordinator: Coordinator {
// MARK: - Private
private let navigationController = ColoredNavigationController(nibName: nil, bundle: nil)
private var tabBarController:UITabBarController?
private var tabBarController: UITabBarController?
var todayViewController: TodayViewController?
// MARK: - Public
......@@ -23,7 +23,7 @@ class TodayCoordinator: Coordinator {
public var childCoordinators = [Coordinator]()
public var parentCoordinator: Coordinator?
public init(tabBarController:UITabBarController) {
public init(tabBarController: UITabBarController) {
self.tabBarController = tabBarController
}
......@@ -65,6 +65,17 @@ class TodayCoordinator: Coordinator {
onboardingCoordinator.start()
}
public func openSubscriptionStorePopUp() {
guard let parentController = self.tabBarController else {
return
}
let subscriptionCoordinator = SubscriptionCoordinator(parentViewController: parentController)
subscriptionCoordinator.parentCoordinator = self
childCoordinators.append(subscriptionCoordinator)
subscriptionCoordinator.startPopUp()
}
public func viewControllerDidEnd(controller: UIViewController) {
parentCoordinator?.childDidFinish(child: self)
}
......
......@@ -36,7 +36,7 @@ public class PushNotificationsManager: NSObject, PushNotificationsManagerProtoco
// TODO: forced re-register on timeout
public func registerForRemoteNotifications() {
public func registerForRemoteNotifications(completion: (() -> Void)? = nil) {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { [weak self]
(granted, error) in
guard let self = self else { return }
......@@ -49,6 +49,7 @@ public class PushNotificationsManager: NSObject, PushNotificationsManagerProtoco
onMain {
MoEngage.sharedInstance().registerForRemoteNotification(withCategories: nil, withUserNotificationCenterDelegate: self)
completion?()
}
}
}
......
//
// SubscriptionPopUpViewController.swift
// 1Weather
//
// Created by Dmitry Stepanets on 15.10.2021.
//
import UIKit
import OneWeatherCore
class SubscriptionPopUpViewController: UIViewController {
private let storeViewController: SubscriptionStoreViewController
init(viewModel: SubscriptionViewModel) {
self.storeViewController = SubscriptionStoreViewController(viewModel: viewModel)
super.init(nibName: nil, bundle: nil)
modalPresentationStyle = .overCurrentContext
modalTransitionStyle = .crossDissolve
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
prepareControler()
prepareStoreController()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
storeViewController.view.snp.updateConstraints { update in
let diffHeight = view.bounds.height - storeViewController.view.bounds.height
let offset = storeViewController.view.bounds.height + diffHeight / 2
update.top.equalTo(view.snp.bottom).offset(-offset)
}
UIView.animate(withDuration: 0.2) {
self.view.layoutIfNeeded()
}
Settings.shared.initialSubscriptionShowed = true
}
}
private extension SubscriptionPopUpViewController {
func prepareControler() {
view.backgroundColor = UIColor.black.withAlphaComponent(0.5)
}
func prepareStoreController() {
storeViewController.view.clipsToBounds = true
storeViewController.view.layer.cornerRadius = 12
view.addSubview(storeViewController.view)
addChild(storeViewController)
storeViewController.didMove(toParent: self)
//Constraints
storeViewController.view.snp.makeConstraints { make in
make.width.equalToSuperview().multipliedBy(0.87)
make.height.equalToSuperview().multipliedBy(0.9)
make.centerX.equalToSuperview()
make.top.equalTo(view.snp.bottom)
}
}
}
......@@ -15,7 +15,6 @@ import OneWeatherAnalytics
/// For users who previously purchased an in-app to disable ads: https://zpl.io/anzPMKr
/// For usual users: https://zpl.io/bLJ8rOd
public class SubscriptionStoreViewController: UIViewController {
private let coordinator: SubscriptionCoordinator
private let viewModel: SubscriptionViewModel
private var localizationObserver: LocalizationChangeObserver!
......@@ -25,28 +24,30 @@ public class SubscriptionStoreViewController: UIViewController {
private let dynamicContentView = UIView()
init(coordinator: SubscriptionCoordinator, viewModel: SubscriptionViewModel) {
self.coordinator = coordinator
init(viewModel: SubscriptionViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
self.viewModel.delegate = self
}
@available(*, unavailable)
required init?(coder: NSCoder) { return nil }
public override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.scrollView.contentSize = self.scrollViewContent.bounds.size
}
public override func viewDidLoad() {
super.viewDidLoad()
prepareViewController()
prepareScrollView()
rebuildUI()
}
}
//MARK: - UI Setup
extension SubscriptionStoreViewController {
private func prepareViewController() {
private extension SubscriptionStoreViewController {
func prepareViewController() {
view.backgroundColor = ThemeManager.currentTheme.baseBackgroundColor
topHeaderView.delegate = self
localizationObserver = LocalizationChangeObserver { [weak self] in
......@@ -54,7 +55,7 @@ extension SubscriptionStoreViewController {
}
}
private func prepareScrollView() {
func prepareScrollView() {
view.addSubview(scrollView)
scrollView.snp.makeConstraints { make in
make.edges.equalToSuperview()
......@@ -79,7 +80,7 @@ extension SubscriptionStoreViewController {
}
}
private func rebuildUI() {
func rebuildUI() {
for subview in dynamicContentView.subviews {
subview.removeFromSuperview()
}
......@@ -159,12 +160,3 @@ extension SubscriptionStoreViewController: SubscriptionPurchaseButtonDelegate {
viewModel.purchase(subscription: product)
}
}
extension SubscriptionStoreViewController: SubscriptionViewModelDelegate {
func viewModel(_ vm: SubscriptionViewModel, finishedSubscriptionPurchaseWithResult result: Bool) {
if result {
self.dismiss(animated: true) {
self.coordinator.openOverview()
}
}
}
}
......@@ -175,6 +175,10 @@ extension TodayViewController: TodayViewModelDelegate {
coordinator.openOnboarding()
}
func showSubscriptionPopup(viewModel: TodayViewModel) {
coordinator.openSubscriptionStorePopUp()
}
func viewModelDidChange<P>(model: P) where P : ViewModelProtocol {
cityButton.configure(with: viewModel.location)
cityButton.isHidden = false
......
......@@ -14,6 +14,7 @@ import AppTrackingTransparency
protocol TodayViewModelDelegate: ViewModelDelegate {
func showOnboarding(viewModel: TodayViewModel)
func showPrivacyNotice(viewModel: TodayViewModel)
func showSubscriptionPopup(viewModel: TodayViewModel)
}
class TodayViewModel: ViewModelProtocol {
......@@ -100,7 +101,12 @@ class TodayViewModel: ViewModelProtocol {
private func onboardingFlowCompleted() {
self.initializeAllAdsIfNeeded()
PushNotificationsManager.shared.registerForRemoteNotifications()
PushNotificationsManager.shared.registerForRemoteNotifications(completion: { [weak self] in
guard let self = self else { return }
if !Settings.shared.initialSubscriptionShowed && CCPAHelper.shared.isNewUser {
self.delegate?.showSubscriptionPopup(viewModel: self)
}
})
analytics(log: .ANALYTICS_VIEW_TODAY)
}
......
......@@ -101,6 +101,9 @@ public class Settings {
@UserDefaultsBasicValue(key: "shorts_showed_swipeUp_count", userDefaults: UserDefaults.appDefaults)
public var shortsSwipeUpNudgeShowedCount = 0
@UserDefaultsBasicValue(key: "initial_subscription_showed", userDefaults: UserDefaults.appDefaults)
public var initialSubscriptionShowed = false
#warning("Not implemented!")
//TODO: implement store in UserDefaults and configure via UI in debug builds.
public var adLogging: Bool = true
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment