Commit 5eca46cbe680b989832cb52a7a99c866f3d3ede1
1 parent
471c93e5
subscription changes + fixed tab openning
added subscription expiration handling. fixed creating snapshot of webpage
Showing
84 changed files
with
248 additions
and
174 deletions
No preview for this file type
... | ... | @@ -36,6 +36,7 @@ |
36 | 36 | 194206C52B10D267000C1263 /* ProductList.plist in Resources */ = {isa = PBXBuildFile; fileRef = 194206C42B10D267000C1263 /* ProductList.plist */; }; |
37 | 37 | 194206C82B10DFC6000C1263 /* RemoveAdvertTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194206C72B10DFC6000C1263 /* RemoveAdvertTableViewCell.swift */; }; |
38 | 38 | 194635D62ADD738E00993D91 /* HistoryDataBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194635D52ADD738E00993D91 /* HistoryDataBase.swift */; }; |
39 | + 1946D8792B178A9F00B5A735 /* SubscriptionsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1946D8782B178A9F00B5A735 /* SubscriptionsModel.swift */; }; | |
39 | 40 | 19696AF52AE80DBD00D1F8F9 /* blockerList.json in Resources */ = {isa = PBXBuildFile; fileRef = 19696AF42AE80DBD00D1F8F9 /* blockerList.json */; }; |
40 | 41 | 19696AF72AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19696AF62AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift */; }; |
41 | 42 | 19696AFB2AE80DBD00D1F8F9 /* AdBlocker.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; |
... | ... | @@ -44,7 +45,7 @@ |
44 | 45 | 1975347B2B109A37000818D3 /* SubscriptionTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1975347A2B109A37000818D3 /* SubscriptionTableViewCell.swift */; }; |
45 | 46 | 197C2A242B0E3A7B0010B386 /* AdBlockButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197C2A232B0E3A7B0010B386 /* AdBlockButton.swift */; }; |
46 | 47 | 197C2A282B0F65840010B386 /* OpenBrowserHomeTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197C2A272B0F65830010B386 /* OpenBrowserHomeTransition.swift */; }; |
47 | - 197C2A2D2B0F9EEB0010B386 /* StoreKitManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197C2A2C2B0F9EEB0010B386 /* StoreKitManager.swift */; }; | |
48 | + 197C2A2D2B0F9EEB0010B386 /* SubscriptionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197C2A2C2B0F9EEB0010B386 /* SubscriptionManager.swift */; }; | |
48 | 49 | 197FC3EF2AC21E1F007F429C /* PayloadViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3EE2AC21E1F007F429C /* PayloadViewController.swift */; }; |
49 | 50 | 197FC3F22AC2AF9A007F429C /* AdvantagesTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3F12AC2AF9A007F429C /* AdvantagesTableViewCell.swift */; }; |
50 | 51 | 197FC3F42AC2BCD7007F429C /* SearchBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3F32AC2BCD7007F429C /* SearchBarView.swift */; }; |
... | ... | @@ -137,6 +138,7 @@ |
137 | 138 | 194206C42B10D267000C1263 /* ProductList.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = ProductList.plist; sourceTree = "<group>"; }; |
138 | 139 | 194206C72B10DFC6000C1263 /* RemoveAdvertTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveAdvertTableViewCell.swift; sourceTree = "<group>"; }; |
139 | 140 | 194635D52ADD738E00993D91 /* HistoryDataBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryDataBase.swift; sourceTree = "<group>"; }; |
141 | + 1946D8782B178A9F00B5A735 /* SubscriptionsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionsModel.swift; sourceTree = "<group>"; }; | |
140 | 142 | 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = AdBlocker.appex; sourceTree = BUILT_PRODUCTS_DIR; }; |
141 | 143 | 19696AF42AE80DBD00D1F8F9 /* blockerList.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = blockerList.json; sourceTree = "<group>"; }; |
142 | 144 | 19696AF62AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentBlockerRequestHandler.swift; sourceTree = "<group>"; }; |
... | ... | @@ -146,7 +148,7 @@ |
146 | 148 | 1975347A2B109A37000818D3 /* SubscriptionTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionTableViewCell.swift; sourceTree = "<group>"; }; |
147 | 149 | 197C2A232B0E3A7B0010B386 /* AdBlockButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdBlockButton.swift; sourceTree = "<group>"; }; |
148 | 150 | 197C2A272B0F65830010B386 /* OpenBrowserHomeTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenBrowserHomeTransition.swift; sourceTree = "<group>"; }; |
149 | - 197C2A2C2B0F9EEB0010B386 /* StoreKitManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreKitManager.swift; sourceTree = "<group>"; }; | |
151 | + 197C2A2C2B0F9EEB0010B386 /* SubscriptionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionManager.swift; sourceTree = "<group>"; }; | |
150 | 152 | 197FC3EE2AC21E1F007F429C /* PayloadViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayloadViewController.swift; sourceTree = "<group>"; }; |
151 | 153 | 197FC3F12AC2AF9A007F429C /* AdvantagesTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvantagesTableViewCell.swift; sourceTree = "<group>"; }; |
152 | 154 | 197FC3F32AC2BCD7007F429C /* SearchBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBarView.swift; sourceTree = "<group>"; }; |
... | ... | @@ -238,7 +240,7 @@ |
238 | 240 | 190DB9FD2AC459CD000A7BF3 /* Managers */ = { |
239 | 241 | isa = PBXGroup; |
240 | 242 | children = ( |
241 | - 197C2A2C2B0F9EEB0010B386 /* StoreKitManager.swift */, | |
243 | + 197C2A2C2B0F9EEB0010B386 /* SubscriptionManager.swift */, | |
242 | 244 | 190DB9FF2AC45A3C000A7BF3 /* CachingManager.swift */, |
243 | 245 | 193B3B892ACAF714002161ED /* TabManager.swift */, |
244 | 246 | 1907D6962ADE766F00C40E9F /* HistoryDBManager.swift */, |
... | ... | @@ -634,6 +636,7 @@ |
634 | 636 | children = ( |
635 | 637 | 19B739752AE276360073AA59 /* HistoryElement.swift */, |
636 | 638 | 1926E82E2B03BED200FEBCFB /* HistoryToolbarMenuCases.swift */, |
639 | + 1946D8782B178A9F00B5A735 /* SubscriptionsModel.swift */, | |
637 | 640 | ); |
638 | 641 | path = Models; |
639 | 642 | sourceTree = "<group>"; |
... | ... | @@ -695,6 +698,12 @@ |
695 | 698 | 19F65A722ACBFD7300B50F61 /* Common */ = { |
696 | 699 | isa = PBXGroup; |
697 | 700 | children = ( |
701 | + 19B739742AE275FF0073AA59 /* Models */, | |
702 | + 199DB1EC2AD3FCE1007E6A81 /* Services */, | |
703 | + 190DB9FD2AC459CD000A7BF3 /* Managers */, | |
704 | + 19F65A712ACBFCB500B50F61 /* Resources */, | |
705 | + 193B3B812ACAF36C002161ED /* DataBases */, | |
706 | + 190DBA012AC45CDA000A7BF3 /* Extentions */, | |
698 | 707 | 19F65A732ACBFDD100B50F61 /* Transitions */, |
699 | 708 | ); |
700 | 709 | path = Common; |
... | ... | @@ -732,15 +741,9 @@ |
732 | 741 | 19FCBF202AC1727800F83A7F /* browser */ = { |
733 | 742 | isa = PBXGroup; |
734 | 743 | children = ( |
735 | - 19B739742AE275FF0073AA59 /* Models */, | |
736 | 744 | 19FCBF382AC17A4800F83A7F /* Modules */, |
737 | - 199DB1EC2AD3FCE1007E6A81 /* Services */, | |
738 | - 19F65A722ACBFD7300B50F61 /* Common */, | |
739 | - 190DBA012AC45CDA000A7BF3 /* Extentions */, | |
740 | - 193B3B812ACAF36C002161ED /* DataBases */, | |
741 | - 19F65A712ACBFCB500B50F61 /* Resources */, | |
742 | - 190DB9FD2AC459CD000A7BF3 /* Managers */, | |
743 | 745 | 19FCBF352AC1779800F83A7F /* Navigation */, |
746 | + 19F65A722ACBFD7300B50F61 /* Common */, | |
744 | 747 | 19FCBF212AC1727800F83A7F /* AppDelegate.swift */, |
745 | 748 | 19FCBF2F2AC1727900F83A7F /* Info.plist */, |
746 | 749 | 194206C42B10D267000C1263 /* ProductList.plist */, |
... | ... | @@ -948,7 +951,7 @@ |
948 | 951 | 197FC4032AC41EB7007F429C /* ToolbarView.swift in Sources */, |
949 | 952 | 19B7396A2AE1554E0073AA59 /* URLConstants.swift in Sources */, |
950 | 953 | 197534782B1096A7000818D3 /* SubscriptionView.swift in Sources */, |
951 | - 197C2A2D2B0F9EEB0010B386 /* StoreKitManager.swift in Sources */, | |
954 | + 197C2A2D2B0F9EEB0010B386 /* SubscriptionManager.swift in Sources */, | |
952 | 955 | 19EECA472ACED48000094AFB /* SearchResultViewController.swift in Sources */, |
953 | 956 | 191BB8572AC5B4AC00A2DEB9 /* OpenedTabsCollectionViewCell.swift in Sources */, |
954 | 957 | 190DB9FC2AC450F6000A7BF3 /* RemoveAdvertViewController.swift in Sources */, |
... | ... | @@ -986,6 +989,7 @@ |
986 | 989 | 197FC3F92AC2FB69007F429C /* SettingViewController.swift in Sources */, |
987 | 990 | 1984BF5A2AFB973C0050F816 /* TermsView.swift in Sources */, |
988 | 991 | 197FC3FC2AC2FBA0007F429C /* SettingView.swift in Sources */, |
992 | + 1946D8792B178A9F00B5A735 /* SubscriptionsModel.swift in Sources */, | |
989 | 993 | 191BB8622AC6A01500A2DEB9 /* SearchingViewController.swift in Sources */, |
990 | 994 | 1975347B2B109A37000818D3 /* SubscriptionTableViewCell.swift in Sources */, |
991 | 995 | 197FC4012AC31D5C007F429C /* NavigationViewController.swift in Sources */, | ... | ... |
No preview for this file type
No preview for this file type
... | ... | @@ -9,7 +9,6 @@ import UIKit |
9 | 9 | window = UIWindow(frame: screenRect) |
10 | 10 | |
11 | 11 | if let window = window { |
12 | - let notification = NotificationManager() | |
13 | 12 | let navigationViewController = NavigationViewController() |
14 | 13 | window.rootViewController = navigationViewController |
15 | 14 | window.makeKeyAndVisible() | ... | ... |
... | ... | @@ -11,19 +11,30 @@ final class CachingManager { |
11 | 11 | private enum Keys { |
12 | 12 | static let isFirstAppLoad = "IsFirstAppLoad" |
13 | 13 | static let isAdBlocking = "IsAdBlocking" |
14 | + static let expirationDate = "ExpirationDate" | |
14 | 15 | } |
15 | 16 | |
16 | - private init() {} | |
17 | - | |
18 | 17 | static let shared = CachingManager() |
19 | 18 | private let userDefaults = UserDefaults.standard |
20 | 19 | |
20 | + private init() {} | |
21 | + | |
21 | 22 | var isFirstAppLoad: Bool { |
22 | 23 | get { return userDefaults.bool(forKey: Keys.isFirstAppLoad) } |
23 | 24 | set { userDefaults.set(newValue, forKey: Keys.isFirstAppLoad) } |
24 | 25 | } |
25 | - var isAdBlocking: Bool { | |
26 | + var adBlockerState: Bool { | |
26 | 27 | get { return userDefaults.bool(forKey: Keys.isAdBlocking) } |
27 | 28 | set { userDefaults.set(newValue, forKey: Keys.isAdBlocking) } |
28 | 29 | } |
30 | + var expirationDate: Double? { | |
31 | + get { | |
32 | + if userDefaults.object(forKey: Keys.expirationDate) == nil { | |
33 | + return nil | |
34 | + } | |
35 | + | |
36 | + return userDefaults.double(forKey: Keys.expirationDate) | |
37 | + } | |
38 | + set { userDefaults.set(newValue, forKey: Keys.expirationDate) } | |
39 | + } | |
29 | 40 | } | ... | ... |
... | ... | @@ -6,10 +6,20 @@ |
6 | 6 | // |
7 | 7 | |
8 | 8 | import Foundation |
9 | +import UIKit | |
9 | 10 | |
10 | 11 | |
11 | 12 | final class DateManager { |
12 | 13 | static let shared = DateManager() |
14 | + | |
15 | + let currentDate = Date() | |
16 | + let currentTimestamp = Date().timeIntervalSince1970 | |
17 | + | |
18 | + var dateFormatter: DateFormatter{ | |
19 | + let obj = DateFormatter() | |
20 | + obj.dateFormat = "EEEE, d MMM" | |
21 | + return obj | |
22 | + } | |
13 | 23 | |
14 | 24 | private init() {} |
15 | 25 | |
... | ... | @@ -19,15 +29,20 @@ final class DateManager { |
19 | 29 | return timeFormatter.string(from: date ?? Date()) |
20 | 30 | } |
21 | 31 | |
22 | - var dateFormatter: DateFormatter{ | |
23 | - let obj = DateFormatter() | |
24 | - obj.dateFormat = "EEEE, d MMM" | |
25 | - return obj | |
26 | - } | |
27 | - | |
28 | - var currentDate: Date { | |
29 | - let obj = Date() | |
30 | - return obj | |
32 | + func getSubscriptionExpirationDate() { | |
33 | + guard CachingManager.shared.expirationDate != nil else { | |
34 | + Task { | |
35 | + if let activeSubscription = SubscriptionManager.shared.purchasedSubscriptions.first { | |
36 | + switch await activeSubscription.latestTransaction { | |
37 | + case .verified(let transaction): | |
38 | + CachingManager.shared.expirationDate = transaction.expirationDate?.timeIntervalSince1970 | |
39 | + default: | |
40 | + return | |
41 | + } | |
42 | + } | |
43 | + } | |
44 | + return | |
45 | + } | |
31 | 46 | } |
32 | 47 | } |
33 | 48 | ... | ... |
... | ... | @@ -12,31 +12,23 @@ fileprivate enum StoreError: Error { |
12 | 12 | case failedVerification |
13 | 13 | } |
14 | 14 | |
15 | -final class StoreKitManager: ObservableObject { | |
16 | - @Published | |
17 | - var storeProducts: [Product] = [] | |
18 | - @Published | |
19 | - var purchasedSubscriptions : [Product] = [] | |
15 | +final class SubscriptionManager: ObservableObject { | |
16 | + static let shared = SubscriptionManager() | |
20 | 17 | |
21 | - private var updateListenerTask: Task<Void, Error>? = nil | |
18 | + @Published var storeProducts: [Product] = [] | |
19 | + @Published var purchasedSubscriptions : [Product] = [] | |
22 | 20 | |
21 | + private var updateListenerTask: Task<Void, Error>? = nil | |
23 | 22 | private let productDict: [String : String] |
24 | 23 | |
25 | 24 | init() { |
26 | - if let plistPath = Bundle.main.path(forResource: "ProductList", ofType: "plist"), | |
27 | - let plist = FileManager.default.contents(atPath: plistPath) { | |
28 | - productDict = (try? PropertyListSerialization.propertyList(from: plist, format: nil) as? [String : String]) ?? [:] | |
29 | - } else { | |
30 | - productDict = [:] | |
31 | - } | |
25 | + productDict = SubscriptionsModel.subscriptionInfo | |
32 | 26 | updateListenerTask = listenForTransactions() |
33 | 27 | |
34 | 28 | Task { |
35 | 29 | await requestProducts() |
36 | 30 | await updateCustomerProductStatus() |
37 | 31 | } |
38 | - | |
39 | - print("controller called") | |
40 | 32 | } |
41 | 33 | |
42 | 34 | deinit { |
... | ... | @@ -57,7 +49,6 @@ final class StoreKitManager: ObservableObject { |
57 | 49 | } |
58 | 50 | } |
59 | 51 | |
60 | - @MainActor | |
61 | 52 | func requestProducts() async { |
62 | 53 | do { |
63 | 54 | storeProducts = try await Product.products(for: productDict.values) |
... | ... | @@ -113,4 +104,8 @@ final class StoreKitManager: ObservableObject { |
113 | 104 | func isPurchased(_ product: Product) async throws -> Bool { |
114 | 105 | return purchasedSubscriptions.contains(product) |
115 | 106 | } |
107 | + | |
108 | + func restorePurchase() async throws { | |
109 | + try await AppStore.sync() | |
110 | + } | |
116 | 111 | } | ... | ... |
1 | +// | |
2 | +// SubscriptionsModel.swift | |
3 | +// Pro-Seecurity-VPN | |
4 | +// | |
5 | +// Created by Artem Talko on 29.11.2023. | |
6 | +// | |
7 | + | |
8 | +import Foundation | |
9 | + | |
10 | +struct SubscriptionsModel { | |
11 | + static var subscriptionInfo: [String: String] { | |
12 | + return ["adBlocker": "com.browser.adblocker"] | |
13 | + } | |
14 | +} | ... | ... |
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
... | ... | @@ -21,15 +21,4 @@ final class SnapshotService { |
21 | 21 | } |
22 | 22 | return siteSnapshotImage |
23 | 23 | } |
24 | - | |
25 | - func makeWKWebViewSnapshot(_ wkWV: WKWebView?, completion: @escaping (UIImage?) -> Void) { | |
26 | - wkWV?.takeSnapshot(with: snapshotConfiguration) { (image, error) in | |
27 | - if let snaphotIMG = image { | |
28 | - completion(snaphotIMG) | |
29 | - } else if let error = error { | |
30 | - print(error) | |
31 | - completion(nil) | |
32 | - } | |
33 | - } | |
34 | - } | |
35 | 24 | } | ... | ... |
... | ... | @@ -24,6 +24,16 @@ final class HistoryViewController: UIViewController { |
24 | 24 | } |
25 | 25 | } |
26 | 26 | |
27 | + init() { | |
28 | + super.init(nibName: nil, bundle: nil) | |
29 | + | |
30 | + historyData = HistoryDBManager.shared.getHistoryDataForTableView() | |
31 | + } | |
32 | + | |
33 | + required init?(coder: NSCoder) { | |
34 | + fatalError("init(coder:) has not been implemented") | |
35 | + } | |
36 | + | |
27 | 37 | override func viewWillAppear(_ animated: Bool) { |
28 | 38 | super.viewWillAppear(animated) |
29 | 39 | |
... | ... | @@ -52,16 +62,6 @@ final class HistoryViewController: UIViewController { |
52 | 62 | navigationController?.isNavigationBarHidden = false |
53 | 63 | navigationItem.title = "History" |
54 | 64 | } |
55 | - | |
56 | - init() { | |
57 | - super.init(nibName: nil, bundle: nil) | |
58 | - | |
59 | - historyData = HistoryDBManager.shared.getHistoryDataForTableView() | |
60 | - } | |
61 | - | |
62 | - required init?(coder: NSCoder) { | |
63 | - fatalError("init(coder:) has not been implemented") | |
64 | - } | |
65 | 65 | } |
66 | 66 | |
67 | 67 | //MARK: - TableView Extention | ... | ... |
... | ... | @@ -30,6 +30,21 @@ final class BrowserHomeViewController: UIViewController { |
30 | 30 | } |
31 | 31 | } |
32 | 32 | |
33 | + init(url: String?, currentTabId: Int?) { | |
34 | + searchResultViewController = SearchResultViewController(searchLink: String()) | |
35 | + searchingViewController = SearchingViewController(dataForReq: []) | |
36 | + subscriptions = [] | |
37 | + searchRequestURL = URLConstants.googleURL | |
38 | + | |
39 | + super.init(nibName: nil, bundle: nil) | |
40 | + self.url = url | |
41 | + self.currentTabId = currentTabId | |
42 | + } | |
43 | + | |
44 | + required init?(coder: NSCoder) { | |
45 | + fatalError("init(coder:) has not been implemented") | |
46 | + } | |
47 | + | |
33 | 48 | override func viewDidLoad() { |
34 | 49 | super.viewDidLoad() |
35 | 50 | view.backgroundColor = ColorConstants.lightGray |
... | ... | @@ -58,21 +73,6 @@ final class BrowserHomeViewController: UIViewController { |
58 | 73 | view = mainView |
59 | 74 | } |
60 | 75 | |
61 | - init(url: String?, currentTabId: Int?) { | |
62 | - searchResultViewController = SearchResultViewController(searchLink: String()) | |
63 | - searchingViewController = SearchingViewController(dataForReq: []) | |
64 | - subscriptions = [] | |
65 | - searchRequestURL = URLConstants.googleURL | |
66 | - | |
67 | - super.init(nibName: nil, bundle: nil) | |
68 | - self.url = url | |
69 | - self.currentTabId = currentTabId | |
70 | - } | |
71 | - | |
72 | - required init?(coder: NSCoder) { | |
73 | - fatalError("init(coder:) has not been implemented") | |
74 | - } | |
75 | - | |
76 | 76 | override func viewWillDisappear(_ animated: Bool) { |
77 | 77 | super.viewWillDisappear(animated) |
78 | 78 | NotificationCenter.default.removeObserver(self) |
... | ... | @@ -189,8 +189,6 @@ extension BrowserHomeViewController { |
189 | 189 | return (controllers.first(where: { $0 is TabsViewController }) as? TabsViewController) |
190 | 190 | } |
191 | 191 | |
192 | - | |
193 | - | |
194 | 192 | private func didTabButtonTapped(type: ToolbarElementType) { |
195 | 193 | switch type { |
196 | 194 | case .history: | ... | ... |
... | ... | @@ -11,8 +11,19 @@ final class PayloadViewController: UIViewController { |
11 | 11 | private let mainView = PayloadView() |
12 | 12 | private let payloadTableViewData: [String] |
13 | 13 | |
14 | + init(){ | |
15 | + payloadTableViewData = StringConstants.payloadViewControllerData | |
16 | + | |
17 | + super.init(nibName: nil, bundle: nil) | |
18 | + } | |
19 | + | |
20 | + required init?(coder: NSCoder) { | |
21 | + fatalError("init(coder:) has not been implemented") | |
22 | + } | |
23 | + | |
14 | 24 | override func viewDidLoad() { |
15 | 25 | super.viewDidLoad() |
26 | + | |
16 | 27 | initViewController() |
17 | 28 | } |
18 | 29 | |
... | ... | @@ -27,16 +38,6 @@ final class PayloadViewController: UIViewController { |
27 | 38 | view = mainView |
28 | 39 | } |
29 | 40 | |
30 | - init(){ | |
31 | - payloadTableViewData = StringConstants.payloadViewControllerData | |
32 | - | |
33 | - super.init(nibName: nil, bundle: nil) | |
34 | - } | |
35 | - | |
36 | - required init?(coder: NSCoder) { | |
37 | - fatalError("init(coder:) has not been implemented") | |
38 | - } | |
39 | - | |
40 | 41 | override func viewWillDisappear(_ animated: Bool) { |
41 | 42 | super.viewWillDisappear(animated) |
42 | 43 | ... | ... |
... | ... | @@ -10,23 +10,14 @@ import UIKit |
10 | 10 | final class RemoveAdvertViewController: UIViewController { |
11 | 11 | private let mainView = RemoveAdvertView() |
12 | 12 | |
13 | - private let tableViewData = StringConstants.tableViewData | |
14 | - | |
15 | - var storeKit: StoreKitManager | |
13 | + private let notification: NotificationManager | |
14 | + private var storeKit: SubscriptionManager | |
16 | 15 | |
17 | - override func viewDidLoad() { | |
18 | - super.viewDidLoad() | |
19 | - | |
20 | - initViewController() | |
21 | - } | |
16 | + private let tableViewData = StringConstants.tableViewData | |
22 | 17 | |
23 | - private func initViewController() { | |
24 | - addTargets() | |
25 | - setupTableView() | |
26 | - } | |
27 | - | |
28 | 18 | init() { |
29 | - self.storeKit = StoreKitManager() | |
19 | + storeKit = SubscriptionManager() | |
20 | + notification = NotificationManager() | |
30 | 21 | |
31 | 22 | super.init(nibName: nil, bundle: nil) |
32 | 23 | } |
... | ... | @@ -35,16 +26,32 @@ final class RemoveAdvertViewController: UIViewController { |
35 | 26 | fatalError("init(coder:) has not been implemented") |
36 | 27 | } |
37 | 28 | |
29 | + override func viewDidLoad() { | |
30 | + super.viewDidLoad() | |
31 | + | |
32 | + initViewController() | |
33 | + } | |
34 | + | |
38 | 35 | override func loadView() { |
39 | 36 | view = mainView |
40 | 37 | } |
38 | + | |
39 | + private func initViewController() { | |
40 | + addTargets() | |
41 | + setupTableView() | |
42 | + } | |
41 | 43 | } |
42 | 44 | |
43 | 45 | //MARK: - Action |
44 | 46 | extension RemoveAdvertViewController { |
45 | 47 | @objc |
46 | 48 | private func adBlockerButtonPressed(_ sender: UIButton) { |
47 | - viewAdBlockingHandler() | |
49 | + if CachingManager.shared.adBlockerState { | |
50 | + turnOffAdBlocker() | |
51 | + } else { | |
52 | + subscriptionHandler() | |
53 | + } | |
54 | + | |
48 | 55 | } |
49 | 56 | |
50 | 57 | @objc |
... | ... | @@ -58,6 +65,50 @@ extension RemoveAdvertViewController { |
58 | 65 | |
59 | 66 | //MARK: Helpers |
60 | 67 | extension RemoveAdvertViewController { |
68 | + private func subscriptionHandler() { | |
69 | + if storeKit.purchasedSubscriptions.isEmpty { | |
70 | + Task { | |
71 | + try? await storeKit.restorePurchase() | |
72 | + | |
73 | + if storeKit.purchasedSubscriptions.isEmpty { | |
74 | + presentSubscriptionHandler() | |
75 | + } else { | |
76 | + if let restoreDate = CachingManager.shared.expirationDate { | |
77 | + if Date().timeIntervalSince1970 < restoreDate { | |
78 | + turnOnAdBlocker() | |
79 | + } else { | |
80 | + presentSubscriptionHandler() | |
81 | + } | |
82 | + } else { | |
83 | + DateManager.shared.getSubscriptionExpirationDate() | |
84 | + let restoreDate = CachingManager.shared.expirationDate | |
85 | + if Date().timeIntervalSince1970 < restoreDate ?? 0 { | |
86 | + turnOnAdBlocker() | |
87 | + } else { | |
88 | + presentSubscriptionHandler() | |
89 | + } | |
90 | + } | |
91 | + } | |
92 | + } | |
93 | + } else { | |
94 | + if let restoreDate = CachingManager.shared.expirationDate { | |
95 | + if Date().timeIntervalSince1970 < restoreDate { | |
96 | + turnOnAdBlocker() | |
97 | + } else { | |
98 | + presentSubscriptionHandler() | |
99 | + } | |
100 | + } else { | |
101 | + DateManager.shared.getSubscriptionExpirationDate() | |
102 | + let restoreDate = CachingManager.shared.expirationDate | |
103 | + if Date().timeIntervalSince1970 < restoreDate ?? 0 { | |
104 | + turnOnAdBlocker() | |
105 | + } else { | |
106 | + presentSubscriptionHandler() | |
107 | + } | |
108 | + } | |
109 | + } | |
110 | + } | |
111 | + | |
61 | 112 | private func addTargets() { |
62 | 113 | mainView.adBlockButton.addTarget(self, action: #selector(adBlockerButtonPressed(_ :)), for: .touchUpInside) |
63 | 114 | |
... | ... | @@ -65,13 +116,19 @@ extension RemoveAdvertViewController { |
65 | 116 | } |
66 | 117 | |
67 | 118 | private func presentSubscriptionHandler() { |
68 | - if(storeKit.purchasedSubscriptions.isEmpty) { | |
69 | - let subcriptionViewController = SubscriptionViewController() | |
119 | + let subcriptionViewController = SubscriptionViewController(storeKit: storeKit, complition: testHandler) | |
70 | 120 | subcriptionViewController.modalPresentationStyle = .fullScreen |
71 | 121 | subcriptionViewController.modalTransitionStyle = .crossDissolve |
72 | 122 | |
73 | 123 | present(subcriptionViewController, animated: true) |
74 | - } | |
124 | + } | |
125 | + | |
126 | + private func testHandler() { | |
127 | + let alert = UIAlertController(title: "Congradulations!", message: "Success by subscription", preferredStyle: .alert) | |
128 | + let okAction = UIAlertAction(title: "OK", style: .default) | |
129 | + alert.addAction(okAction) | |
130 | + present(alert, animated: true) | |
131 | + turnOnAdBlocker() | |
75 | 132 | } |
76 | 133 | |
77 | 134 | private func setupTableView() { |
... | ... | @@ -79,33 +136,21 @@ extension RemoveAdvertViewController { |
79 | 136 | mainView.adBlockTableView.delegate = self |
80 | 137 | mainView.adBlockTableView.register(RemoveAdvertTableViewCell.self, forCellReuseIdentifier: RemoveAdvertTableViewCell.cellID) |
81 | 138 | } |
82 | - | |
83 | - func successfullPurchaseHandler() { | |
84 | - self.mainView.adBlockButton.buttonImageView.image = .adBlockOnState | |
85 | - self.mainView.tapActionLabel.textColor = ColorConstants.SearchbarTintBlue | |
86 | - self.mainView.tapActionLabel.text = StringConstants.turnOff | |
139 | + | |
140 | + private func turnOnAdBlocker() { | |
141 | + mainView.adBlockButton.buttonImageView.image = .adBlockOnState | |
142 | + mainView.tapActionLabel.textColor = ColorConstants.SearchbarTintBlue | |
143 | + mainView.tapActionLabel.text = StringConstants.turnOff | |
87 | 144 | |
88 | - CachingManager.shared.isAdBlocking = true | |
145 | + CachingManager.shared.adBlockerState = true | |
89 | 146 | } |
90 | 147 | |
91 | - func viewAdBlockingHandler() { | |
92 | - if CachingManager.shared.isAdBlocking { | |
93 | - mainView.adBlockButton.buttonImageView.image = .adBlockOffState | |
94 | - mainView.tapActionLabel.textColor = ColorConstants.customPink | |
95 | - mainView.tapActionLabel.text = StringConstants.turnOn | |
96 | - | |
97 | - CachingManager.shared.isAdBlocking = false | |
98 | - } else { | |
99 | - if !storeKit.purchasedSubscriptions.isEmpty { | |
100 | - mainView.adBlockButton.buttonImageView.image = .adBlockOnState | |
101 | - mainView.tapActionLabel.textColor = ColorConstants.SearchbarTintBlue | |
102 | - mainView.tapActionLabel.text = StringConstants.turnOff | |
103 | - | |
104 | - CachingManager.shared.isAdBlocking = true | |
105 | - } else { | |
106 | - presentSubscriptionHandler() | |
107 | - } | |
108 | - } | |
148 | + private func turnOffAdBlocker() { | |
149 | + mainView.adBlockButton.buttonImageView.image = .adBlockOffState | |
150 | + mainView.tapActionLabel.textColor = ColorConstants.customPink | |
151 | + mainView.tapActionLabel.text = StringConstants.turnOn | |
152 | + | |
153 | + CachingManager.shared.adBlockerState = false | |
109 | 154 | } |
110 | 155 | } |
111 | 156 | |
... | ... | @@ -121,7 +166,7 @@ extension RemoveAdvertViewController: UITableViewDelegate, UITableViewDataSource |
121 | 166 | return UITableViewCell() |
122 | 167 | } |
123 | 168 | cell.advantagesCellLabel.text = tableViewData[indexPath.row] |
124 | - | |
169 | + | |
125 | 170 | return cell |
126 | 171 | } |
127 | 172 | } | ... | ... |
... | ... | @@ -10,7 +10,7 @@ import UIKit |
10 | 10 | final class AdBlockButton: UIButton { |
11 | 11 | var buttonImageView: UIImageView = { |
12 | 12 | let obj = UIImageView() |
13 | - let userDefaultsAdBlockingValue = CachingManager.shared.isAdBlocking | |
13 | + let userDefaultsAdBlockingValue = CachingManager.shared.adBlockerState | |
14 | 14 | |
15 | 15 | if userDefaultsAdBlockingValue { |
16 | 16 | obj.image = .adBlockOnState | ... | ... |
... | ... | @@ -53,11 +53,10 @@ final class RemoveAdvertView: GradientView { |
53 | 53 | |
54 | 54 | let tapActionLabel: UILabel = { |
55 | 55 | let obj = UILabel() |
56 | - let userDefaultsAdBlockerValue = CachingManager.shared.isAdBlocking | |
56 | + let userDefaultsAdBlockerValue = CachingManager.shared.adBlockerState | |
57 | 57 | |
58 | 58 | obj.text = StringConstants.turnOn |
59 | 59 | obj.font = FontConstants.semiboldFont_24 |
60 | - //ok | |
61 | 60 | if userDefaultsAdBlockerValue { |
62 | 61 | obj.textColor = ColorConstants.SearchbarTintBlue |
63 | 62 | } else { | ... | ... |
... | ... | @@ -45,6 +45,7 @@ final class SearchResultViewController: UIViewController { |
45 | 45 | } |
46 | 46 | } |
47 | 47 | |
48 | +//MARK: URL handling | |
48 | 49 | extension SearchResultViewController { |
49 | 50 | private func urlChecker(_ url: String) { |
50 | 51 | let request = URLRequest(url: URL(string: url) ?? URL(fileURLWithPath: "")) |
... | ... | @@ -56,7 +57,7 @@ extension SearchResultViewController { |
56 | 57 | //MARK: AdBlocker |
57 | 58 | extension SearchResultViewController { |
58 | 59 | private func setupAdBlocker() { |
59 | - let userDefaultsAdblockKey = CachingManager.shared.isAdBlocking | |
60 | + let userDefaultsAdblockKey = CachingManager.shared.adBlockerState | |
60 | 61 | if userDefaultsAdblockKey { |
61 | 62 | WKContentRuleListStore.default().getAvailableContentRuleListIdentifiers { res in |
62 | 63 | if let url = Bundle.main.url(forResource: "blockerList", withExtension: "json"), | ... | ... |
... | ... | @@ -28,12 +28,14 @@ final class SettingViewController: UIViewController { |
28 | 28 | |
29 | 29 | override func viewDidLoad() { |
30 | 30 | super.viewDidLoad() |
31 | + | |
31 | 32 | view.backgroundColor = .white |
32 | 33 | initViewController() |
33 | 34 | } |
34 | 35 | |
35 | 36 | private func initViewController() { |
36 | 37 | navigationController?.isNavigationBarHidden = false |
38 | + | |
37 | 39 | setupSettingTableView() |
38 | 40 | addTargets() |
39 | 41 | } |
... | ... | @@ -104,7 +106,7 @@ extension SettingViewController { |
104 | 106 | setupMessage() |
105 | 107 | case 5: |
106 | 108 | Task { |
107 | - try? await AppStore.sync() | |
109 | + try? await SubscriptionManager.shared.restorePurchase() | |
108 | 110 | } |
109 | 111 | default: |
110 | 112 | break | ... | ... |
... | ... | @@ -10,19 +10,17 @@ import StoreKit |
10 | 10 | |
11 | 11 | |
12 | 12 | final class SubscriptionViewController: UIViewController { |
13 | + | |
13 | 14 | private let mainView = SubscriptionView() |
14 | 15 | |
15 | 16 | private let tableViewData: [String] |
16 | - | |
17 | - | |
18 | - override func viewDidLoad() { | |
19 | - super.viewDidLoad() | |
20 | - | |
21 | - initViewController() | |
22 | - } | |
17 | + private let storeKitManager: SubscriptionManager | |
18 | + private let successCompletion: () -> Void | |
23 | 19 | |
24 | - init() { | |
25 | - self.tableViewData = StringConstants.removeAdvertTableViewData | |
20 | + init(storeKit: SubscriptionManager, complition: @escaping() -> Void) { | |
21 | + tableViewData = StringConstants.removeAdvertTableViewData | |
22 | + storeKitManager = storeKit | |
23 | + successCompletion = complition | |
26 | 24 | |
27 | 25 | super.init(nibName: nil, bundle: nil) |
28 | 26 | } |
... | ... | @@ -31,6 +29,12 @@ final class SubscriptionViewController: UIViewController { |
31 | 29 | fatalError("init(coder:) has not been implemented") |
32 | 30 | } |
33 | 31 | |
32 | + override func viewDidLoad() { | |
33 | + super.viewDidLoad() | |
34 | + | |
35 | + initViewController() | |
36 | + } | |
37 | + | |
34 | 38 | override func loadView() { |
35 | 39 | view = mainView |
36 | 40 | } |
... | ... | @@ -70,6 +74,17 @@ extension SubscriptionViewController { |
70 | 74 | mainView.advantagesTableView.delegate = self |
71 | 75 | mainView.advantagesTableView.register(SubscriptionTableViewCell.self, forCellReuseIdentifier: SubscriptionTableViewCell.cellID) |
72 | 76 | } |
77 | + | |
78 | + @MainActor | |
79 | + private func buySubscription() async throws { | |
80 | + if let adblockerProduct = storeKitManager.storeProducts.first(where: { $0.id == SubscriptionsModel.subscriptionInfo["adBlocker"]}) { | |
81 | + if let transaction = try await storeKitManager.purchase(adblockerProduct) { | |
82 | + CachingManager.shared.expirationDate = transaction.expirationDate?.timeIntervalSince1970 ?? 0 | |
83 | + dismiss(animated: true) | |
84 | + successCompletion() | |
85 | + } | |
86 | + } | |
87 | + } | |
73 | 88 | } |
74 | 89 | |
75 | 90 | |
... | ... | @@ -82,29 +97,14 @@ extension SubscriptionViewController { |
82 | 97 | |
83 | 98 | @objc |
84 | 99 | private func buyAdblocker(_ sender: UIButton) { |
85 | - guard let navigationController = presentingViewController as? NavigationViewController else { | |
86 | - return | |
87 | - } | |
88 | - for viewController in navigationController.viewControllers { | |
89 | - guard let removeAdvertViewController = viewController as? RemoveAdvertViewController else { | |
90 | - return | |
91 | - } | |
92 | - Task { | |
93 | - do { | |
94 | - if let adblockerProduct = removeAdvertViewController.storeKit.storeProducts.first(where: { $0.id == "com.browser.adblocker" }) { | |
95 | - if (try await removeAdvertViewController.storeKit.purchase(adblockerProduct)) != nil { | |
96 | - removeAdvertViewController.successfullPurchaseHandler() | |
97 | - | |
98 | - self.dismiss(animated: true) | |
99 | - } else { | |
100 | - print("Purchase cancelled or pending.") | |
101 | - } | |
102 | - } else { | |
103 | - print("Adblocker product not found.") | |
104 | - } | |
105 | - } catch { | |
106 | - print("Failed to purchase Adblocker: \(error)") | |
107 | - } | |
100 | + Task { | |
101 | + do { | |
102 | + try await buySubscription() | |
103 | + } catch { | |
104 | + let alert = UIAlertController(title: "Fail!", message: "Error with subscription", preferredStyle: .alert) | |
105 | + let okAction = UIAlertAction(title: "OK", style: .default) | |
106 | + alert.addAction(okAction) | |
107 | + present(alert, animated: true) | |
108 | 108 | } |
109 | 109 | } |
110 | 110 | } | ... | ... |
... | ... | @@ -17,7 +17,7 @@ final class SubscriptionView: GradientView { |
17 | 17 | return obj |
18 | 18 | }() |
19 | 19 | |
20 | - let shieldView: UIImageView = { | |
20 | + private let shieldView: UIImageView = { | |
21 | 21 | let obj = UIImageView() |
22 | 22 | obj.image = .shield |
23 | 23 | obj.contentMode = .scaleAspectFit |
... | ... | @@ -96,15 +96,16 @@ final class SubscriptionView: GradientView { |
96 | 96 | setup() |
97 | 97 | } |
98 | 98 | |
99 | + required init?(coder: NSCoder) { | |
100 | + fatalError("init(coder:) has not been implemented") | |
101 | + } | |
102 | + | |
99 | 103 | override func layoutSubviews() { |
100 | 104 | super.layoutSubviews() |
101 | 105 | |
102 | 106 | gradientLayer.frame = subscribeButton.bounds |
103 | 107 | } |
104 | - | |
105 | - required init?(coder: NSCoder) { | |
106 | - fatalError("init(coder:) has not been implemented") | |
107 | - } | |
108 | + | |
108 | 109 | |
109 | 110 | private func setup() { |
110 | 111 | addSubview(closeButton) | ... | ... |
... | ... | @@ -16,7 +16,6 @@ final class NavigationViewController: UINavigationController { |
16 | 16 | } |
17 | 17 | |
18 | 18 | private func initViewController() { |
19 | - view.backgroundColor = .black | |
20 | 19 | delegate = self |
21 | 20 | |
22 | 21 | setStartControllers() |
... | ... | @@ -28,6 +27,7 @@ extension NavigationViewController { |
28 | 27 | private func setStartControllers() { |
29 | 28 | let payloadViewController = PayloadViewController() |
30 | 29 | let removeAdvertViewController = RemoveAdvertViewController() |
30 | + | |
31 | 31 | let cachingManager = CachingManager.shared |
32 | 32 | |
33 | 33 | if cachingManager.isFirstAppLoad == false { | ... | ... |
Please
register
or
login
to post a comment