Commit 6306e3dda49a4362c0c8505df2e64b64e4f3398c

Authored by Artem Talko
1 parent f1aa2730

subscription added + redesign + fixed tabs open

Showing 100 changed files with 2442 additions and 540 deletions

Too many changes to show.

To preserve performance only 100 of 100+ files are displayed.

No preview for this file type
@@ -27,14 +27,23 @@ @@ -27,14 +27,23 @@
27 191BB87F2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB87E2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift */; }; 27 191BB87F2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB87E2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift */; };
28 191BB8812AC6FF6600A2DEB9 /* RemoveAdvertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB8802AC6FF6600A2DEB9 /* RemoveAdvertView.swift */; }; 28 191BB8812AC6FF6600A2DEB9 /* RemoveAdvertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB8802AC6FF6600A2DEB9 /* RemoveAdvertView.swift */; };
29 1926E82F2B03BED200FEBCFB /* HistoryToolbarMenuCases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1926E82E2B03BED200FEBCFB /* HistoryToolbarMenuCases.swift */; }; 29 1926E82F2B03BED200FEBCFB /* HistoryToolbarMenuCases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1926E82E2B03BED200FEBCFB /* HistoryToolbarMenuCases.swift */; };
  30 + 192BC8202B16173700A8A426 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 192BC81F2B16173700A8A426 /* StoreKit.framework */; };
30 193B3B832ACAF394002161ED /* BrowserTabDataBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193B3B822ACAF394002161ED /* BrowserTabDataBase.swift */; }; 31 193B3B832ACAF394002161ED /* BrowserTabDataBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193B3B822ACAF394002161ED /* BrowserTabDataBase.swift */; };
31 193B3B862ACAF480002161ED /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = 193B3B852ACAF480002161ED /* Realm */; }; 32 193B3B862ACAF480002161ED /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = 193B3B852ACAF480002161ED /* Realm */; };
32 193B3B882ACAF480002161ED /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 193B3B872ACAF480002161ED /* RealmSwift */; }; 33 193B3B882ACAF480002161ED /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 193B3B872ACAF480002161ED /* RealmSwift */; };
33 193B3B8A2ACAF714002161ED /* TabManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193B3B892ACAF714002161ED /* TabManager.swift */; }; 34 193B3B8A2ACAF714002161ED /* TabManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193B3B892ACAF714002161ED /* TabManager.swift */; };
  35 + 194206C52B10D267000C1263 /* ProductList.plist in Resources */ = {isa = PBXBuildFile; fileRef = 194206C42B10D267000C1263 /* ProductList.plist */; };
  36 + 194206C82B10DFC6000C1263 /* RemoveAdvertTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194206C72B10DFC6000C1263 /* RemoveAdvertTableViewCell.swift */; };
34 194635D62ADD738E00993D91 /* HistoryDataBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194635D52ADD738E00993D91 /* HistoryDataBase.swift */; }; 37 194635D62ADD738E00993D91 /* HistoryDataBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194635D52ADD738E00993D91 /* HistoryDataBase.swift */; };
35 19696AF52AE80DBD00D1F8F9 /* blockerList.json in Resources */ = {isa = PBXBuildFile; fileRef = 19696AF42AE80DBD00D1F8F9 /* blockerList.json */; }; 38 19696AF52AE80DBD00D1F8F9 /* blockerList.json in Resources */ = {isa = PBXBuildFile; fileRef = 19696AF42AE80DBD00D1F8F9 /* blockerList.json */; };
36 19696AF72AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19696AF62AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift */; }; 39 19696AF72AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19696AF62AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift */; };
37 19696AFB2AE80DBD00D1F8F9 /* AdBlocker.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 40 19696AFB2AE80DBD00D1F8F9 /* AdBlocker.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
  41 + 197534762B10968E000818D3 /* SubscriptionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197534752B10968E000818D3 /* SubscriptionViewController.swift */; };
  42 + 197534782B1096A7000818D3 /* SubscriptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197534772B1096A7000818D3 /* SubscriptionView.swift */; };
  43 + 1975347B2B109A37000818D3 /* SubscriptionTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1975347A2B109A37000818D3 /* SubscriptionTableViewCell.swift */; };
  44 + 197C2A242B0E3A7B0010B386 /* AdBlockButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197C2A232B0E3A7B0010B386 /* AdBlockButton.swift */; };
  45 + 197C2A282B0F65840010B386 /* OpenBrowserHomeTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197C2A272B0F65830010B386 /* OpenBrowserHomeTransition.swift */; };
  46 + 197C2A2D2B0F9EEB0010B386 /* StoreKitManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197C2A2C2B0F9EEB0010B386 /* StoreKitManager.swift */; };
38 197FC3EF2AC21E1F007F429C /* PayloadViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3EE2AC21E1F007F429C /* PayloadViewController.swift */; }; 47 197FC3EF2AC21E1F007F429C /* PayloadViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3EE2AC21E1F007F429C /* PayloadViewController.swift */; };
39 197FC3F22AC2AF9A007F429C /* AdvantagesTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3F12AC2AF9A007F429C /* AdvantagesTableViewCell.swift */; }; 48 197FC3F22AC2AF9A007F429C /* AdvantagesTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3F12AC2AF9A007F429C /* AdvantagesTableViewCell.swift */; };
40 197FC3F42AC2BCD7007F429C /* SearchBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3F32AC2BCD7007F429C /* SearchBarView.swift */; }; 49 197FC3F42AC2BCD7007F429C /* SearchBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3F32AC2BCD7007F429C /* SearchBarView.swift */; };
@@ -57,8 +66,8 @@ @@ -57,8 +66,8 @@
57 19B739712AE157900073AA59 /* FontConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B739702AE157900073AA59 /* FontConstants.swift */; }; 66 19B739712AE157900073AA59 /* FontConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B739702AE157900073AA59 /* FontConstants.swift */; };
58 19B739732AE15B3B0073AA59 /* ColorConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B739722AE15B3B0073AA59 /* ColorConstants.swift */; }; 67 19B739732AE15B3B0073AA59 /* ColorConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B739722AE15B3B0073AA59 /* ColorConstants.swift */; };
59 19B739762AE276360073AA59 /* HistoryElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B739752AE276360073AA59 /* HistoryElement.swift */; }; 68 19B739762AE276360073AA59 /* HistoryElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B739752AE276360073AA59 /* HistoryElement.swift */; };
  69 + 19C33E992B0DF91D006BFD72 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C33E982B0DF91D006BFD72 /* GradientView.swift */; };
60 19C5F0572AD9784400133BD7 /* DataExtention+toImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C5F0562AD9784400133BD7 /* DataExtention+toImage.swift */; }; 70 19C5F0572AD9784400133BD7 /* DataExtention+toImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C5F0562AD9784400133BD7 /* DataExtention+toImage.swift */; };
61 - 19C7A70C2AC9EBB800B954FC /* RemoveAdvertTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7A70B2AC9EBB800B954FC /* RemoveAdvertTableViewCell.swift */; };  
62 19C7A70E2AC9F5FD00B954FC /* HistorySearchBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7A70D2AC9F5FD00B954FC /* HistorySearchBarView.swift */; }; 71 19C7A70E2AC9F5FD00B954FC /* HistorySearchBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7A70D2AC9F5FD00B954FC /* HistorySearchBarView.swift */; };
63 19CD89482AC719AC0035CB55 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 19CD89472AC719AC0035CB55 /* SnapKit */; }; 72 19CD89482AC719AC0035CB55 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 19CD89472AC719AC0035CB55 /* SnapKit */; };
64 19D1F2E02AC1EF3200510506 /* PayloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19D1F2DF2AC1EF3200510506 /* PayloadView.swift */; }; 73 19D1F2E02AC1EF3200510506 /* PayloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19D1F2DF2AC1EF3200510506 /* PayloadView.swift */; };
@@ -119,13 +128,23 @@ @@ -119,13 +128,23 @@
119 191BB87E2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryToolbarView.swift; sourceTree = "<group>"; }; 128 191BB87E2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryToolbarView.swift; sourceTree = "<group>"; };
120 191BB8802AC6FF6600A2DEB9 /* RemoveAdvertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveAdvertView.swift; sourceTree = "<group>"; }; 129 191BB8802AC6FF6600A2DEB9 /* RemoveAdvertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveAdvertView.swift; sourceTree = "<group>"; };
121 1926E82E2B03BED200FEBCFB /* HistoryToolbarMenuCases.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryToolbarMenuCases.swift; sourceTree = "<group>"; }; 130 1926E82E2B03BED200FEBCFB /* HistoryToolbarMenuCases.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryToolbarMenuCases.swift; sourceTree = "<group>"; };
  131 + 192BC81F2B16173700A8A426 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
  132 + 192BC8212B16326B00A8A426 /* StoreKitSubscription.storekit */ = {isa = PBXFileReference; lastKnownFileType = text; path = StoreKitSubscription.storekit; sourceTree = "<group>"; };
122 193B3B822ACAF394002161ED /* BrowserTabDataBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserTabDataBase.swift; sourceTree = "<group>"; }; 133 193B3B822ACAF394002161ED /* BrowserTabDataBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserTabDataBase.swift; sourceTree = "<group>"; };
123 193B3B892ACAF714002161ED /* TabManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabManager.swift; sourceTree = "<group>"; }; 134 193B3B892ACAF714002161ED /* TabManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabManager.swift; sourceTree = "<group>"; };
  135 + 194206C42B10D267000C1263 /* ProductList.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = ProductList.plist; sourceTree = "<group>"; };
  136 + 194206C72B10DFC6000C1263 /* RemoveAdvertTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveAdvertTableViewCell.swift; sourceTree = "<group>"; };
124 194635D52ADD738E00993D91 /* HistoryDataBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryDataBase.swift; sourceTree = "<group>"; }; 137 194635D52ADD738E00993D91 /* HistoryDataBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryDataBase.swift; sourceTree = "<group>"; };
125 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = AdBlocker.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 138 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = AdBlocker.appex; sourceTree = BUILT_PRODUCTS_DIR; };
126 19696AF42AE80DBD00D1F8F9 /* blockerList.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = blockerList.json; sourceTree = "<group>"; }; 139 19696AF42AE80DBD00D1F8F9 /* blockerList.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = blockerList.json; sourceTree = "<group>"; };
127 19696AF62AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentBlockerRequestHandler.swift; sourceTree = "<group>"; }; 140 19696AF62AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentBlockerRequestHandler.swift; sourceTree = "<group>"; };
128 19696AF82AE80DBD00D1F8F9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 141 19696AF82AE80DBD00D1F8F9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
  142 + 197534752B10968E000818D3 /* SubscriptionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionViewController.swift; sourceTree = "<group>"; };
  143 + 197534772B1096A7000818D3 /* SubscriptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionView.swift; sourceTree = "<group>"; };
  144 + 1975347A2B109A37000818D3 /* SubscriptionTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionTableViewCell.swift; sourceTree = "<group>"; };
  145 + 197C2A232B0E3A7B0010B386 /* AdBlockButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdBlockButton.swift; sourceTree = "<group>"; };
  146 + 197C2A272B0F65830010B386 /* OpenBrowserHomeTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenBrowserHomeTransition.swift; sourceTree = "<group>"; };
  147 + 197C2A2C2B0F9EEB0010B386 /* StoreKitManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreKitManager.swift; sourceTree = "<group>"; };
129 197FC3EE2AC21E1F007F429C /* PayloadViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayloadViewController.swift; sourceTree = "<group>"; }; 148 197FC3EE2AC21E1F007F429C /* PayloadViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayloadViewController.swift; sourceTree = "<group>"; };
130 197FC3F12AC2AF9A007F429C /* AdvantagesTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvantagesTableViewCell.swift; sourceTree = "<group>"; }; 149 197FC3F12AC2AF9A007F429C /* AdvantagesTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvantagesTableViewCell.swift; sourceTree = "<group>"; };
131 197FC3F32AC2BCD7007F429C /* SearchBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBarView.swift; sourceTree = "<group>"; }; 150 197FC3F32AC2BCD7007F429C /* SearchBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBarView.swift; sourceTree = "<group>"; };
@@ -147,13 +166,13 @@ @@ -147,13 +166,13 @@
147 19B739702AE157900073AA59 /* FontConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontConstants.swift; sourceTree = "<group>"; }; 166 19B739702AE157900073AA59 /* FontConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontConstants.swift; sourceTree = "<group>"; };
148 19B739722AE15B3B0073AA59 /* ColorConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorConstants.swift; sourceTree = "<group>"; }; 167 19B739722AE15B3B0073AA59 /* ColorConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorConstants.swift; sourceTree = "<group>"; };
149 19B739752AE276360073AA59 /* HistoryElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryElement.swift; sourceTree = "<group>"; }; 168 19B739752AE276360073AA59 /* HistoryElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryElement.swift; sourceTree = "<group>"; };
  169 + 19C33E982B0DF91D006BFD72 /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = "<group>"; };
150 19C5F0562AD9784400133BD7 /* DataExtention+toImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataExtention+toImage.swift"; sourceTree = "<group>"; }; 170 19C5F0562AD9784400133BD7 /* DataExtention+toImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataExtention+toImage.swift"; sourceTree = "<group>"; };
151 - 19C7A70B2AC9EBB800B954FC /* RemoveAdvertTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveAdvertTableViewCell.swift; sourceTree = "<group>"; };  
152 19C7A70D2AC9F5FD00B954FC /* HistorySearchBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistorySearchBarView.swift; sourceTree = "<group>"; }; 171 19C7A70D2AC9F5FD00B954FC /* HistorySearchBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistorySearchBarView.swift; sourceTree = "<group>"; };
153 19D1F2DF2AC1EF3200510506 /* PayloadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayloadView.swift; sourceTree = "<group>"; }; 172 19D1F2DF2AC1EF3200510506 /* PayloadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayloadView.swift; sourceTree = "<group>"; };
154 19EECA442ACED45A00094AFB /* SearchResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultView.swift; sourceTree = "<group>"; }; 173 19EECA442ACED45A00094AFB /* SearchResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultView.swift; sourceTree = "<group>"; };
155 19EECA462ACED48000094AFB /* SearchResultViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultViewController.swift; sourceTree = "<group>"; }; 174 19EECA462ACED48000094AFB /* SearchResultViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultViewController.swift; sourceTree = "<group>"; };
156 - 19FCBF1E2AC1727800F83A7F /* browser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = browser.app; sourceTree = BUILT_PRODUCTS_DIR; }; 175 + 19FCBF1E2AC1727800F83A7F /* Pro-Seecurity-VPN.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Pro-Seecurity-VPN.app"; sourceTree = BUILT_PRODUCTS_DIR; };
157 19FCBF212AC1727800F83A7F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 176 19FCBF212AC1727800F83A7F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
158 19FCBF252AC1727800F83A7F /* BrowserHomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHomeViewController.swift; sourceTree = "<group>"; }; 177 19FCBF252AC1727800F83A7F /* BrowserHomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHomeViewController.swift; sourceTree = "<group>"; };
159 19FCBF2A2AC1727900F83A7F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 178 19FCBF2A2AC1727900F83A7F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@@ -178,6 +197,7 @@ @@ -178,6 +197,7 @@
178 files = ( 197 files = (
179 193B3B882ACAF480002161ED /* RealmSwift in Frameworks */, 198 193B3B882ACAF480002161ED /* RealmSwift in Frameworks */,
180 199DB1F12AD3FDEE007E6A81 /* Alamofire in Frameworks */, 199 199DB1F12AD3FDEE007E6A81 /* Alamofire in Frameworks */,
  200 + 192BC8202B16173700A8A426 /* StoreKit.framework in Frameworks */,
181 193B3B862ACAF480002161ED /* Realm in Frameworks */, 201 193B3B862ACAF480002161ED /* Realm in Frameworks */,
182 19CD89482AC719AC0035CB55 /* SnapKit in Frameworks */, 202 19CD89482AC719AC0035CB55 /* SnapKit in Frameworks */,
183 ); 203 );
@@ -198,7 +218,8 @@ @@ -198,7 +218,8 @@
198 190DB9F82AC44FD4000A7BF3 /* View */ = { 218 190DB9F82AC44FD4000A7BF3 /* View */ = {
199 isa = PBXGroup; 219 isa = PBXGroup;
200 children = ( 220 children = (
201 - 19C7A70A2AC9EB9B00B954FC /* Cell */, 221 + 194206C62B10DFAF000C1263 /* Cell */,
  222 + 197C2A222B0E3A420010B386 /* Components */,
202 191BB8802AC6FF6600A2DEB9 /* RemoveAdvertView.swift */, 223 191BB8802AC6FF6600A2DEB9 /* RemoveAdvertView.swift */,
203 ); 224 );
204 path = View; 225 path = View;
@@ -215,6 +236,7 @@ @@ -215,6 +236,7 @@
215 190DB9FD2AC459CD000A7BF3 /* Managers */ = { 236 190DB9FD2AC459CD000A7BF3 /* Managers */ = {
216 isa = PBXGroup; 237 isa = PBXGroup;
217 children = ( 238 children = (
  239 + 197C2A2C2B0F9EEB0010B386 /* StoreKitManager.swift */,
218 190DB9FF2AC45A3C000A7BF3 /* CachingManager.swift */, 240 190DB9FF2AC45A3C000A7BF3 /* CachingManager.swift */,
219 193B3B892ACAF714002161ED /* TabManager.swift */, 241 193B3B892ACAF714002161ED /* TabManager.swift */,
220 1907D6962ADE766F00C40E9F /* HistoryDBManager.swift */, 242 1907D6962ADE766F00C40E9F /* HistoryDBManager.swift */,
@@ -373,6 +395,14 @@ @@ -373,6 +395,14 @@
373 path = Components; 395 path = Components;
374 sourceTree = "<group>"; 396 sourceTree = "<group>";
375 }; 397 };
  398 + 192BC81E2B16173700A8A426 /* Frameworks */ = {
  399 + isa = PBXGroup;
  400 + children = (
  401 + 192BC81F2B16173700A8A426 /* StoreKit.framework */,
  402 + );
  403 + name = Frameworks;
  404 + sourceTree = "<group>";
  405 + };
376 193B3B812ACAF36C002161ED /* DataBases */ = { 406 193B3B812ACAF36C002161ED /* DataBases */ = {
377 isa = PBXGroup; 407 isa = PBXGroup;
378 children = ( 408 children = (
@@ -382,6 +412,14 @@ @@ -382,6 +412,14 @@
382 path = DataBases; 412 path = DataBases;
383 sourceTree = "<group>"; 413 sourceTree = "<group>";
384 }; 414 };
  415 + 194206C62B10DFAF000C1263 /* Cell */ = {
  416 + isa = PBXGroup;
  417 + children = (
  418 + 194206C72B10DFC6000C1263 /* RemoveAdvertTableViewCell.swift */,
  419 + );
  420 + path = Cell;
  421 + sourceTree = "<group>";
  422 + };
385 19696AF32AE80DBD00D1F8F9 /* AdBlocker */ = { 423 19696AF32AE80DBD00D1F8F9 /* AdBlocker */ = {
386 isa = PBXGroup; 424 isa = PBXGroup;
387 children = ( 425 children = (
@@ -391,6 +429,48 @@ @@ -391,6 +429,48 @@
391 path = AdBlocker; 429 path = AdBlocker;
392 sourceTree = "<group>"; 430 sourceTree = "<group>";
393 }; 431 };
  432 + 197534722B10965F000818D3 /* Subscription */ = {
  433 + isa = PBXGroup;
  434 + children = (
  435 + 197534742B10967B000818D3 /* Controller */,
  436 + 197534732B109675000818D3 /* View */,
  437 + );
  438 + path = Subscription;
  439 + sourceTree = "<group>";
  440 + };
  441 + 197534732B109675000818D3 /* View */ = {
  442 + isa = PBXGroup;
  443 + children = (
  444 + 197534792B109A27000818D3 /* Cell */,
  445 + 197534772B1096A7000818D3 /* SubscriptionView.swift */,
  446 + );
  447 + path = View;
  448 + sourceTree = "<group>";
  449 + };
  450 + 197534742B10967B000818D3 /* Controller */ = {
  451 + isa = PBXGroup;
  452 + children = (
  453 + 197534752B10968E000818D3 /* SubscriptionViewController.swift */,
  454 + );
  455 + path = Controller;
  456 + sourceTree = "<group>";
  457 + };
  458 + 197534792B109A27000818D3 /* Cell */ = {
  459 + isa = PBXGroup;
  460 + children = (
  461 + 1975347A2B109A37000818D3 /* SubscriptionTableViewCell.swift */,
  462 + );
  463 + path = Cell;
  464 + sourceTree = "<group>";
  465 + };
  466 + 197C2A222B0E3A420010B386 /* Components */ = {
  467 + isa = PBXGroup;
  468 + children = (
  469 + 197C2A232B0E3A7B0010B386 /* AdBlockButton.swift */,
  470 + );
  471 + path = Components;
  472 + sourceTree = "<group>";
  473 + };
394 197FC3F02AC2AF8A007F429C /* Cell */ = { 474 197FC3F02AC2AF8A007F429C /* Cell */ = {
395 isa = PBXGroup; 475 isa = PBXGroup;
396 children = ( 476 children = (
@@ -555,12 +635,12 @@ @@ -555,12 +635,12 @@
555 path = Models; 635 path = Models;
556 sourceTree = "<group>"; 636 sourceTree = "<group>";
557 }; 637 };
558 - 19C7A70A2AC9EB9B00B954FC /* Cell */ = { 638 + 19C33E972B0DF8FA006BFD72 /* ReusableElements */ = {
559 isa = PBXGroup; 639 isa = PBXGroup;
560 children = ( 640 children = (
561 - 19C7A70B2AC9EBB800B954FC /* RemoveAdvertTableViewCell.swift */, 641 + 19C33E982B0DF91D006BFD72 /* GradientView.swift */,
562 ); 642 );
563 - path = Cell; 643 + path = ReusableElements;
564 sourceTree = "<group>"; 644 sourceTree = "<group>";
565 }; 645 };
566 19D1F2DC2AC1EE6200510506 /* Payload */ = { 646 19D1F2DC2AC1EE6200510506 /* Payload */ = {
@@ -621,6 +701,7 @@ @@ -621,6 +701,7 @@
621 isa = PBXGroup; 701 isa = PBXGroup;
622 children = ( 702 children = (
623 1989A15F2AE29D4B00292680 /* OpenTabsTransition.swift */, 703 1989A15F2AE29D4B00292680 /* OpenTabsTransition.swift */,
  704 + 197C2A272B0F65830010B386 /* OpenBrowserHomeTransition.swift */,
624 ); 705 );
625 path = Transitions; 706 path = Transitions;
626 sourceTree = "<group>"; 707 sourceTree = "<group>";
@@ -628,16 +709,18 @@ @@ -628,16 +709,18 @@
628 19FCBF152AC1727800F83A7F = { 709 19FCBF152AC1727800F83A7F = {
629 isa = PBXGroup; 710 isa = PBXGroup;
630 children = ( 711 children = (
  712 + 192BC8212B16326B00A8A426 /* StoreKitSubscription.storekit */,
631 19FCBF202AC1727800F83A7F /* browser */, 713 19FCBF202AC1727800F83A7F /* browser */,
632 19696AF32AE80DBD00D1F8F9 /* AdBlocker */, 714 19696AF32AE80DBD00D1F8F9 /* AdBlocker */,
633 19FCBF1F2AC1727800F83A7F /* Products */, 715 19FCBF1F2AC1727800F83A7F /* Products */,
  716 + 192BC81E2B16173700A8A426 /* Frameworks */,
634 ); 717 );
635 sourceTree = "<group>"; 718 sourceTree = "<group>";
636 }; 719 };
637 19FCBF1F2AC1727800F83A7F /* Products */ = { 720 19FCBF1F2AC1727800F83A7F /* Products */ = {
638 isa = PBXGroup; 721 isa = PBXGroup;
639 children = ( 722 children = (
640 - 19FCBF1E2AC1727800F83A7F /* browser.app */, 723 + 19FCBF1E2AC1727800F83A7F /* Pro-Seecurity-VPN.app */,
641 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */, 724 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */,
642 ); 725 );
643 name = Products; 726 name = Products;
@@ -657,6 +740,7 @@ @@ -657,6 +740,7 @@
657 19FCBF352AC1779800F83A7F /* Navigation */, 740 19FCBF352AC1779800F83A7F /* Navigation */,
658 19FCBF212AC1727800F83A7F /* AppDelegate.swift */, 741 19FCBF212AC1727800F83A7F /* AppDelegate.swift */,
659 19FCBF2F2AC1727900F83A7F /* Info.plist */, 742 19FCBF2F2AC1727900F83A7F /* Info.plist */,
  743 + 194206C42B10D267000C1263 /* ProductList.plist */,
660 ); 744 );
661 path = browser; 745 path = browser;
662 sourceTree = "<group>"; 746 sourceTree = "<group>";
@@ -672,6 +756,8 @@ @@ -672,6 +756,8 @@
672 19FCBF382AC17A4800F83A7F /* Modules */ = { 756 19FCBF382AC17A4800F83A7F /* Modules */ = {
673 isa = PBXGroup; 757 isa = PBXGroup;
674 children = ( 758 children = (
  759 + 197534722B10965F000818D3 /* Subscription */,
  760 + 19C33E972B0DF8FA006BFD72 /* ReusableElements */,
675 19B2D0AF2ACDEAB600D20CE8 /* SearchResult */, 761 19B2D0AF2ACDEAB600D20CE8 /* SearchResult */,
676 191BB8702AC6B19F00A2DEB9 /* History */, 762 191BB8702AC6B19F00A2DEB9 /* History */,
677 191BB85D2AC69FC800A2DEB9 /* Searching */, 763 191BB85D2AC69FC800A2DEB9 /* Searching */,
@@ -739,9 +825,9 @@ @@ -739,9 +825,9 @@
739 productReference = 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */; 825 productReference = 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */;
740 productType = "com.apple.product-type.app-extension"; 826 productType = "com.apple.product-type.app-extension";
741 }; 827 };
742 - 19FCBF1D2AC1727800F83A7F /* browser */ = { 828 + 19FCBF1D2AC1727800F83A7F /* Pro-Seecurity-VPN */ = {
743 isa = PBXNativeTarget; 829 isa = PBXNativeTarget;
744 - buildConfigurationList = 19FCBF322AC1727900F83A7F /* Build configuration list for PBXNativeTarget "browser" */; 830 + buildConfigurationList = 19FCBF322AC1727900F83A7F /* Build configuration list for PBXNativeTarget "Pro-Seecurity-VPN" */;
745 buildPhases = ( 831 buildPhases = (
746 19FCBF1A2AC1727800F83A7F /* Sources */, 832 19FCBF1A2AC1727800F83A7F /* Sources */,
747 19FCBF1B2AC1727800F83A7F /* Frameworks */, 833 19FCBF1B2AC1727800F83A7F /* Frameworks */,
@@ -753,7 +839,7 @@ @@ -753,7 +839,7 @@
753 dependencies = ( 839 dependencies = (
754 19696AFA2AE80DBD00D1F8F9 /* PBXTargetDependency */, 840 19696AFA2AE80DBD00D1F8F9 /* PBXTargetDependency */,
755 ); 841 );
756 - name = browser; 842 + name = "Pro-Seecurity-VPN";
757 packageProductDependencies = ( 843 packageProductDependencies = (
758 19CD89472AC719AC0035CB55 /* SnapKit */, 844 19CD89472AC719AC0035CB55 /* SnapKit */,
759 193B3B852ACAF480002161ED /* Realm */, 845 193B3B852ACAF480002161ED /* Realm */,
@@ -761,7 +847,7 @@ @@ -761,7 +847,7 @@
761 199DB1F02AD3FDEE007E6A81 /* Alamofire */, 847 199DB1F02AD3FDEE007E6A81 /* Alamofire */,
762 ); 848 );
763 productName = browser; 849 productName = browser;
764 - productReference = 19FCBF1E2AC1727800F83A7F /* browser.app */; 850 + productReference = 19FCBF1E2AC1727800F83A7F /* Pro-Seecurity-VPN.app */;
765 productType = "com.apple.product-type.application"; 851 productType = "com.apple.product-type.application";
766 }; 852 };
767 /* End PBXNativeTarget section */ 853 /* End PBXNativeTarget section */
@@ -782,7 +868,7 @@ @@ -782,7 +868,7 @@
782 }; 868 };
783 }; 869 };
784 }; 870 };
785 - buildConfigurationList = 19FCBF192AC1727800F83A7F /* Build configuration list for PBXProject "browser" */; 871 + buildConfigurationList = 19FCBF192AC1727800F83A7F /* Build configuration list for PBXProject "Pro-Seecurity-VPN" */;
786 compatibilityVersion = "Xcode 14.0"; 872 compatibilityVersion = "Xcode 14.0";
787 developmentRegion = en; 873 developmentRegion = en;
788 hasScannedForEncodings = 0; 874 hasScannedForEncodings = 0;
@@ -800,7 +886,7 @@ @@ -800,7 +886,7 @@
800 projectDirPath = ""; 886 projectDirPath = "";
801 projectRoot = ""; 887 projectRoot = "";
802 targets = ( 888 targets = (
803 - 19FCBF1D2AC1727800F83A7F /* browser */, 889 + 19FCBF1D2AC1727800F83A7F /* Pro-Seecurity-VPN */,
804 19696AF12AE80DBC00D1F8F9 /* AdBlocker */, 890 19696AF12AE80DBC00D1F8F9 /* AdBlocker */,
805 ); 891 );
806 }; 892 };
@@ -819,6 +905,7 @@ @@ -819,6 +905,7 @@
819 isa = PBXResourcesBuildPhase; 905 isa = PBXResourcesBuildPhase;
820 buildActionMask = 2147483647; 906 buildActionMask = 2147483647;
821 files = ( 907 files = (
  908 + 194206C52B10D267000C1263 /* ProductList.plist in Resources */,
822 1904ED472AC56BDB0035DB66 /* FontsFree-Net-SFProText-Semibold.ttf in Resources */, 909 1904ED472AC56BDB0035DB66 /* FontsFree-Net-SFProText-Semibold.ttf in Resources */,
823 19FCBF2E2AC1727900F83A7F /* LaunchScreen.storyboard in Resources */, 910 19FCBF2E2AC1727900F83A7F /* LaunchScreen.storyboard in Resources */,
824 1904ED482AC56BDB0035DB66 /* FontsFree-Net-SFProText-Regular.ttf in Resources */, 911 1904ED482AC56BDB0035DB66 /* FontsFree-Net-SFProText-Regular.ttf in Resources */,
@@ -850,11 +937,15 @@ @@ -850,11 +937,15 @@
850 19FCBF262AC1727800F83A7F /* BrowserHomeViewController.swift in Sources */, 937 19FCBF262AC1727800F83A7F /* BrowserHomeViewController.swift in Sources */,
851 197FC3FF2AC30746007F429C /* SettingTableViewCell.swift in Sources */, 938 197FC3FF2AC30746007F429C /* SettingTableViewCell.swift in Sources */,
852 19B41DA12AD81A70002C0D31 /* SearchBarContainer.swift in Sources */, 939 19B41DA12AD81A70002C0D31 /* SearchBarContainer.swift in Sources */,
  940 + 19C33E992B0DF91D006BFD72 /* GradientView.swift in Sources */,
853 19EECA452ACED45A00094AFB /* SearchResultView.swift in Sources */, 941 19EECA452ACED45A00094AFB /* SearchResultView.swift in Sources */,
854 1907D6972ADE766F00C40E9F /* HistoryDBManager.swift in Sources */, 942 1907D6972ADE766F00C40E9F /* HistoryDBManager.swift in Sources */,
855 19B739762AE276360073AA59 /* HistoryElement.swift in Sources */, 943 19B739762AE276360073AA59 /* HistoryElement.swift in Sources */,
  944 + 197534762B10968E000818D3 /* SubscriptionViewController.swift in Sources */,
856 197FC4032AC41EB7007F429C /* ToolbarView.swift in Sources */, 945 197FC4032AC41EB7007F429C /* ToolbarView.swift in Sources */,
857 19B7396A2AE1554E0073AA59 /* URLConstants.swift in Sources */, 946 19B7396A2AE1554E0073AA59 /* URLConstants.swift in Sources */,
  947 + 197534782B1096A7000818D3 /* SubscriptionView.swift in Sources */,
  948 + 197C2A2D2B0F9EEB0010B386 /* StoreKitManager.swift in Sources */,
858 19EECA472ACED48000094AFB /* SearchResultViewController.swift in Sources */, 949 19EECA472ACED48000094AFB /* SearchResultViewController.swift in Sources */,
859 191BB8572AC5B4AC00A2DEB9 /* OpenedTabsCollectionViewCell.swift in Sources */, 950 191BB8572AC5B4AC00A2DEB9 /* OpenedTabsCollectionViewCell.swift in Sources */,
860 190DB9FC2AC450F6000A7BF3 /* RemoveAdvertViewController.swift in Sources */, 951 190DB9FC2AC450F6000A7BF3 /* RemoveAdvertViewController.swift in Sources */,
@@ -875,12 +966,14 @@ @@ -875,12 +966,14 @@
875 191BB8692AC6A66900A2DEB9 /* SearchingTableViewCell.swift in Sources */, 966 191BB8692AC6A66900A2DEB9 /* SearchingTableViewCell.swift in Sources */,
876 1990C69C2AEFDF89004AF856 /* UICollectionViewCell+convertFrameToScreenCoordinates.swift in Sources */, 967 1990C69C2AEFDF89004AF856 /* UICollectionViewCell+convertFrameToScreenCoordinates.swift in Sources */,
877 19FCBF222AC1727800F83A7F /* AppDelegate.swift in Sources */, 968 19FCBF222AC1727800F83A7F /* AppDelegate.swift in Sources */,
878 - 19C7A70C2AC9EBB800B954FC /* RemoveAdvertTableViewCell.swift in Sources */, 969 + 197C2A242B0E3A7B0010B386 /* AdBlockButton.swift in Sources */,
  970 + 197C2A282B0F65840010B386 /* OpenBrowserHomeTransition.swift in Sources */,
879 19D1F2E02AC1EF3200510506 /* PayloadView.swift in Sources */, 971 19D1F2E02AC1EF3200510506 /* PayloadView.swift in Sources */,
880 19FFD6BF2AE64A7B00D0F768 /* SnapshotService.swift in Sources */, 972 19FFD6BF2AE64A7B00D0F768 /* SnapshotService.swift in Sources */,
881 190DBA0D2AC47701000A7BF3 /* BinaryFloatingPoint.swift in Sources */, 973 190DBA0D2AC47701000A7BF3 /* BinaryFloatingPoint.swift in Sources */,
882 191BB8772AC6B47700A2DEB9 /* HistoryView.swift in Sources */, 974 191BB8772AC6B47700A2DEB9 /* HistoryView.swift in Sources */,
883 19FCBF3D2AC17AB000F83A7F /* BrowserHomeView.swift in Sources */, 975 19FCBF3D2AC17AB000F83A7F /* BrowserHomeView.swift in Sources */,
  976 + 194206C82B10DFC6000C1263 /* RemoveAdvertTableViewCell.swift in Sources */,
884 191BB87F2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift in Sources */, 977 191BB87F2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift in Sources */,
885 1984BF582AFB970F0050F816 /* TermsViewController.swift in Sources */, 978 1984BF582AFB970F0050F816 /* TermsViewController.swift in Sources */,
886 193B3B8A2ACAF714002161ED /* TabManager.swift in Sources */, 979 193B3B8A2ACAF714002161ED /* TabManager.swift in Sources */,
@@ -890,6 +983,7 @@ @@ -890,6 +983,7 @@
890 1984BF5A2AFB973C0050F816 /* TermsView.swift in Sources */, 983 1984BF5A2AFB973C0050F816 /* TermsView.swift in Sources */,
891 197FC3FC2AC2FBA0007F429C /* SettingView.swift in Sources */, 984 197FC3FC2AC2FBA0007F429C /* SettingView.swift in Sources */,
892 191BB8622AC6A01500A2DEB9 /* SearchingViewController.swift in Sources */, 985 191BB8622AC6A01500A2DEB9 /* SearchingViewController.swift in Sources */,
  986 + 1975347B2B109A37000818D3 /* SubscriptionTableViewCell.swift in Sources */,
893 197FC4012AC31D5C007F429C /* NavigationViewController.swift in Sources */, 987 197FC4012AC31D5C007F429C /* NavigationViewController.swift in Sources */,
894 19C5F0572AD9784400133BD7 /* DataExtention+toImage.swift in Sources */, 988 19C5F0572AD9784400133BD7 /* DataExtention+toImage.swift in Sources */,
895 1989A1602AE29D4C00292680 /* OpenTabsTransition.swift in Sources */, 989 1989A1602AE29D4C00292680 /* OpenTabsTransition.swift in Sources */,
@@ -938,7 +1032,7 @@ @@ -938,7 +1032,7 @@
938 "@executable_path/../../Frameworks", 1032 "@executable_path/../../Frameworks",
939 ); 1033 );
940 MARKETING_VERSION = 1.0; 1034 MARKETING_VERSION = 1.0;
941 - PRODUCT_BUNDLE_IDENTIFIER = "com.4k-soft.browser.AdBlock"; 1035 + PRODUCT_BUNDLE_IDENTIFIER = "com.4k.Pro-Seecurity-VPN.test.SafariAdblocker";
942 PRODUCT_NAME = "$(TARGET_NAME)"; 1036 PRODUCT_NAME = "$(TARGET_NAME)";
943 SKIP_INSTALL = YES; 1037 SKIP_INSTALL = YES;
944 SWIFT_EMIT_LOC_STRINGS = YES; 1038 SWIFT_EMIT_LOC_STRINGS = YES;
@@ -965,7 +1059,7 @@ @@ -965,7 +1059,7 @@
965 "@executable_path/../../Frameworks", 1059 "@executable_path/../../Frameworks",
966 ); 1060 );
967 MARKETING_VERSION = 1.0; 1061 MARKETING_VERSION = 1.0;
968 - PRODUCT_BUNDLE_IDENTIFIER = "com.4k-soft.browser.AdBlock"; 1062 + PRODUCT_BUNDLE_IDENTIFIER = "com.4k.Pro-Seecurity-VPN.test.SafariAdblocker";
969 PRODUCT_NAME = "$(TARGET_NAME)"; 1063 PRODUCT_NAME = "$(TARGET_NAME)";
970 SKIP_INSTALL = YES; 1064 SKIP_INSTALL = YES;
971 SWIFT_EMIT_LOC_STRINGS = YES; 1065 SWIFT_EMIT_LOC_STRINGS = YES;
@@ -1107,18 +1201,21 @@ @@ -1107,18 +1201,21 @@
1107 INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 1201 INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
1108 INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 1202 INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
1109 INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; 1203 INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
1110 - INFOPLIST_KEY_UIUserInterfaceStyle = Light; 1204 + INFOPLIST_KEY_UIUserInterfaceStyle = Dark;
1111 IPHONEOS_DEPLOYMENT_TARGET = 15.0; 1205 IPHONEOS_DEPLOYMENT_TARGET = 15.0;
1112 LD_RUNPATH_SEARCH_PATHS = ( 1206 LD_RUNPATH_SEARCH_PATHS = (
1113 "$(inherited)", 1207 "$(inherited)",
1114 "@executable_path/Frameworks", 1208 "@executable_path/Frameworks",
1115 ); 1209 );
1116 - MARKETING_VERSION = 1.0;  
1117 - PRODUCT_BUNDLE_IDENTIFIER = "com.4k-soft.browser"; 1210 + MARKETING_VERSION = 5.1;
  1211 + PRODUCT_BUNDLE_IDENTIFIER = "com.4k.Pro-Seecurity-VPN.test";
1118 PRODUCT_NAME = "$(TARGET_NAME)"; 1212 PRODUCT_NAME = "$(TARGET_NAME)";
  1213 + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
  1214 + SUPPORTS_MACCATALYST = NO;
  1215 + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
1119 SWIFT_EMIT_LOC_STRINGS = YES; 1216 SWIFT_EMIT_LOC_STRINGS = YES;
1120 SWIFT_VERSION = 5.0; 1217 SWIFT_VERSION = 5.0;
1121 - TARGETED_DEVICE_FAMILY = "1,2"; 1218 + TARGETED_DEVICE_FAMILY = 1;
1122 }; 1219 };
1123 name = Debug; 1220 name = Debug;
1124 }; 1221 };
@@ -1136,18 +1233,21 @@ @@ -1136,18 +1233,21 @@
1136 INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 1233 INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
1137 INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 1234 INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
1138 INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; 1235 INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
1139 - INFOPLIST_KEY_UIUserInterfaceStyle = Light; 1236 + INFOPLIST_KEY_UIUserInterfaceStyle = Dark;
1140 IPHONEOS_DEPLOYMENT_TARGET = 15.0; 1237 IPHONEOS_DEPLOYMENT_TARGET = 15.0;
1141 LD_RUNPATH_SEARCH_PATHS = ( 1238 LD_RUNPATH_SEARCH_PATHS = (
1142 "$(inherited)", 1239 "$(inherited)",
1143 "@executable_path/Frameworks", 1240 "@executable_path/Frameworks",
1144 ); 1241 );
1145 - MARKETING_VERSION = 1.0;  
1146 - PRODUCT_BUNDLE_IDENTIFIER = "com.4k-soft.browser"; 1242 + MARKETING_VERSION = 5.1;
  1243 + PRODUCT_BUNDLE_IDENTIFIER = "com.4k.Pro-Seecurity-VPN.test";
1147 PRODUCT_NAME = "$(TARGET_NAME)"; 1244 PRODUCT_NAME = "$(TARGET_NAME)";
  1245 + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
  1246 + SUPPORTS_MACCATALYST = NO;
  1247 + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
1148 SWIFT_EMIT_LOC_STRINGS = YES; 1248 SWIFT_EMIT_LOC_STRINGS = YES;
1149 SWIFT_VERSION = 5.0; 1249 SWIFT_VERSION = 5.0;
1150 - TARGETED_DEVICE_FAMILY = "1,2"; 1250 + TARGETED_DEVICE_FAMILY = 1;
1151 }; 1251 };
1152 name = Release; 1252 name = Release;
1153 }; 1253 };
@@ -1163,7 +1263,7 @@ @@ -1163,7 +1263,7 @@
1163 defaultConfigurationIsVisible = 0; 1263 defaultConfigurationIsVisible = 0;
1164 defaultConfigurationName = Release; 1264 defaultConfigurationName = Release;
1165 }; 1265 };
1166 - 19FCBF192AC1727800F83A7F /* Build configuration list for PBXProject "browser" */ = { 1266 + 19FCBF192AC1727800F83A7F /* Build configuration list for PBXProject "Pro-Seecurity-VPN" */ = {
1167 isa = XCConfigurationList; 1267 isa = XCConfigurationList;
1168 buildConfigurations = ( 1268 buildConfigurations = (
1169 19FCBF302AC1727900F83A7F /* Debug */, 1269 19FCBF302AC1727900F83A7F /* Debug */,
@@ -1172,7 +1272,7 @@ @@ -1172,7 +1272,7 @@
1172 defaultConfigurationIsVisible = 0; 1272 defaultConfigurationIsVisible = 0;
1173 defaultConfigurationName = Release; 1273 defaultConfigurationName = Release;
1174 }; 1274 };
1175 - 19FCBF322AC1727900F83A7F /* Build configuration list for PBXNativeTarget "browser" */ = { 1275 + 19FCBF322AC1727900F83A7F /* Build configuration list for PBXNativeTarget "Pro-Seecurity-VPN" */ = {
1176 isa = XCConfigurationList; 1276 isa = XCConfigurationList;
1177 buildConfigurations = ( 1277 buildConfigurations = (
1178 19FCBF332AC1727900F83A7F /* Debug */, 1278 19FCBF332AC1727900F83A7F /* Debug */,
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<Scheme
  3 + LastUpgradeVersion = "1500"
  4 + wasCreatedForAppExtension = "YES"
  5 + version = "2.0">
  6 + <BuildAction
  7 + parallelizeBuildables = "YES"
  8 + buildImplicitDependencies = "YES">
  9 + <BuildActionEntries>
  10 + <BuildActionEntry
  11 + buildForTesting = "YES"
  12 + buildForRunning = "YES"
  13 + buildForProfiling = "YES"
  14 + buildForArchiving = "YES"
  15 + buildForAnalyzing = "YES">
  16 + <BuildableReference
  17 + BuildableIdentifier = "primary"
  18 + BlueprintIdentifier = "19696AF12AE80DBC00D1F8F9"
  19 + BuildableName = "AdBlocker.appex"
  20 + BlueprintName = "AdBlocker"
  21 + ReferencedContainer = "container:Pro-Seecurity-VPN.xcodeproj">
  22 + </BuildableReference>
  23 + </BuildActionEntry>
  24 + <BuildActionEntry
  25 + buildForTesting = "YES"
  26 + buildForRunning = "YES"
  27 + buildForProfiling = "YES"
  28 + buildForArchiving = "YES"
  29 + buildForAnalyzing = "YES">
  30 + <BuildableReference
  31 + BuildableIdentifier = "primary"
  32 + BlueprintIdentifier = "19FCBF1D2AC1727800F83A7F"
  33 + BuildableName = "Pro-Seecurity-VPN.app"
  34 + BlueprintName = "Pro-Seecurity-VPN"
  35 + ReferencedContainer = "container:Pro-Seecurity-VPN.xcodeproj">
  36 + </BuildableReference>
  37 + </BuildActionEntry>
  38 + </BuildActionEntries>
  39 + </BuildAction>
  40 + <TestAction
  41 + buildConfiguration = "Debug"
  42 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
  43 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
  44 + shouldUseLaunchSchemeArgsEnv = "YES"
  45 + shouldAutocreateTestPlan = "YES">
  46 + </TestAction>
  47 + <LaunchAction
  48 + buildConfiguration = "Debug"
  49 + selectedDebuggerIdentifier = ""
  50 + selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
  51 + launchStyle = "0"
  52 + askForAppToLaunch = "Yes"
  53 + useCustomWorkingDirectory = "NO"
  54 + ignoresPersistentStateOnLaunch = "NO"
  55 + debugDocumentVersioning = "YES"
  56 + debugServiceExtension = "internal"
  57 + allowLocationSimulation = "YES"
  58 + launchAutomaticallySubstyle = "2">
  59 + <BuildableProductRunnable
  60 + runnableDebuggingMode = "0">
  61 + <BuildableReference
  62 + BuildableIdentifier = "primary"
  63 + BlueprintIdentifier = "19FCBF1D2AC1727800F83A7F"
  64 + BuildableName = "Pro-Seecurity-VPN.app"
  65 + BlueprintName = "Pro-Seecurity-VPN"
  66 + ReferencedContainer = "container:Pro-Seecurity-VPN.xcodeproj">
  67 + </BuildableReference>
  68 + </BuildableProductRunnable>
  69 + </LaunchAction>
  70 + <ProfileAction
  71 + buildConfiguration = "Release"
  72 + shouldUseLaunchSchemeArgsEnv = "YES"
  73 + savedToolIdentifier = ""
  74 + useCustomWorkingDirectory = "NO"
  75 + debugDocumentVersioning = "YES"
  76 + askForAppToLaunch = "Yes"
  77 + launchAutomaticallySubstyle = "2">
  78 + <BuildableProductRunnable
  79 + runnableDebuggingMode = "0">
  80 + <BuildableReference
  81 + BuildableIdentifier = "primary"
  82 + BlueprintIdentifier = "19FCBF1D2AC1727800F83A7F"
  83 + BuildableName = "Pro-Seecurity-VPN.app"
  84 + BlueprintName = "Pro-Seecurity-VPN"
  85 + ReferencedContainer = "container:Pro-Seecurity-VPN.xcodeproj">
  86 + </BuildableReference>
  87 + </BuildableProductRunnable>
  88 + </ProfileAction>
  89 + <AnalyzeAction
  90 + buildConfiguration = "Debug">
  91 + </AnalyzeAction>
  92 + <ArchiveAction
  93 + buildConfiguration = "Release"
  94 + revealArchiveInOrganizer = "YES">
  95 + </ArchiveAction>
  96 +</Scheme>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<Scheme
  3 + LastUpgradeVersion = "1500"
  4 + version = "1.7">
  5 + <BuildAction
  6 + parallelizeBuildables = "YES"
  7 + buildImplicitDependencies = "YES">
  8 + <BuildActionEntries>
  9 + <BuildActionEntry
  10 + buildForTesting = "YES"
  11 + buildForRunning = "YES"
  12 + buildForProfiling = "YES"
  13 + buildForArchiving = "YES"
  14 + buildForAnalyzing = "YES">
  15 + <BuildableReference
  16 + BuildableIdentifier = "primary"
  17 + BlueprintIdentifier = "19FCBF1D2AC1727800F83A7F"
  18 + BuildableName = "Pro-Seecurity-VPN.app"
  19 + BlueprintName = "Pro-Seecurity-VPN"
  20 + ReferencedContainer = "container:Pro-Seecurity-VPN.xcodeproj">
  21 + </BuildableReference>
  22 + </BuildActionEntry>
  23 + </BuildActionEntries>
  24 + </BuildAction>
  25 + <TestAction
  26 + buildConfiguration = "Debug"
  27 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
  28 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
  29 + shouldUseLaunchSchemeArgsEnv = "YES"
  30 + shouldAutocreateTestPlan = "YES">
  31 + </TestAction>
  32 + <LaunchAction
  33 + buildConfiguration = "Debug"
  34 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
  35 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
  36 + launchStyle = "0"
  37 + useCustomWorkingDirectory = "NO"
  38 + ignoresPersistentStateOnLaunch = "NO"
  39 + debugDocumentVersioning = "YES"
  40 + debugServiceExtension = "internal"
  41 + allowLocationSimulation = "YES">
  42 + <BuildableProductRunnable
  43 + runnableDebuggingMode = "0">
  44 + <BuildableReference
  45 + BuildableIdentifier = "primary"
  46 + BlueprintIdentifier = "19FCBF1D2AC1727800F83A7F"
  47 + BuildableName = "Pro-Seecurity-VPN.app"
  48 + BlueprintName = "Pro-Seecurity-VPN"
  49 + ReferencedContainer = "container:Pro-Seecurity-VPN.xcodeproj">
  50 + </BuildableReference>
  51 + </BuildableProductRunnable>
  52 + <StoreKitConfigurationFileReference
  53 + identifier = "../../browser/AdBlockSubscription.storekit">
  54 + </StoreKitConfigurationFileReference>
  55 + </LaunchAction>
  56 + <ProfileAction
  57 + buildConfiguration = "Release"
  58 + shouldUseLaunchSchemeArgsEnv = "YES"
  59 + savedToolIdentifier = ""
  60 + useCustomWorkingDirectory = "NO"
  61 + debugDocumentVersioning = "YES">
  62 + <BuildableProductRunnable
  63 + runnableDebuggingMode = "0">
  64 + <BuildableReference
  65 + BuildableIdentifier = "primary"
  66 + BlueprintIdentifier = "19FCBF1D2AC1727800F83A7F"
  67 + BuildableName = "Pro-Seecurity-VPN.app"
  68 + BlueprintName = "Pro-Seecurity-VPN"
  69 + ReferencedContainer = "container:Pro-Seecurity-VPN.xcodeproj">
  70 + </BuildableReference>
  71 + </BuildableProductRunnable>
  72 + </ProfileAction>
  73 + <AnalyzeAction
  74 + buildConfiguration = "Debug">
  75 + </AnalyzeAction>
  76 + <ArchiveAction
  77 + buildConfiguration = "Release"
  78 + revealArchiveInOrganizer = "YES">
  79 + </ArchiveAction>
  80 +</Scheme>
@@ -7,42 +7,42 @@ @@ -7,42 +7,42 @@
7 <key>AdBlocker.xcscheme_^#shared#^_</key> 7 <key>AdBlocker.xcscheme_^#shared#^_</key>
8 <dict> 8 <dict>
9 <key>orderHint</key> 9 <key>orderHint</key>
10 - <integer>0</integer> 10 + <integer>1</integer>
11 </dict> 11 </dict>
12 <key>GettingStarted (Playground) 1.xcscheme</key> 12 <key>GettingStarted (Playground) 1.xcscheme</key>
13 <dict> 13 <dict>
14 <key>isShown</key> 14 <key>isShown</key>
15 <false/> 15 <false/>
16 <key>orderHint</key> 16 <key>orderHint</key>
17 - <integer>5</integer> 17 + <integer>6</integer>
18 </dict> 18 </dict>
19 <key>GettingStarted (Playground) 2.xcscheme</key> 19 <key>GettingStarted (Playground) 2.xcscheme</key>
20 <dict> 20 <dict>
21 <key>isShown</key> 21 <key>isShown</key>
22 <false/> 22 <false/>
23 <key>orderHint</key> 23 <key>orderHint</key>
24 - <integer>6</integer> 24 + <integer>7</integer>
25 </dict> 25 </dict>
26 <key>GettingStarted (Playground).xcscheme</key> 26 <key>GettingStarted (Playground).xcscheme</key>
27 <dict> 27 <dict>
28 <key>isShown</key> 28 <key>isShown</key>
29 <false/> 29 <false/>
30 <key>orderHint</key> 30 <key>orderHint</key>
31 - <integer>2</integer> 31 + <integer>3</integer>
32 </dict> 32 </dict>
33 <key>SnapKitPlayground (Playground) 1.xcscheme</key> 33 <key>SnapKitPlayground (Playground) 1.xcscheme</key>
34 <dict> 34 <dict>
35 <key>isShown</key> 35 <key>isShown</key>
36 <false/> 36 <false/>
37 <key>orderHint</key> 37 <key>orderHint</key>
38 - <integer>3</integer> 38 + <integer>4</integer>
39 </dict> 39 </dict>
40 <key>SnapKitPlayground (Playground) 2.xcscheme</key> 40 <key>SnapKitPlayground (Playground) 2.xcscheme</key>
41 <dict> 41 <dict>
42 <key>isShown</key> 42 <key>isShown</key>
43 <false/> 43 <false/>
44 <key>orderHint</key> 44 <key>orderHint</key>
45 - <integer>4</integer> 45 + <integer>5</integer>
46 </dict> 46 </dict>
47 <key>SnapKitPlayground (Playground) 3.xcscheme</key> 47 <key>SnapKitPlayground (Playground) 3.xcscheme</key>
48 <dict> 48 <dict>
@@ -70,12 +70,25 @@ @@ -70,12 +70,25 @@
70 <key>isShown</key> 70 <key>isShown</key>
71 <false/> 71 <false/>
72 <key>orderHint</key> 72 <key>orderHint</key>
73 - <integer>1</integer> 73 + <integer>2</integer>
74 </dict> 74 </dict>
75 <key>browser.xcscheme_^#shared#^_</key> 75 <key>browser.xcscheme_^#shared#^_</key>
76 <dict> 76 <dict>
77 <key>orderHint</key> 77 <key>orderHint</key>
78 - <integer>1</integer> 78 + <integer>0</integer>
  79 + </dict>
  80 + </dict>
  81 + <key>SuppressBuildableAutocreation</key>
  82 + <dict>
  83 + <key>19696AF12AE80DBC00D1F8F9</key>
  84 + <dict>
  85 + <key>primary</key>
  86 + <true/>
  87 + </dict>
  88 + <key>19FCBF1D2AC1727800F83A7F</key>
  89 + <dict>
  90 + <key>primary</key>
  91 + <true/>
79 </dict> 92 </dict>
80 </dict> 93 </dict>
81 </dict> 94 </dict>
  1 +{
  2 + "identifier" : "795B98EF",
  3 + "nonRenewingSubscriptions" : [
  4 +
  5 + ],
  6 + "products" : [
  7 +
  8 + ],
  9 + "settings" : {
  10 + "_applicationInternalID" : "6449258523",
  11 + "_developerTeamID" : "6Y97YM76EY",
  12 + "_failTransactionsEnabled" : false,
  13 + "_lastSynchronizedDate" : 722874993.00790405,
  14 + "_locale" : "en_US",
  15 + "_storefront" : "USA",
  16 + "_storeKitErrors" : [
  17 + {
  18 + "current" : null,
  19 + "enabled" : false,
  20 + "name" : "Load Products"
  21 + },
  22 + {
  23 + "current" : null,
  24 + "enabled" : false,
  25 + "name" : "Purchase"
  26 + },
  27 + {
  28 + "current" : null,
  29 + "enabled" : false,
  30 + "name" : "Verification"
  31 + },
  32 + {
  33 + "current" : null,
  34 + "enabled" : false,
  35 + "name" : "App Store Sync"
  36 + },
  37 + {
  38 + "current" : null,
  39 + "enabled" : false,
  40 + "name" : "Subscription Status"
  41 + },
  42 + {
  43 + "current" : null,
  44 + "enabled" : false,
  45 + "name" : "App Transaction"
  46 + },
  47 + {
  48 + "current" : null,
  49 + "enabled" : false,
  50 + "name" : "Manage Subscriptions Sheet"
  51 + },
  52 + {
  53 + "current" : null,
  54 + "enabled" : false,
  55 + "name" : "Refund Request Sheet"
  56 + },
  57 + {
  58 + "current" : null,
  59 + "enabled" : false,
  60 + "name" : "Offer Code Redeem Sheet"
  61 + }
  62 + ]
  63 + },
  64 + "subscriptionGroups" : [
  65 + {
  66 + "id" : "21417095",
  67 + "localizations" : [
  68 +
  69 + ],
  70 + "name" : "adBlocker",
  71 + "subscriptions" : [
  72 + {
  73 + "adHocOffers" : [
  74 +
  75 + ],
  76 + "codeOffers" : [
  77 +
  78 + ],
  79 + "displayPrice" : "8.99",
  80 + "familyShareable" : false,
  81 + "groupNumber" : 1,
  82 + "internalID" : "6473264580",
  83 + "introductoryOffer" : null,
  84 + "localizations" : [
  85 + {
  86 + "description" : "One week",
  87 + "displayName" : "One week",
  88 + "locale" : "ru"
  89 + }
  90 + ],
  91 + "productID" : "com.browser.adblocker",
  92 + "recurringSubscriptionPeriod" : "P1W",
  93 + "referenceName" : "adBlocker",
  94 + "subscriptionGroupID" : "21417095",
  95 + "type" : "RecurringSubscription"
  96 + }
  97 + ]
  98 + }
  99 + ],
  100 + "version" : {
  101 + "major" : 3,
  102 + "minor" : 0
  103 + }
  104 +}
@@ -5,7 +5,6 @@ import UIKit @@ -5,7 +5,6 @@ import UIKit
5 var window: UIWindow? 5 var window: UIWindow?
6 6
7 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 7 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
8 -  
9 let screenRect = UIScreen.main.bounds 8 let screenRect = UIScreen.main.bounds
10 window = UIWindow(frame: screenRect) 9 window = UIWindow(frame: screenRect)
11 10
  1 +//
  2 +// OpenBrowserHomeTransition.swift
  3 +// browser
  4 +//
  5 +// Created by Artem Talko on 23.11.2023.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +final class OpenBrowserHomeTransition: NSObject, UIViewControllerAnimatedTransitioning {
  11 + private var operation: UINavigationController.Operation
  12 +
  13 + init( operation: UINavigationController.Operation ) {
  14 + self.operation = operation
  15 +
  16 + super.init()
  17 + }
  18 +
  19 + func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
  20 + return 0.5
  21 + }
  22 +
  23 + func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
  24 + guard let toController = transitionContext.viewController(forKey: .to),
  25 + let fromController = transitionContext.viewController(forKey: .from) else {
  26 + transitionContext.completeTransition(true)
  27 + return
  28 + }
  29 + switch operation {
  30 + case .push :
  31 + pushController(fromController: fromController, toController: toController, transitionContext: transitionContext)
  32 + case .pop:
  33 + print("error: VC was popped")
  34 + break
  35 + case .none:
  36 + transitionContext.completeTransition(true)
  37 + return
  38 + @unknown default:
  39 + break
  40 + }
  41 + }
  42 +}
  43 +
  44 +extension OpenBrowserHomeTransition {
  45 + private func pushController(fromController: UIViewController, toController: UIViewController, transitionContext: UIViewControllerContextTransitioning) {
  46 + let container = transitionContext.containerView
  47 +
  48 + if let browserHomeViewController = toController as? BrowserHomeViewController {
  49 + toController.view.frame = CGRect(x: 0, y: container.bounds.height, width: container.bounds.width, height: container.bounds.height)
  50 +
  51 + container.addSubview(toController.view)
  52 +
  53 + UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
  54 + toController.view.frame = container.bounds
  55 + fromController.view.alpha = 0.5
  56 + }, completion: { _ in
  57 + transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
  58 + fromController.view.alpha = 1.0
  59 + })
  60 + } else {
  61 + toController.view.frame = CGRect(x: 0, y: -toController.view.frame.height, width: toController.view.frame.width, height: toController.view.frame.height)
  62 +
  63 + container.addSubview(toController.view)
  64 +
  65 + UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
  66 + toController.view.frame = CGRect(x: 0, y: 0, width: toController.view.frame.width, height: toController.view.frame.height)
  67 + }, completion: { _ in
  68 + transitionContext.completeTransition(true)
  69 + })
  70 + }
  71 +
  72 + }
  73 +}
  74 +
@@ -10,13 +10,14 @@ import UIKit @@ -10,13 +10,14 @@ import UIKit
10 final class OpenTabsTransition: NSObject, UIViewControllerAnimatedTransitioning { 10 final class OpenTabsTransition: NSObject, UIViewControllerAnimatedTransitioning {
11 private var operation: UINavigationController.Operation 11 private var operation: UINavigationController.Operation
12 12
13 - init( operation: UINavigationController.Operation ) { 13 + init(operation: UINavigationController.Operation) {
14 self.operation = operation 14 self.operation = operation
  15 +
15 super.init() 16 super.init()
16 } 17 }
17 18
18 func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 19 func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
19 - return 0.4 20 + return 0.6
20 } 21 }
21 22
22 func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 23 func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
@@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
2 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 2 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 <plist version="1.0"> 3 <plist version="1.0">
4 <dict> 4 <dict>
  5 + <key>ITSAppUsesNonExemptEncryption</key>
  6 + <false/>
5 <key>NSAppTransportSecurity</key> 7 <key>NSAppTransportSecurity</key>
6 <dict> 8 <dict>
7 <key>NSAllowsArbitraryLoads</key> 9 <key>NSAllowsArbitraryLoads</key>
@@ -28,7 +28,7 @@ final class HistoryDBManager { @@ -28,7 +28,7 @@ final class HistoryDBManager {
28 try realm.write { 28 try realm.write {
29 realm.add(historyCell) 29 realm.add(historyCell)
30 } 30 }
31 - 31 +
32 } catch { 32 } catch {
33 print("Error adding new tab: \(error.localizedDescription)") 33 print("Error adding new tab: \(error.localizedDescription)")
34 } 34 }
  1 +//
  2 +// SubscriptionService.swift
  3 +// browser
  4 +//
  5 +// Created by Artem Talko on 23.11.2023.
  6 +//
  7 +
  8 +import Foundation
  9 +import StoreKit
  10 +
  11 +fileprivate enum StoreError: Error {
  12 + case failedVerification
  13 +}
  14 +
  15 +final class StoreKitManager: ObservableObject {
  16 + @Published
  17 + var storeProducts: [Product] = []
  18 + @Published
  19 + var purchasedSubscriptions : [Product] = []
  20 +
  21 + private var updateListenerTask: Task<Void, Error>? = nil
  22 +
  23 + private let productDict: [String : String]
  24 +
  25 + 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 + }
  32 + updateListenerTask = listenForTransactions()
  33 +
  34 + Task {
  35 + await requestProducts()
  36 + await updateCustomerProductStatus()
  37 + }
  38 +
  39 + print("controller called")
  40 + }
  41 +
  42 + deinit {
  43 + updateListenerTask?.cancel()
  44 + }
  45 +
  46 + func listenForTransactions() -> Task<Void, Error> {
  47 + return Task.detached {
  48 + for await result in Transaction.updates {
  49 + do {
  50 + let transaction = try self.checkVerified(result)
  51 + await self.updateCustomerProductStatus()
  52 + await transaction.finish()
  53 + } catch {
  54 + print("Transaction failed verification")
  55 + }
  56 + }
  57 + }
  58 + }
  59 +
  60 + @MainActor
  61 + func requestProducts() async {
  62 + do {
  63 + storeProducts = try await Product.products(for: productDict.values)
  64 +
  65 + } catch {
  66 + print("Failed - error retrieving products \(error)")
  67 + }
  68 + }
  69 +
  70 + func checkVerified<T>(_ result: VerificationResult<T>) throws -> T {
  71 + switch result {
  72 + case .unverified:
  73 + throw StoreError.failedVerification
  74 + case .verified(let signedType):
  75 + return signedType
  76 + }
  77 + }
  78 +
  79 + @MainActor
  80 + func updateCustomerProductStatus() async {
  81 + var purchasedCourses: [Product] = []
  82 +
  83 + for await result in Transaction.currentEntitlements {
  84 + do {
  85 + let transaction = try checkVerified(result)
  86 + if let course = storeProducts.first(where: { $0.id == transaction.productID}) {
  87 + purchasedCourses.append(course)
  88 + }
  89 + } catch {
  90 + print("Transaction failed verification")
  91 + }
  92 + self.purchasedSubscriptions = purchasedCourses
  93 + }
  94 + }
  95 +
  96 + func purchase(_ product: Product) async throws -> Transaction? {
  97 + let result = try await product.purchase()
  98 +
  99 + switch result {
  100 + case .success(let verificationResult):
  101 + let transaction = try checkVerified(verificationResult)
  102 + await updateCustomerProductStatus()
  103 + await transaction.finish()
  104 +
  105 + return transaction
  106 + case .userCancelled, .pending:
  107 + return nil
  108 + default:
  109 + return nil
  110 + }
  111 + }
  112 +
  113 + func isPurchased(_ product: Product) async throws -> Bool {
  114 + return purchasedSubscriptions.contains(product)
  115 + }
  116 +}
@@ -20,28 +20,31 @@ final class HistoryTableViewCell: UITableViewCell { @@ -20,28 +20,31 @@ final class HistoryTableViewCell: UITableViewCell {
20 private let searchImageLogo: UIImageView = { 20 private let searchImageLogo: UIImageView = {
21 let obj = UIImageView() 21 let obj = UIImageView()
22 obj.image = UIImage(systemName: "magnifyingglass") 22 obj.image = UIImage(systemName: "magnifyingglass")
23 - obj.tintColor = .gray 23 + obj.tintColor = .white
24 obj.contentMode = .scaleAspectFit 24 obj.contentMode = .scaleAspectFit
  25 +
25 return obj 26 return obj
26 }() 27 }()
27 28
28 private let lastVisitSiteLabel: UILabel = { 29 private let lastVisitSiteLabel: UILabel = {
29 let obj = UILabel() 30 let obj = UILabel()
30 obj.font = FontConstants.regularFont_14 31 obj.font = FontConstants.regularFont_14
  32 +
31 return obj 33 return obj
32 }() 34 }()
33 35
34 private let lastVisitSiteUrlLabel: UILabel = { 36 private let lastVisitSiteUrlLabel: UILabel = {
35 let obj = UILabel() 37 let obj = UILabel()
36 - obj.textColor = .gray 38 + obj.textColor = .white
37 obj.font = FontConstants.regularFont_12 39 obj.font = FontConstants.regularFont_12
  40 +
38 return obj 41 return obj
39 }() 42 }()
40 43
41 private let lastVisitDateLabel: UILabel = { 44 private let lastVisitDateLabel: UILabel = {
42 let obj = UILabel() 45 let obj = UILabel()
43 obj.font = FontConstants.regularFont_12 46 obj.font = FontConstants.regularFont_12
44 - obj.textColor = .gray 47 + obj.textColor = .white
45 return obj 48 return obj
46 }() 49 }()
47 50
@@ -56,6 +59,7 @@ final class HistoryTableViewCell: UITableViewCell { @@ -56,6 +59,7 @@ final class HistoryTableViewCell: UITableViewCell {
56 } 59 }
57 60
58 private func setup() { 61 private func setup() {
  62 + self.backgroundColor = .clear
59 contentView.addSubview(searchImageLogo) 63 contentView.addSubview(searchImageLogo)
60 contentView.addSubview(lastVisitSiteLabel) 64 contentView.addSubview(lastVisitSiteLabel)
61 contentView.addSubview(lastVisitSiteUrlLabel) 65 contentView.addSubview(lastVisitSiteUrlLabel)
@@ -20,7 +20,7 @@ final class HistorySearchBarView: UIView { @@ -20,7 +20,7 @@ final class HistorySearchBarView: UIView {
20 let searchTextFieldView: UITextField = { 20 let searchTextFieldView: UITextField = {
21 let obj = UITextField() 21 let obj = UITextField()
22 obj.text = StringConstants.search 22 obj.text = StringConstants.search
23 - obj.textColor = ColorConstants.gray 23 + obj.textColor = ColorConstants.SearchbarTintBlue
24 24
25 return obj 25 return obj
26 }() 26 }()
@@ -7,11 +7,11 @@ @@ -7,11 +7,11 @@
7 7
8 import UIKit 8 import UIKit
9 9
10 -final class HistoryView: UIView { 10 +final class HistoryView: GradientView {
11 let historySearchBar: HistorySearchBarView = { 11 let historySearchBar: HistorySearchBarView = {
12 let obj = HistorySearchBarView() 12 let obj = HistorySearchBarView()
13 obj.layer.cornerRadius = 10 13 obj.layer.cornerRadius = 10
14 - obj.backgroundColor = UIColor(red: 0.913, green: 0.913, blue: 0.947, alpha: 1) 14 + obj.backgroundColor = ColorConstants.customLightBlue
15 15
16 return obj 16 return obj
17 }() 17 }()
@@ -19,13 +19,14 @@ final class HistoryView: UIView { @@ -19,13 +19,14 @@ final class HistoryView: UIView {
19 let historyTabsTableView: UITableView = { 19 let historyTabsTableView: UITableView = {
20 let obj = UITableView() 20 let obj = UITableView()
21 obj.separatorStyle = .none 21 obj.separatorStyle = .none
  22 + obj.backgroundColor = .clear
22 23
23 return obj 24 return obj
24 }() 25 }()
25 26
26 let historyToolbarView: HistoryToolbarView = { 27 let historyToolbarView: HistoryToolbarView = {
27 let obj = HistoryToolbarView() 28 let obj = HistoryToolbarView()
28 - 29 + obj.backgroundColor = ColorConstants.customLightBlue
29 return obj 30 return obj
30 }() 31 }()
31 32
@@ -16,7 +16,7 @@ final class BrowserHomeViewController: UIViewController { @@ -16,7 +16,7 @@ final class BrowserHomeViewController: UIViewController {
16 16
17 private let searchingViewController: SearchingViewController 17 private let searchingViewController: SearchingViewController
18 private let searchResultViewController: SearchResultViewController 18 private let searchResultViewController: SearchResultViewController
19 - private let tabsViewController: TabsViewController 19 + private var tabsViewController: TabsViewController?
20 20
21 private var subscriptions: Set<AnyCancellable> 21 private var subscriptions: Set<AnyCancellable>
22 private var searchRequestURL: String 22 private var searchRequestURL: String
@@ -33,7 +33,6 @@ final class BrowserHomeViewController: UIViewController { @@ -33,7 +33,6 @@ final class BrowserHomeViewController: UIViewController {
33 override func viewDidLoad() { 33 override func viewDidLoad() {
34 super.viewDidLoad() 34 super.viewDidLoad()
35 view.backgroundColor = ColorConstants.lightGray 35 view.backgroundColor = ColorConstants.lightGray
36 -  
37 initViewController() 36 initViewController()
38 } 37 }
39 38
@@ -51,6 +50,8 @@ final class BrowserHomeViewController: UIViewController { @@ -51,6 +50,8 @@ final class BrowserHomeViewController: UIViewController {
51 50
52 override func viewIsAppearing(_ animated: Bool) { 51 override func viewIsAppearing(_ animated: Bool) {
53 navigationController?.isNavigationBarHidden = true 52 navigationController?.isNavigationBarHidden = true
  53 +
  54 + tabsViewController = getTabsViewController()
54 } 55 }
55 56
56 override func loadView() { 57 override func loadView() {
@@ -60,7 +61,9 @@ final class BrowserHomeViewController: UIViewController { @@ -60,7 +61,9 @@ final class BrowserHomeViewController: UIViewController {
60 init(url: String?, currentTabId: Int?) { 61 init(url: String?, currentTabId: Int?) {
61 searchResultViewController = SearchResultViewController(searchLink: String()) 62 searchResultViewController = SearchResultViewController(searchLink: String())
62 searchingViewController = SearchingViewController(dataForReq: []) 63 searchingViewController = SearchingViewController(dataForReq: [])
63 - tabsViewController = TabsViewController() 64 +
  65 +
  66 +
64 67
65 subscriptions = [] 68 subscriptions = []
66 searchRequestURL = URLConstants.googleURL 69 searchRequestURL = URLConstants.googleURL
@@ -169,9 +172,9 @@ extension BrowserHomeViewController { @@ -169,9 +172,9 @@ extension BrowserHomeViewController {
169 } 172 }
170 173
171 @objc 174 @objc
172 - private func removeAdButtonTapped(_ sender: UIButton) {  
173 - let removeAdViewController = RemoveAdvertViewController()  
174 - openAdditionViewController(removeAdViewController) 175 + private func advertSegmantControlStateHandler() {
  176 + let removeAdvertViewController = RemoveAdvertViewController()
  177 + navigationController?.setViewControllers([removeAdvertViewController], animated: true)
175 } 178 }
176 179
177 @objc 180 @objc
@@ -180,9 +183,18 @@ extension BrowserHomeViewController { @@ -180,9 +183,18 @@ extension BrowserHomeViewController {
180 } 183 }
181 } 184 }
182 185
183 -  
184 //MARK: - Helpers 186 //MARK: - Helpers
185 extension BrowserHomeViewController { 187 extension BrowserHomeViewController {
  188 + private func getTabsViewController() -> TabsViewController? {
  189 + guard let controllers = navigationController?.viewControllers else {
  190 + return nil
  191 + }
  192 +
  193 + return (controllers.first(where: { $0 is TabsViewController }) as? TabsViewController)
  194 + }
  195 +
  196 +
  197 +
186 private func didTabButtonTapped(type: ToolbarElementType) { 198 private func didTabButtonTapped(type: ToolbarElementType) {
187 switch type { 199 switch type {
188 case .history: 200 case .history:
@@ -222,7 +234,7 @@ extension BrowserHomeViewController { @@ -222,7 +234,7 @@ extension BrowserHomeViewController {
222 234
223 private func addTargets() { 235 private func addTargets() {
224 mainView.settingButton.addTarget(self, action: #selector(settingButtonTapped(_ :)), for: .touchUpInside) 236 mainView.settingButton.addTarget(self, action: #selector(settingButtonTapped(_ :)), for: .touchUpInside)
225 - mainView.removeAddButton.addTarget(self, action: #selector(removeAdButtonTapped(_ :)), for: .touchUpInside) 237 + mainView.removeAdvertSegmentControl.addTarget(self, action: #selector(advertSegmantControlStateHandler), for: .valueChanged)
226 mainView.searchBarContainer.searchBarView.searchTextFieldView.addTarget(self, action: #selector(searchBarTextChanged), for: .editingChanged) 238 mainView.searchBarContainer.searchBarView.searchTextFieldView.addTarget(self, action: #selector(searchBarTextChanged), for: .editingChanged)
227 searchingViewController.mainView.searchingButton.addTarget(self, action: #selector(removeSearchingViewController(_ :)), for: .touchUpInside) 239 searchingViewController.mainView.searchingButton.addTarget(self, action: #selector(removeSearchingViewController(_ :)), for: .touchUpInside)
228 addToolbarTargets() 240 addToolbarTargets()
@@ -261,7 +273,6 @@ extension BrowserHomeViewController { @@ -261,7 +273,6 @@ extension BrowserHomeViewController {
261 private func tabsButtonHandler() { 273 private func tabsButtonHandler() {
262 if currentTabId == nil { 274 if currentTabId == nil {
263 addNewTab() 275 addNewTab()
264 - navigationController?.popViewController(animated: true)  
265 } else { 276 } else {
266 updateCurrentTab() 277 updateCurrentTab()
267 } 278 }
@@ -277,16 +288,20 @@ extension BrowserHomeViewController { @@ -277,16 +288,20 @@ extension BrowserHomeViewController {
277 } 288 }
278 let finalUrl = siteUrl.absoluteString 289 let finalUrl = siteUrl.absoluteString
279 let lastVisit = DateManager.shared.currentDate 290 let lastVisit = DateManager.shared.currentDate
280 - let wkWVForSnapshot = childViewController.mainView.searchResultView 291 + let homeViewSnapshot = SnapshotService.shared.makeSnapshot(mainView)
281 292
282 - SnapshotService.shared.makeWKWebViewSnapshot(wkWVForSnapshot) { snapshotForDB in  
283 - TabManager.shared.saveTab(tabTitle: siteTitle, snapshotImage: snapshotForDB, tabUrl: finalUrl)  
284 - } 293 + TabManager.shared.saveTab(tabTitle: siteTitle, snapshotImage: homeViewSnapshot, tabUrl: finalUrl)
  294 + self.currentTabId = tabsViewController?.getCellIndex().row
  295 +
  296 + tabsViewController?.refreshData()
285 HistoryDBManager.shared.saveToHistory(siteTitle: siteTitle, siteUrl: finalUrl, lastVisit: lastVisit) 297 HistoryDBManager.shared.saveToHistory(siteTitle: siteTitle, siteUrl: finalUrl, lastVisit: lastVisit)
  298 + navigationController?.popViewController(animated: true)
286 } else { 299 } else {
287 let homeViewSnapshot = SnapshotService.shared.makeSnapshot(mainView) 300 let homeViewSnapshot = SnapshotService.shared.makeSnapshot(mainView)
288 TabManager.shared.saveTab(tabTitle: "Start Page", snapshotImage: homeViewSnapshot, tabUrl: "homeUrl") 301 TabManager.shared.saveTab(tabTitle: "Start Page", snapshotImage: homeViewSnapshot, tabUrl: "homeUrl")
289 - currentTabId = tabsViewController.getCellIndex().row 302 + tabsViewController?.refreshData()
  303 + currentTabId = tabsViewController?.getCellIndex().row
  304 + navigationController?.popViewController(animated: true)
290 } 305 }
291 } 306 }
292 307
@@ -295,6 +310,7 @@ extension BrowserHomeViewController { @@ -295,6 +310,7 @@ extension BrowserHomeViewController {
295 let chosenTab = allTabs[self.currentTabId ?? Int()] 310 let chosenTab = allTabs[self.currentTabId ?? Int()]
296 let gottedCellId = chosenTab.tabId 311 let gottedCellId = chosenTab.tabId
297 let imageForUpdatedTab = SnapshotService.shared.makeSnapshot(self.mainView) 312 let imageForUpdatedTab = SnapshotService.shared.makeSnapshot(self.mainView)
  313 +
298 if let childViewController = self.children.first as? SearchResultViewController { 314 if let childViewController = self.children.first as? SearchResultViewController {
299 guard let siteTitle = childViewController.mainView.searchResultView.title else { 315 guard let siteTitle = childViewController.mainView.searchResultView.title else {
300 return 316 return
@@ -8,23 +8,19 @@ @@ -8,23 +8,19 @@
8 import UIKit 8 import UIKit
9 import SnapKit 9 import SnapKit
10 10
11 -final class BrowserHomeView: UIView {  
12 - let removeAddButton: UIButton = {  
13 - let obj = UIButton()  
14 - obj.backgroundColor = ColorConstants.buttonsBackgroundColor  
15 - obj.setTitle("Remove advert", for: .normal)  
16 - obj.titleLabel?.font = FontConstants.semiboldFont_15  
17 - obj.translatesAutoresizingMaskIntoConstraints = false  
18 - obj.setTitleColor(.white, for: .normal)  
19 - obj.setImage(UIImage(systemName: "shield.lefthalf.filled")?.withTintColor(.white, renderingMode: .alwaysOriginal), for: .normal) 11 +final class BrowserHomeView: GradientView {
  12 + let removeAdvertSegmentControl: UISegmentedControl = {
  13 + let items = ["AdBlock", "Browser"]
  14 + let obj = UISegmentedControl(items: items)
  15 + obj.selectedSegmentIndex = 1
  16 + obj.backgroundColor = ColorConstants.segmentControlBackground
20 obj.layer.cornerRadius = 10 17 obj.layer.cornerRadius = 10
21 - obj.contentEdgeInsets = UIEdgeInsets(top: 10.sizeW, left: 10.sizeW, bottom: 10.sizeW, right: 10.sizeW)  
22 - obj.clipsToBounds = true  
23 - obj.layer.masksToBounds = false 18 + obj.selectedSegmentTintColor = UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 1)
  19 + obj.setTitleTextAttributes([.foregroundColor: UIColor.black], for: .normal)
  20 + obj.setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
24 21
25 return obj 22 return obj
26 }() 23 }()
27 -  
28 let settingButton: UIButton = { 24 let settingButton: UIButton = {
29 let obj = UIButton() 25 let obj = UIButton()
30 obj.setImage(UIImage(named: "Settings")?.withTintColor(.systemBlue), for: .normal) 26 obj.setImage(UIImage(named: "Settings")?.withTintColor(.systemBlue), for: .normal)
@@ -55,6 +51,7 @@ final class BrowserHomeView: UIView { @@ -55,6 +51,7 @@ final class BrowserHomeView: UIView {
55 51
56 let toolbarView: ToolbarView = { 52 let toolbarView: ToolbarView = {
57 let obj = ToolbarView() 53 let obj = ToolbarView()
  54 + obj.backgroundColor = ColorConstants.customLightBlue
58 55
59 return obj 56 return obj
60 }() 57 }()
@@ -79,7 +76,7 @@ final class BrowserHomeView: UIView { @@ -79,7 +76,7 @@ final class BrowserHomeView: UIView {
79 private func setup() { 76 private func setup() {
80 addSubview(titleLabel) 77 addSubview(titleLabel)
81 addSubview(frequentlyVisitedCollectionView) 78 addSubview(frequentlyVisitedCollectionView)
82 - addSubview(removeAddButton) 79 + addSubview(removeAdvertSegmentControl)
83 addSubview(settingButton) 80 addSubview(settingButton)
84 addSubview(searchBarContainer) 81 addSubview(searchBarContainer)
85 addSubview(toolbarView) 82 addSubview(toolbarView)
@@ -88,19 +85,20 @@ final class BrowserHomeView: UIView { @@ -88,19 +85,20 @@ final class BrowserHomeView: UIView {
88 } 85 }
89 86
90 private func setupConstraints() { 87 private func setupConstraints() {
91 - removeAddButton.snp.makeConstraints { make in 88 + removeAdvertSegmentControl.snp.makeConstraints { make in
92 make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(16.sizeH) 89 make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(16.sizeH)
93 - make.leading.equalTo(safeAreaLayoutGuide.snp.leading).offset(20.sizeW)  
94 - make.trailing.equalToSuperview().offset(-158.sizeW) 90 + make.leading.equalToSuperview().offset(54.sizeW)
  91 + make.trailing.equalTo(settingButton.snp.leading).offset(-15.sizeW)
  92 + make.height.equalTo(34.sizeH)
95 } 93 }
96 settingButton.snp.makeConstraints { make in 94 settingButton.snp.makeConstraints { make in
97 make.trailing.equalToSuperview().offset(-16.sizeW) 95 make.trailing.equalToSuperview().offset(-16.sizeW)
98 make.height.equalTo(24.sizeH) 96 make.height.equalTo(24.sizeH)
99 make.width.equalTo(24.sizeH) 97 make.width.equalTo(24.sizeH)
100 - make.centerY.equalTo(removeAddButton) 98 + make.centerY.equalTo(removeAdvertSegmentControl)
101 } 99 }
102 titleLabel.snp.makeConstraints { make in 100 titleLabel.snp.makeConstraints { make in
103 - make.top.equalTo(removeAddButton.snp.bottom).offset(64.sizeH) 101 + make.top.equalTo(removeAdvertSegmentControl.snp.bottom).offset(64.sizeH)
104 make.leading.equalTo(safeAreaLayoutGuide.snp.leading).offset(16.sizeW) 102 make.leading.equalTo(safeAreaLayoutGuide.snp.leading).offset(16.sizeW)
105 } 103 }
106 frequentlyVisitedCollectionView.snp.makeConstraints { make in 104 frequentlyVisitedCollectionView.snp.makeConstraints { make in
@@ -110,7 +108,7 @@ final class BrowserHomeView: UIView { @@ -110,7 +108,7 @@ final class BrowserHomeView: UIView {
110 } 108 }
111 toolbarView.snp.makeConstraints { make in 109 toolbarView.snp.makeConstraints { make in
112 make.leading.equalToSuperview() 110 make.leading.equalToSuperview()
113 - make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom) 111 + make.bottom.equalToSuperview()
114 make.trailing.equalToSuperview() 112 make.trailing.equalToSuperview()
115 } 113 }
116 searchBarContainer.snp.makeConstraints { make in 114 searchBarContainer.snp.makeConstraints { make in
@@ -123,7 +121,7 @@ final class BrowserHomeView: UIView { @@ -123,7 +121,7 @@ final class BrowserHomeView: UIView {
123 121
124 //MARK: - childView extension 122 //MARK: - childView extension
125 extension BrowserHomeView { 123 extension BrowserHomeView {
126 - func addSearchView(_ childView: UIView){ 124 + func addSearchView(_ childView: UIView) {
127 addSubview(childView) 125 addSubview(childView)
128 126
129 childView.snp.makeConstraints { make in 127 childView.snp.makeConstraints { make in
@@ -138,7 +136,10 @@ extension BrowserHomeView { @@ -138,7 +136,10 @@ extension BrowserHomeView {
138 extension BrowserHomeView { 136 extension BrowserHomeView {
139 func animateSearchBar(_ keyboardHeight: CGFloat) { 137 func animateSearchBar(_ keyboardHeight: CGFloat) {
140 UIView.animate(withDuration: 0.3) { 138 UIView.animate(withDuration: 0.3) {
141 - self.searchBarContainer.backgroundColor = UIColor(red: 0.808, green: 0.823, blue: 0.85, alpha: 0.9) 139 + self.searchBarContainer.backgroundColor = ColorConstants.customLightBlue
  140 + self.searchBarContainer.searchBarView.backgroundColor = .black
  141 + self.searchBarContainer.searchBarView.searchTextFieldView.textColor = .white
  142 +
142 self.searchBarContainer.snp.updateConstraints { make in 143 self.searchBarContainer.snp.updateConstraints { make in
143 make.leading.equalToSuperview() 144 make.leading.equalToSuperview()
144 make.trailing.equalToSuperview() 145 make.trailing.equalToSuperview()
@@ -150,7 +151,7 @@ extension BrowserHomeView { @@ -150,7 +151,7 @@ extension BrowserHomeView {
150 151
151 func animateSearchBarDismiss() { 152 func animateSearchBarDismiss() {
152 BrowserHomeView.animate(withDuration: 0.3) { 153 BrowserHomeView.animate(withDuration: 0.3) {
153 - self.searchBarContainer.backgroundColor = .clear 154 + self.searchBarContainer.searchBarView.backgroundColor = ColorConstants.customLightBlue
154 self.searchBarContainer.snp.updateConstraints { make in 155 self.searchBarContainer.snp.updateConstraints { make in
155 make.leading.equalToSuperview() 156 make.leading.equalToSuperview()
156 make.trailing.equalToSuperview() 157 make.trailing.equalToSuperview()
@@ -10,7 +10,7 @@ import UIKit @@ -10,7 +10,7 @@ import UIKit
10 final class SearchBarContainer: UIView { 10 final class SearchBarContainer: UIView {
11 let searchBarView: SearchBarView = { 11 let searchBarView: SearchBarView = {
12 let obj = SearchBarView() 12 let obj = SearchBarView()
13 - obj.backgroundColor = .white 13 + obj.backgroundColor = ColorConstants.customLightBlue
14 obj.layer.cornerRadius = 10 14 obj.layer.cornerRadius = 10
15 obj.layer.shadowColor = UIColor.black.withAlphaComponent(0.1).cgColor 15 obj.layer.shadowColor = UIColor.black.withAlphaComponent(0.1).cgColor
16 obj.layer.shadowOpacity = 1 16 obj.layer.shadowOpacity = 1
@@ -10,7 +10,7 @@ import UIKit @@ -10,7 +10,7 @@ import UIKit
10 final class SearchBarView: UIView { 10 final class SearchBarView: UIView {
11 private let searchImageView: UIImageView = { 11 private let searchImageView: UIImageView = {
12 let obj = UIImageView() 12 let obj = UIImageView()
13 - let magnifyImage = UIImage(systemName: "magnifyingglass")?.withTintColor(.gray, renderingMode: .alwaysOriginal) 13 + let magnifyImage = UIImage(systemName: "magnifyingglass")?.withTintColor(ColorConstants.SearchbarTintBlue, renderingMode: .alwaysOriginal)
14 obj.image = magnifyImage 14 obj.image = magnifyImage
15 15
16 return obj 16 return obj
@@ -19,7 +19,7 @@ final class SearchBarView: UIView { @@ -19,7 +19,7 @@ final class SearchBarView: UIView {
19 let searchTextFieldView: UITextField = { 19 let searchTextFieldView: UITextField = {
20 let obj = UITextField() 20 let obj = UITextField()
21 obj.text = "Search" 21 obj.text = "Search"
22 - obj.textColor = ColorConstants.gray 22 + obj.textColor = ColorConstants.SearchbarTintBlue
23 23
24 return obj 24 return obj
25 }() 25 }()
@@ -27,7 +27,7 @@ final class SearchBarView: UIView { @@ -27,7 +27,7 @@ final class SearchBarView: UIView {
27 let cleanTextFieldButton: UIButton = { 27 let cleanTextFieldButton: UIButton = {
28 let obj = UIButton() 28 let obj = UIButton()
29 obj.setImage(UIImage(systemName: "xmark.circle.fill"), for: .normal) 29 obj.setImage(UIImage(systemName: "xmark.circle.fill"), for: .normal)
30 - obj.tintColor = .black 30 + obj.tintColor = ColorConstants.SearchbarTintBlue
31 obj.isHidden = true 31 obj.isHidden = true
32 32
33 return obj 33 return obj
@@ -21,7 +21,7 @@ final class ToolbarView: UIView { @@ -21,7 +21,7 @@ final class ToolbarView: UIView {
21 private let toolbar: UIToolbar = { 21 private let toolbar: UIToolbar = {
22 let obj = UIToolbar() 22 let obj = UIToolbar()
23 obj.sizeToFit() 23 obj.sizeToFit()
24 - obj.barTintColor = ColorConstants.lightGray 24 + obj.barTintColor = ColorConstants.customLightBlue
25 obj.clipsToBounds = true 25 obj.clipsToBounds = true
26 26
27 return obj 27 return obj
@@ -13,8 +13,6 @@ final class PayloadViewController: UIViewController { @@ -13,8 +13,6 @@ final class PayloadViewController: UIViewController {
13 13
14 override func viewDidLoad() { 14 override func viewDidLoad() {
15 super.viewDidLoad() 15 super.viewDidLoad()
16 - view.backgroundColor = ColorConstants.lightGray  
17 -  
18 initViewController() 16 initViewController()
19 } 17 }
20 18
@@ -19,7 +19,7 @@ final class AdvantagesTableViewCell: UITableViewCell { @@ -19,7 +19,7 @@ final class AdvantagesTableViewCell: UITableViewCell {
19 19
20 private let advantagesCellImage: UIImageView = { 20 private let advantagesCellImage: UIImageView = {
21 let obj = UIImageView() 21 let obj = UIImageView()
22 - let checkmarkImg = UIImage(systemName: "checkmark")?.withTintColor(.blue, renderingMode: .alwaysOriginal) 22 + let checkmarkImg = UIImage(systemName: "checkmark")?.withTintColor(ColorConstants.customPink, renderingMode: .alwaysOriginal)
23 obj.image = checkmarkImg 23 obj.image = checkmarkImg
24 obj.contentMode = .scaleToFill 24 obj.contentMode = .scaleToFill
25 25
@@ -7,10 +7,10 @@ @@ -7,10 +7,10 @@
7 7
8 import UIKit 8 import UIKit
9 9
10 -final class PayloadView: UIView { 10 +final class PayloadView: GradientView {
11 private let logoImageView: UIImageView = { 11 private let logoImageView: UIImageView = {
12 let obj = UIImageView() 12 let obj = UIImageView()
13 - obj.image = UIImage(named: "Gotoweb") 13 + obj.image = UIImage(named: "gotoweb")
14 obj.contentMode = .scaleAspectFit 14 obj.contentMode = .scaleAspectFit
15 15
16 return obj 16 return obj
@@ -34,6 +34,7 @@ final class PayloadView: UIView { @@ -34,6 +34,7 @@ final class PayloadView: UIView {
34 34
35 let infoLabel: UILabel = { 35 let infoLabel: UILabel = {
36 let obj = UILabel() 36 let obj = UILabel()
  37 + obj.textColor = .white
37 obj.text = StringConstants.ourBrowser 38 obj.text = StringConstants.ourBrowser
38 obj.font = FontConstants.regularFont_12 39 obj.font = FontConstants.regularFont_12
39 obj.numberOfLines = 0 40 obj.numberOfLines = 0
@@ -50,7 +51,7 @@ final class PayloadView: UIView { @@ -50,7 +51,7 @@ final class PayloadView: UIView {
50 return obj 51 return obj
51 }() 52 }()
52 53
53 - private let gradientLayer = CAGradientLayer() 54 + private let gradientButtonLayer = CAGradientLayer()
54 55
55 let getStartedButton: UIButton = { 56 let getStartedButton: UIButton = {
56 let obj = UIButton() 57 let obj = UIButton()
@@ -66,12 +67,12 @@ final class PayloadView: UIView { @@ -66,12 +67,12 @@ final class PayloadView: UIView {
66 let privacyLabelView: UILabel = { 67 let privacyLabelView: UILabel = {
67 let obj = UILabel() 68 let obj = UILabel()
68 obj.textAlignment = .center 69 obj.textAlignment = .center
69 - 70 + obj.textColor = .white
70 let fullText = "By starting, you agree to our Terms and Condition and Privacy Policy." 71 let fullText = "By starting, you agree to our Terms and Condition and Privacy Policy."
71 let attributedText = NSMutableAttributedString(string: fullText) 72 let attributedText = NSMutableAttributedString(string: fullText)
72 73
73 - attributedText.addAttribute(.foregroundColor, value: UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 1).cgColor, range: NSRange(location: fullText.range(of: "Terms and Condition")?.lowerBound.utf16Offset(in: fullText) ?? 0, length: "Terms and Condition".count))  
74 - attributedText.addAttribute(.foregroundColor, value: UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 1).cgColor, range: NSRange(location: fullText.range(of: "Privacy Policy")?.lowerBound.utf16Offset(in: fullText) ?? 0, length: "Privacy Policy".count)) 74 + attributedText.addAttribute(.foregroundColor, value: ColorConstants.customPinkForText.cgColor, range: NSRange(location: fullText.range(of: "Terms and Condition")?.lowerBound.utf16Offset(in: fullText) ?? 0, length: "Terms and Condition".count))
  75 + attributedText.addAttribute(.foregroundColor, value: ColorConstants.customPinkForText.cgColor, range: NSRange(location: fullText.range(of: "Privacy Policy")?.lowerBound.utf16Offset(in: fullText) ?? 0, length: "Privacy Policy".count))
75 obj.attributedText = attributedText 76 obj.attributedText = attributedText
76 obj.font = FontConstants.regularFont_12 77 obj.font = FontConstants.regularFont_12
77 obj.numberOfLines = 0 78 obj.numberOfLines = 0
@@ -93,7 +94,7 @@ final class PayloadView: UIView { @@ -93,7 +94,7 @@ final class PayloadView: UIView {
93 override func layoutSubviews() { 94 override func layoutSubviews() {
94 super.layoutSubviews() 95 super.layoutSubviews()
95 96
96 - gradientLayer.frame = getStartedButton.bounds 97 + gradientButtonLayer.frame = getStartedButton.bounds
97 } 98 }
98 99
99 private func setup() { 100 private func setup() {
@@ -112,7 +113,7 @@ final class PayloadView: UIView { @@ -112,7 +113,7 @@ final class PayloadView: UIView {
112 private func setupConstraints() { 113 private func setupConstraints() {
113 logoImageView.snp.makeConstraints { make in 114 logoImageView.snp.makeConstraints { make in
114 make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(16.sizeH) 115 make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(16.sizeH)
115 - make.leading.trailing.equalToSuperview().inset(143.sizeW) 116 + make.leading.equalToSuperview().offset(131.sizeW)
116 make.height.equalTo(26.sizeH) 117 make.height.equalTo(26.sizeH)
117 } 118 }
118 119
@@ -156,11 +157,11 @@ final class PayloadView: UIView { @@ -156,11 +157,11 @@ final class PayloadView: UIView {
156 } 157 }
157 } 158 }
158 159
159 -//MARK: Gradient 160 +//MARK: Gradients
160 extension PayloadView { 161 extension PayloadView {
161 private func gradientSetup() { 162 private func gradientSetup() {
162 - getStartedButton.layer.insertSublayer(gradientLayer, at: 0)  
163 - gradientLayer.colors = [UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 1).cgColor, UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 0.7).cgColor]  
164 - gradientLayer.locations = [0.0, 1.0] 163 + getStartedButton.layer.insertSublayer(gradientButtonLayer, at: 0)
  164 + gradientButtonLayer.colors = [UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 1).cgColor, UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 0.7).cgColor]
  165 + gradientButtonLayer.locations = [0.0, 1.0]
165 } 166 }
166 } 167 }
@@ -9,27 +9,24 @@ import UIKit @@ -9,27 +9,24 @@ import UIKit
9 9
10 final class RemoveAdvertViewController: UIViewController { 10 final class RemoveAdvertViewController: UIViewController {
11 private let mainView = RemoveAdvertView() 11 private let mainView = RemoveAdvertView()
12 - private let removeTableViewCellsData: [String] 12 +
  13 + private let tableViewData = StringConstants.tableViewData
  14 +
  15 + var storeKit: StoreKitManager
13 16
14 override func viewDidLoad() { 17 override func viewDidLoad() {
15 super.viewDidLoad() 18 super.viewDidLoad()
16 - 19 +
17 initViewController() 20 initViewController()
18 } 21 }
19 22
20 private func initViewController() { 23 private func initViewController() {
21 - view.backgroundColor = ColorConstants.lightGray  
22 -  
23 - setupTableView()  
24 addTargets() 24 addTargets()
  25 + setupTableView()
25 } 26 }
26 -  
27 - override func loadView() {  
28 - view = mainView  
29 - }  
30 - 27 +
31 init() { 28 init() {
32 - removeTableViewCellsData = StringConstants.removeAdvertTableViewData 29 + self.storeKit = StoreKitManager()
33 30
34 super.init(nibName: nil, bundle: nil) 31 super.init(nibName: nil, bundle: nil)
35 } 32 }
@@ -37,70 +34,94 @@ final class RemoveAdvertViewController: UIViewController { @@ -37,70 +34,94 @@ final class RemoveAdvertViewController: UIViewController {
37 required init?(coder: NSCoder) { 34 required init?(coder: NSCoder) {
38 fatalError("init(coder:) has not been implemented") 35 fatalError("init(coder:) has not been implemented")
39 } 36 }
  37 +
  38 + override func loadView() {
  39 + view = mainView
  40 + }
40 } 41 }
41 42
42 -  
43 -//MARK: - Table View  
44 -extension RemoveAdvertViewController: UITableViewDelegate, UITableViewDataSource {  
45 - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {  
46 - return removeTableViewCellsData.count 43 +//MARK: - Action
  44 +extension RemoveAdvertViewController {
  45 + @objc
  46 + private func adBlockerButtonPressed(_ sender: UIButton) {
  47 + viewAdBlockingHandler()
47 } 48 }
48 49
49 - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {  
50 - guard let cell = tableView.dequeueReusableCell(withIdentifier: RemoveAdvertTableViewCell.cellID) as?  
51 - RemoveAdvertTableViewCell else {  
52 - return UITableViewCell()  
53 - } 50 + @objc
  51 + private func advertSegmantControlStateHandler() {
  52 + let browserHomeViewController = BrowserHomeViewController(url: nil, currentTabId: nil)
  53 + let tabsViewController = TabsViewController()
54 54
55 - cell.advantagesCellLabel.text = removeTableViewCellsData[indexPath.row]  
56 - cell.selectionStyle = .none  
57 -  
58 - return cell 55 + navigationController?.setViewControllers([tabsViewController, browserHomeViewController], animated: true)
59 } 56 }
60 } 57 }
61 58
62 -  
63 -//MARK: - Action 59 +//MARK: Helpers
64 extension RemoveAdvertViewController { 60 extension RemoveAdvertViewController {
65 - @objc  
66 - private func shieldButtonTapped(_ sender: UIButton) {  
67 - UIView.animate(withDuration: 0.2) {  
68 - sender.transform = CGAffineTransform(scaleX: 1.1, y: 1.1)  
69 - sender.alpha = 0.7 61 + private func addTargets() {
  62 + mainView.adBlockButton.addTarget(self, action: #selector(adBlockerButtonPressed(_ :)), for: .touchUpInside)
  63 +
  64 + mainView.removeAdvertSegmentControl.addTarget(self, action: #selector(advertSegmantControlStateHandler), for: .valueChanged)
  65 + }
  66 +
  67 + private func presentSubscriptionHandler() {
  68 + if(storeKit.purchasedSubscriptions.isEmpty) {
  69 + let subcriptionViewController = SubscriptionViewController()
  70 + subcriptionViewController.modalPresentationStyle = .fullScreen
  71 + subcriptionViewController.modalTransitionStyle = .crossDissolve
  72 +
  73 + present(subcriptionViewController, animated: true)
70 } 74 }
71 - let userDefaultsAdBlockerValue = CachingManager.shared.isAdBlocking 75 + }
  76 +
  77 + private func setupTableView() {
  78 + mainView.adBlockTableView.dataSource = self
  79 + mainView.adBlockTableView.delegate = self
  80 + mainView.adBlockTableView.register(RemoveAdvertTableViewCell.self, forCellReuseIdentifier: RemoveAdvertTableViewCell.cellID)
  81 + }
  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
72 87
73 - if userDefaultsAdBlockerValue {  
74 - mainView.shieldView.setImage(.shieldInactive, for: .normal)  
75 - mainView.tapActionLabel.text = StringConstants.turnOff 88 + CachingManager.shared.isAdBlocking = true
  89 + }
  90 +
  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 +
76 CachingManager.shared.isAdBlocking = false 97 CachingManager.shared.isAdBlocking = false
77 } else { 98 } else {
78 - mainView.shieldView.setImage(.shieldActive, for: .normal)  
79 - mainView.tapActionLabel.text = StringConstants.turnOn  
80 - CachingManager.shared.isAdBlocking = true  
81 - }  
82 - UIView.animate(withDuration: 0.2, delay: 0.2) {  
83 - sender.transform = .identity  
84 - sender.alpha = 1.0 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 + }
85 } 108 }
86 } 109 }
87 -  
88 - @objc  
89 - private func closeViewController(_ sender: UIButton) {  
90 - dismiss(animated: true, completion: nil)  
91 - }  
92 } 110 }
93 111
94 -//MARK: Helpers  
95 -extension RemoveAdvertViewController {  
96 - private func addTargets() {  
97 - mainView.shieldView.addTarget(self, action: #selector(shieldButtonTapped(_ :)), for: .touchUpInside)  
98 - mainView.closeButton.addTarget(self, action: #selector(closeViewController(_ :)), for: .touchUpInside) 112 +//MARK: - Table View
  113 +extension RemoveAdvertViewController: UITableViewDelegate, UITableViewDataSource {
  114 + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  115 + return tableViewData.count
99 } 116 }
100 117
101 - private func setupTableView() {  
102 - mainView.advantagesTableView.dataSource = self  
103 - mainView.advantagesTableView.delegate = self  
104 - mainView.advantagesTableView.register(RemoveAdvertTableViewCell.self, forCellReuseIdentifier: RemoveAdvertTableViewCell.cellID) 118 + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  119 + guard let cell = tableView.dequeueReusableCell(withIdentifier: RemoveAdvertTableViewCell.cellID) as?
  120 + RemoveAdvertTableViewCell else {
  121 + return UITableViewCell()
  122 + }
  123 + cell.advantagesCellLabel.text = tableViewData[indexPath.row]
  124 +
  125 + return cell
105 } 126 }
106 } 127 }
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 // RemoveAdvertTableViewCell.swift 2 // RemoveAdvertTableViewCell.swift
3 // browser 3 // browser
4 // 4 //
5 -// Created by Artem Talko on 01.10.2023. 5 +// Created by Artem Talko on 24.11.2023.
6 // 6 //
7 7
8 import UIKit 8 import UIKit
@@ -10,52 +10,55 @@ import UIKit @@ -10,52 +10,55 @@ import UIKit
10 final class RemoveAdvertTableViewCell: UITableViewCell { 10 final class RemoveAdvertTableViewCell: UITableViewCell {
11 static let cellID = String(describing: RemoveAdvertTableViewCell.self) 11 static let cellID = String(describing: RemoveAdvertTableViewCell.self)
12 12
13 - let advantagesCellLabel: UILabel = {  
14 - let obj = UILabel()  
15 - obj.font = FontConstants.regularFont_14  
16 -  
17 - return obj  
18 - }()  
19 -  
20 - private let advantagesCellImage: UIImageView = {  
21 - let obj = UIImageView()  
22 - let checkmarkImg = UIImage(systemName: "checkmark")?.withTintColor(.blue, renderingMode: .alwaysOriginal)  
23 - obj.image = checkmarkImg  
24 - obj.contentMode = .scaleToFill  
25 -  
26 - return obj  
27 - }()  
28 -  
29 - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {  
30 - super.init(style: style, reuseIdentifier: reuseIdentifier)  
31 -  
32 - setup()  
33 - }  
34 -  
35 - required init?(coder: NSCoder) {  
36 - fatalError("init(coder:) has not been implemented")  
37 - }  
38 -  
39 - private func setup() {  
40 - backgroundColor = .clear  
41 - contentView.addSubview(advantagesCellLabel)  
42 - contentView.addSubview(advantagesCellImage)  
43 -  
44 - setupConstraints()  
45 - }  
46 -  
47 - private func setupConstraints() {  
48 - advantagesCellImage.snp.makeConstraints { make in  
49 - make.top.equalToSuperview().inset(5.sizeH)  
50 - make.leading.equalToSuperview()  
51 - make.bottom.equalToSuperview().inset(5.sizeH)  
52 - make.trailing.equalTo(advantagesCellLabel.snp.leading).offset(-8.sizeW)  
53 - }  
54 - advantagesCellLabel.snp.makeConstraints { make in  
55 - make.top.equalToSuperview().inset(5.sizeH)  
56 - make.leading.equalTo(advantagesCellImage.snp.trailing)  
57 - make.bottom.equalToSuperview().inset(5.sizeH)  
58 - make.trailing.equalToSuperview()  
59 - }  
60 - } 13 + let advantagesCellLabel: UILabel = {
  14 + let obj = UILabel()
  15 + obj.font = FontConstants.regularFont_14
  16 +
  17 + return obj
  18 + }()
  19 +
  20 + private let advantagesCellImage: UIImageView = {
  21 + let obj = UIImageView()
  22 + let checkmarkImg = UIImage(systemName: "circle.fill")?.withTintColor(.white, renderingMode: .alwaysOriginal)
  23 + obj.image = checkmarkImg
  24 + obj.contentMode = .scaleAspectFit
  25 +
  26 + return obj
  27 + }()
  28 +
  29 + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
  30 + super.init(style: style, reuseIdentifier: reuseIdentifier)
  31 +
  32 + setup()
  33 + }
  34 +
  35 + required init?(coder: NSCoder) {
  36 + fatalError("init(coder:) has not been implemented")
  37 + }
  38 +
  39 + private func setup() {
  40 + selectionStyle = .none
  41 + backgroundColor = .clear
  42 + contentView.addSubview(advantagesCellLabel)
  43 + contentView.addSubview(advantagesCellImage)
  44 +
  45 + setupConstraints()
  46 + }
  47 +
  48 + private func setupConstraints() {
  49 + advantagesCellLabel.snp.makeConstraints { make in
  50 + make.top.equalToSuperview().inset(5.sizeH)
  51 + make.leading.equalTo(advantagesCellImage.snp.trailing)
  52 + make.bottom.equalToSuperview().inset(5.sizeH)
  53 + make.trailing.equalToSuperview()
  54 + }
  55 +
  56 + advantagesCellImage.snp.makeConstraints { make in
  57 + make.top.equalToSuperview().inset(6.sizeH)
  58 + make.leading.equalToSuperview()
  59 + make.bottom.equalToSuperview().inset(10.sizeH)
  60 + make.trailing.equalTo(advantagesCellLabel.snp.leading).offset(-8.sizeW)
  61 + make.height.width.equalTo(12.sizeH)
  62 + }
  63 + }
61 } 64 }
  1 +//
  2 +// AdBlockButton.swift
  3 +// browser
  4 +//
  5 +// Created by Artem Talko on 22.11.2023.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +final class AdBlockButton: UIButton {
  11 + var buttonImageView: UIImageView = {
  12 + let obj = UIImageView()
  13 + let userDefaultsAdBlockingValue = CachingManager.shared.isAdBlocking
  14 +
  15 + if userDefaultsAdBlockingValue {
  16 + obj.image = .adBlockOnState
  17 + } else {
  18 + obj.image = .adBlockOffState
  19 + }
  20 + obj.contentMode = .scaleAspectFit
  21 +
  22 + return obj
  23 + }()
  24 +
  25 + override init (frame: CGRect) {
  26 + super.init(frame: frame)
  27 +
  28 + setup()
  29 + }
  30 +
  31 + required init?(coder: NSCoder) {
  32 + fatalError("init(coder:) has not been implemented")
  33 + }
  34 +
  35 + private func setup() {
  36 + addSubview(buttonImageView)
  37 +
  38 + setupConstraints()
  39 + }
  40 +
  41 + private func setupConstraints() {
  42 + buttonImageView.snp.makeConstraints { make in
  43 + make.top.equalToSuperview()
  44 + make.leading.equalToSuperview()
  45 + make.bottom.equalToSuperview()
  46 + make.trailing.equalToSuperview()
  47 + }
  48 + }
  49 +}
@@ -8,99 +8,78 @@ @@ -8,99 +8,78 @@
8 import UIKit 8 import UIKit
9 import SnapKit 9 import SnapKit
10 10
11 -final class RemoveAdvertView: UIView {  
12 - let closeButton: UIButton = {  
13 - let obj = UIButton()  
14 - obj.setImage(UIImage(systemName: "xmark"), for: .normal)  
15 - obj.contentMode = .scaleToFill  
16 - obj.tintColor = .gray  
17 -  
18 - return obj  
19 - }()  
20 -  
21 - let shieldView: UIButton = {  
22 - let obj = UIButton()  
23 - let userDefaultsValue = CachingManager.shared.isAdBlocking  
24 -  
25 - if userDefaultsValue {  
26 - obj.setImage(UIImage(named: "ShieldActive"), for: .normal)  
27 - } else {  
28 - obj.setImage(UIImage(named: "ShieldInactive"), for: .normal)  
29 - } 11 +final class RemoveAdvertView: GradientView {
  12 +
  13 + private let appLogoImageView: UIImageView = {
  14 + let obj = UIImageView()
  15 + obj.image = .gotoweb
30 obj.contentMode = .scaleAspectFit 16 obj.contentMode = .scaleAspectFit
31 17
32 return obj 18 return obj
33 }() 19 }()
34 20
35 - private let gradientLayer = CAGradientLayer()  
36 -  
37 - private let abvertBlockerModeLabel: UILabel = {  
38 - let obj = UILabel()  
39 - obj.text = StringConstants.advertMode  
40 - obj.font = FontConstants.semiboldFont_18 21 + let adBlockButton: AdBlockButton = {
  22 + let obj = AdBlockButton()
41 23
42 return obj 24 return obj
43 }() 25 }()
44 26
45 - let tapActionLabel: UILabel = {  
46 - let obj = UILabel()  
47 - obj.text = StringConstants.turnOff  
48 - obj.font = FontConstants.semiboldFont_14 27 + let removeAdvertSegmentControl: UISegmentedControl = {
  28 + let items = ["AdBlock", "Browser"]
  29 + let obj = UISegmentedControl(items: items)
  30 + obj.selectedSegmentIndex = 0
  31 + obj.backgroundColor = ColorConstants.segmentControlBackground
  32 + obj.layer.cornerRadius = 10
  33 + obj.selectedSegmentTintColor = UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 1)
  34 + obj.setTitleTextAttributes([.foregroundColor: UIColor.black], for: .normal)
  35 + obj.setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
49 36
50 return obj 37 return obj
51 }() 38 }()
52 39
53 - let advantagesTableView: UITableView = {  
54 - let obj = UITableView()  
55 - obj.backgroundColor = .clear  
56 - obj.isScrollEnabled = false  
57 - obj.separatorStyle = .none 40 + private let leftDecorativeSquareImageView: UIImageView = {
  41 + let obj = UIImageView()
  42 + obj.image = .leftDecorativeSquares
58 43
59 return obj 44 return obj
60 }() 45 }()
61 46
62 - private let claimOfferLabel: UILabel = {  
63 - let obj = UILabel()  
64 - obj.text = StringConstants.claimOffer  
65 - obj.font = FontConstants.regularFont_12 47 + private let rightDecorativeSquareImageView: UIImageView = {
  48 + let obj = UIImageView()
  49 + obj.image = .rightDecorativeSquares
66 50
67 return obj 51 return obj
68 }() 52 }()
69 53
70 - private let priceLabel: UILabel = { 54 + let tapActionLabel: UILabel = {
71 let obj = UILabel() 55 let obj = UILabel()
72 - obj.text = StringConstants.price  
73 - obj.font = FontConstants.regularFont_18 56 + let userDefaultsAdBlockerValue = CachingManager.shared.isAdBlocking
74 57
75 - return obj  
76 - }()  
77 -  
78 - private let subscribeButton: UIButton = {  
79 - let obj = UIButton()  
80 - obj.backgroundColor = .systemIndigo  
81 - obj.setTitle(StringConstants.subscribe, for: .normal)  
82 - obj.titleLabel?.font = FontConstants.semiboldFont_17  
83 - obj.setTitleColor(.white, for: .normal)  
84 - obj.layer.cornerRadius = 10  
85 - obj.layer.masksToBounds = true 58 + obj.text = StringConstants.turnOn
  59 + obj.font = FontConstants.semiboldFont_24
  60 + //ok
  61 + if userDefaultsAdBlockerValue {
  62 + obj.textColor = ColorConstants.SearchbarTintBlue
  63 + } else {
  64 + obj.textColor = ColorConstants.customPink
  65 + }
86 66
87 return obj 67 return obj
88 }() 68 }()
89 69
90 - private let freeTrialLabel: UILabel = { 70 + private let protectFromLabel: UILabel = {
91 let obj = UILabel() 71 let obj = UILabel()
92 - obj.textAlignment = .center  
93 - obj.font = FontConstants.semiboldFont_12  
94 - obj.text = StringConstants.freeTrial 72 + obj.text = StringConstants.adBlockProtectFrom
  73 + obj.font = FontConstants.semiboldFont_18
95 74
96 return obj 75 return obj
97 }() 76 }()
98 77
99 - private let discountLabel: UILabel = {  
100 - let obj = UILabel()  
101 - obj.textAlignment = .center  
102 - obj.text = StringConstants.yourDiscount  
103 - obj.font = FontConstants.regularFont_12 78 + let adBlockTableView: UITableView = {
  79 + let obj = UITableView()
  80 + obj.backgroundColor = .clear
  81 + obj.isScrollEnabled = false
  82 + obj.separatorStyle = .none
104 83
105 return obj 84 return obj
106 }() 85 }()
@@ -111,95 +90,67 @@ final class RemoveAdvertView: UIView { @@ -111,95 +90,67 @@ final class RemoveAdvertView: UIView {
111 setup() 90 setup()
112 } 91 }
113 92
114 - override func layoutSubviews() {  
115 - super.layoutSubviews()  
116 -  
117 - gradientLayer.frame = subscribeButton.bounds  
118 - }  
119 -  
120 required init?(coder: NSCoder) { 93 required init?(coder: NSCoder) {
121 fatalError("init(coder:) has not been implemented") 94 fatalError("init(coder:) has not been implemented")
122 } 95 }
123 96
124 private func setup() { 97 private func setup() {
125 - addSubview(closeButton)  
126 - addSubview(shieldView)  
127 - addSubview(abvertBlockerModeLabel) 98 + addSubview(appLogoImageView)
  99 + addSubview(adBlockButton)
128 addSubview(tapActionLabel) 100 addSubview(tapActionLabel)
129 - addSubview(advantagesTableView)  
130 - addSubview(claimOfferLabel)  
131 - addSubview(priceLabel)  
132 - addSubview(subscribeButton)  
133 - addSubview(freeTrialLabel)  
134 - addSubview(discountLabel) 101 + addSubview(removeAdvertSegmentControl)
  102 + addSubview(leftDecorativeSquareImageView)
  103 + addSubview(rightDecorativeSquareImageView)
  104 + addSubview(protectFromLabel)
  105 + addSubview(adBlockTableView)
135 106
136 setupConstraints() 107 setupConstraints()
137 - gradientSetup()  
138 } 108 }
139 109
140 private func setupConstraints() { 110 private func setupConstraints() {
141 - closeButton.snp.makeConstraints { make in  
142 - make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(16.sizeH)  
143 - make.trailing.equalToSuperview().inset(16.sizeW)  
144 - make.height.equalTo(24.sizeH) 111 + leftDecorativeSquareImageView.snp.makeConstraints { make in
  112 + make.top.equalToSuperview()
  113 + make.leading.equalToSuperview()
145 } 114 }
146 115
147 - shieldView.snp.makeConstraints { make in  
148 - make.top.equalTo(closeButton.snp.top).offset(8.sizeH)  
149 - make.leading.trailing.equalToSuperview().inset(47.sizeW)  
150 - make.height.equalTo(280.sizeH) 116 + rightDecorativeSquareImageView.snp.makeConstraints { make in
  117 + make.bottom.equalToSuperview()
  118 + make.trailing.equalToSuperview()
151 } 119 }
152 120
153 - abvertBlockerModeLabel.snp.makeConstraints { make in  
154 - make.top.equalTo(shieldView.snp.bottom).offset(16.sizeH)  
155 - make.centerX.equalToSuperview() 121 + appLogoImageView.snp.makeConstraints { make in
  122 + make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(24.sizeH)
  123 + make.leading.trailing.equalToSuperview()
  124 + make.height.equalTo(34.sizeH)
156 } 125 }
157 126
158 - tapActionLabel.snp.makeConstraints { make in  
159 - make.top.equalTo(abvertBlockerModeLabel.snp.bottom).offset(8.sizeH)  
160 - make.centerX.equalToSuperview() 127 + removeAdvertSegmentControl.snp.makeConstraints { make in
  128 + make.top.equalTo(appLogoImageView.snp.bottom).offset(34.sizeH)
  129 + make.leading.trailing.equalToSuperview().inset(54.sizeW)
  130 + make.height.equalTo(34.sizeH)
161 } 131 }
162 132
163 - advantagesTableView.snp.makeConstraints { make in  
164 - make.top.equalTo(tapActionLabel.snp.bottom).offset(26.sizeH)  
165 - make.leading.equalToSuperview().offset(80.sizeW)  
166 - make.bottom.equalTo(claimOfferLabel.snp.top).offset(-24.sizeH)  
167 - make.trailing.equalToSuperview().offset(-86.sizeW)  
168 - }  
169 -  
170 - claimOfferLabel.snp.makeConstraints { make in  
171 - make.bottom.equalTo(priceLabel.snp.top).offset(-4.sizeH)  
172 - make.centerX.equalToSuperview() 133 + adBlockButton.snp.makeConstraints { make in
  134 + make.top.equalTo(removeAdvertSegmentControl.snp.bottom).offset(84.sizeH)
  135 + make.leading.trailing.equalToSuperview().inset(47.sizeW)
  136 + make.height.equalTo(171.sizeH)
173 } 137 }
174 138
175 - priceLabel.snp.makeConstraints { make in  
176 - make.bottom.equalTo(subscribeButton.snp.top).offset(-16.sizeH) 139 + tapActionLabel.snp.makeConstraints { make in
  140 + make.top.equalTo(adBlockButton.snp.bottom).offset(45.sizeH)
177 make.centerX.equalToSuperview() 141 make.centerX.equalToSuperview()
178 } 142 }
179 143
180 - subscribeButton.snp.makeConstraints { make in  
181 - make.leading.trailing.equalToSuperview().inset(32.sizeW)  
182 - make.bottom.equalTo(freeTrialLabel.snp.top).offset(-16.sizeH)  
183 - make.height.equalTo(40.sizeH)  
184 - }  
185 -  
186 - freeTrialLabel.snp.makeConstraints { make in  
187 - make.bottom.equalTo(discountLabel.snp.top).offset(-8.sizeH)  
188 - make.centerX.equalToSuperview() 144 + protectFromLabel.snp.makeConstraints { make in
  145 + make.top.equalTo(tapActionLabel.snp.bottom).offset(44.sizeH)
  146 + make.leading.equalToSuperview().offset(44.sizeW)
189 } 147 }
190 148
191 - discountLabel.snp.makeConstraints { make in  
192 - make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom).offset(-24.sizeH)  
193 - make.centerX.equalToSuperview() 149 + adBlockTableView.snp.makeConstraints { make in
  150 + make.top.equalTo(protectFromLabel.snp.bottom).offset(4.sizeH)
  151 + make.leading.equalToSuperview().offset(44.sizeW)
  152 + make.trailing.equalToSuperview().offset(-32.sizeW)
  153 + make.bottom.equalToSuperview().offset(-16.sizeH)
194 } 154 }
195 } 155 }
196 } 156 }
197 -  
198 -//MARK: Gradient  
199 -extension RemoveAdvertView {  
200 - private func gradientSetup() {  
201 - subscribeButton.layer.insertSublayer(gradientLayer, at: 0)  
202 - gradientLayer.colors = [UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 1).cgColor, UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 0.7).cgColor]  
203 - gradientLayer.locations = [0.0, 1.0]  
204 - }  
205 -}  
  1 +//
  2 +// GradientView.swift
  3 +// browser
  4 +//
  5 +// Created by Artem Talko on 22.11.2023.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +class GradientView: UIView {
  11 + private let gradientViewLayer = CAGradientLayer()
  12 +
  13 + override init (frame: CGRect) {
  14 + super.init(frame: frame)
  15 +
  16 + mainViewGradientSetup()
  17 + }
  18 +
  19 + required init?(coder: NSCoder) {
  20 + fatalError("init(coder:) has not been implemented")
  21 + }
  22 +
  23 + override func layoutSubviews() {
  24 + super.layoutSubviews()
  25 +
  26 + gradientViewLayer.frame = self.bounds
  27 + }
  28 +
  29 + private func mainViewGradientSetup() {
  30 + self.layer.insertSublayer(gradientViewLayer, at: 0)
  31 + gradientViewLayer.colors = [
  32 + UIColor(red: 0, green: 0, blue: 0, alpha: 1).cgColor,
  33 + UIColor(red: 0.337, green: 0.537, blue: 0.949, alpha: 1).cgColor
  34 + ]
  35 + }
  36 +}
@@ -19,7 +19,7 @@ final class SearchingTableViewCell: UITableViewCell { @@ -19,7 +19,7 @@ final class SearchingTableViewCell: UITableViewCell {
19 private var searchImage: UIImageView = { 19 private var searchImage: UIImageView = {
20 let obj = UIImageView() 20 let obj = UIImageView()
21 obj.image = UIImage(systemName: "magnifyingglass") 21 obj.image = UIImage(systemName: "magnifyingglass")
22 - obj.tintColor = .gray 22 + obj.tintColor = .white
23 23
24 return obj 24 return obj
25 }() 25 }()
@@ -40,7 +40,7 @@ final class SearchingTableViewCell: UITableViewCell { @@ -40,7 +40,7 @@ final class SearchingTableViewCell: UITableViewCell {
40 private var linkImage: UIImageView = { 40 private var linkImage: UIImageView = {
41 let obj = UIImageView() 41 let obj = UIImageView()
42 obj.image = UIImage(systemName: "arrow.up.left") 42 obj.image = UIImage(systemName: "arrow.up.left")
43 - obj.tintColor = .gray 43 + obj.tintColor = .white
44 44
45 return obj 45 return obj
46 }() 46 }()
@@ -57,6 +57,7 @@ final class SearchingTableViewCell: UITableViewCell { @@ -57,6 +57,7 @@ final class SearchingTableViewCell: UITableViewCell {
57 } 57 }
58 58
59 private func setup() { 59 private func setup() {
  60 + self.backgroundColor = .clear
60 contentView.addSubview(searchImage) 61 contentView.addSubview(searchImage)
61 contentView.addSubview(searchLabel) 62 contentView.addSubview(searchLabel)
62 contentView.addSubview(siteLogoImage) 63 contentView.addSubview(siteLogoImage)
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 7
8 import UIKit 8 import UIKit
9 9
10 -final class SearchingView: UIView, UITextFieldDelegate { 10 +final class SearchingView: GradientView {
11 let searchingButton: UIButton = { 11 let searchingButton: UIButton = {
12 let obj = UIButton() 12 let obj = UIButton()
13 obj.setImage(UIImage(systemName: "arrow.left"), for: .normal) 13 obj.setImage(UIImage(systemName: "arrow.left"), for: .normal)
@@ -15,7 +15,7 @@ final class SearchingView: UIView, UITextFieldDelegate { @@ -15,7 +15,7 @@ final class SearchingView: UIView, UITextFieldDelegate {
15 return obj 15 return obj
16 }() 16 }()
17 17
18 - let searchingLabel: UILabel = { 18 + private let searchingLabel: UILabel = {
19 let obj = UILabel() 19 let obj = UILabel()
20 obj.text = "Searching" 20 obj.text = "Searching"
21 obj.font = FontConstants.semiboldFont_18 21 obj.font = FontConstants.semiboldFont_18
@@ -7,10 +7,13 @@ @@ -7,10 +7,13 @@
7 7
8 import UIKit 8 import UIKit
9 import MessageUI 9 import MessageUI
  10 +import StoreKit
10 11
11 final class SettingViewController: UIViewController { 12 final class SettingViewController: UIViewController {
  13 +
12 private let mainView = SettingView() 14 private let mainView = SettingView()
13 - private let param = StringConstants.settingViewControllerTableViewData 15 + private let settingTableViewData = StringConstants.settingViewControllerTableViewData
  16 +
14 init() { 17 init() {
15 super.init(nibName: nil, bundle: nil) 18 super.init(nibName: nil, bundle: nil)
16 } 19 }
@@ -40,15 +43,18 @@ final class SettingViewController: UIViewController { @@ -40,15 +43,18 @@ final class SettingViewController: UIViewController {
40 //MARK: SettingTableView 43 //MARK: SettingTableView
41 extension SettingViewController: UITableViewDelegate, UITableViewDataSource { 44 extension SettingViewController: UITableViewDelegate, UITableViewDataSource {
42 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 45 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
43 - return param.count 46 + return settingTableViewData.count
44 } 47 }
45 48
46 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 49 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
47 - guard let cell = tableView.dequeueReusableCell(withIdentifier: "SettingTableViewCell", for: indexPath) as? SettingTableViewCell  
48 - else { return UITableViewCell() }  
49 - let info = param[indexPath.item] 50 + guard let cell = tableView.dequeueReusableCell(withIdentifier: SettingTableViewCell.cellId, for: indexPath) as? SettingTableViewCell
  51 + else {
  52 + return UITableViewCell()
  53 + }
  54 + let info = settingTableViewData[indexPath.item]
50 cell.settingTableViewLabel.text = info 55 cell.settingTableViewLabel.text = info
51 cell.selectionStyle = .none 56 cell.selectionStyle = .none
  57 +
52 return cell 58 return cell
53 } 59 }
54 60
@@ -68,7 +74,7 @@ extension SettingViewController { @@ -68,7 +74,7 @@ extension SettingViewController {
68 private func setupSettingTableView() { 74 private func setupSettingTableView() {
69 mainView.settingTableView.delegate = self 75 mainView.settingTableView.delegate = self
70 mainView.settingTableView.dataSource = self 76 mainView.settingTableView.dataSource = self
71 - mainView.settingTableView.register(SettingTableViewCell.self, forCellReuseIdentifier: StringConstants.settingTableViewCell) 77 + mainView.settingTableView.register(SettingTableViewCell.self, forCellReuseIdentifier: SettingTableViewCell.cellId)
72 } 78 }
73 79
74 private func setupMessage() { 80 private func setupMessage() {
@@ -77,7 +83,7 @@ extension SettingViewController { @@ -77,7 +83,7 @@ extension SettingViewController {
77 } 83 }
78 let composer = MFMailComposeViewController() 84 let composer = MFMailComposeViewController()
79 composer.mailComposeDelegate = self 85 composer.mailComposeDelegate = self
80 - composer.setToRecipients(["test@gmail.com"]) 86 + composer.setToRecipients(["creattechllc@gmail.com"])
81 composer.setSubject("Browser") 87 composer.setSubject("Browser")
82 present(composer, animated: true, completion: nil) 88 present(composer, animated: true, completion: nil)
83 } 89 }
@@ -96,6 +102,10 @@ extension SettingViewController { @@ -96,6 +102,10 @@ extension SettingViewController {
96 break 102 break
97 case 4: 103 case 4:
98 setupMessage() 104 setupMessage()
  105 + case 5:
  106 + Task {
  107 + try? await AppStore.sync()
  108 + }
99 default: 109 default:
100 break 110 break
101 } 111 }
@@ -116,14 +126,15 @@ extension SettingViewController { @@ -116,14 +126,15 @@ extension SettingViewController {
116 private func shareButtonPressed() { 126 private func shareButtonPressed() {
117 let items = [URL(string: URLConstants.shareAppLink)] 127 let items = [URL(string: URLConstants.shareAppLink)]
118 let shareView = UIActivityViewController(activityItems: items as [Any], applicationActivities: nil) 128 let shareView = UIActivityViewController(activityItems: items as [Any], applicationActivities: nil)
  129 +
119 present(shareView, animated: true) 130 present(shareView, animated: true)
120 } 131 }
121 132
122 private func presentViewController(_ viewController: UIViewController) { 133 private func presentViewController(_ viewController: UIViewController) {
123 viewController.modalPresentationStyle = .fullScreen 134 viewController.modalPresentationStyle = .fullScreen
  135 +
124 present(viewController, animated: true) 136 present(viewController, animated: true)
125 } 137 }
126 -  
127 } 138 }
128 139
129 //MARK: Mail helper 140 //MARK: Mail helper
@@ -8,14 +8,18 @@ @@ -8,14 +8,18 @@
8 import UIKit 8 import UIKit
9 9
10 final class SettingTableViewCell: UITableViewCell { 10 final class SettingTableViewCell: UITableViewCell {
  11 + static let cellId = String(describing: SettingTableViewCell.self)
  12 +
11 let settingTableViewLabel: UILabel = { 13 let settingTableViewLabel: UILabel = {
12 let obj = UILabel() 14 let obj = UILabel()
13 obj.font = FontConstants.semiboldFont_17 15 obj.font = FontConstants.semiboldFont_17
14 obj.textColor = ColorConstants.lightGray 16 obj.textColor = ColorConstants.lightGray
15 obj.textAlignment = .center 17 obj.textAlignment = .center
  18 +
16 obj.backgroundColor = ColorConstants.buttonsBackgroundColor 19 obj.backgroundColor = ColorConstants.buttonsBackgroundColor
17 obj.layer.cornerRadius = 10 20 obj.layer.cornerRadius = 10
18 obj.layer.masksToBounds = true 21 obj.layer.masksToBounds = true
  22 +
19 return obj 23 return obj
20 }() 24 }()
21 25
@@ -23,6 +27,7 @@ final class SettingTableViewCell: UITableViewCell { @@ -23,6 +27,7 @@ final class SettingTableViewCell: UITableViewCell {
23 27
24 override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 28 override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
25 super.init(style: style, reuseIdentifier: reuseIdentifier) 29 super.init(style: style, reuseIdentifier: reuseIdentifier)
  30 +
26 setup() 31 setup()
27 } 32 }
28 33
@@ -31,12 +36,15 @@ final class SettingTableViewCell: UITableViewCell { @@ -31,12 +36,15 @@ final class SettingTableViewCell: UITableViewCell {
31 } 36 }
32 37
33 private func setup() { 38 private func setup() {
  39 + self.backgroundColor = .clear
34 contentView.addSubview(settingTableViewLabel) 40 contentView.addSubview(settingTableViewLabel)
  41 +
35 setupConstraints() 42 setupConstraints()
36 } 43 }
37 44
38 override func layoutSubviews() { 45 override func layoutSubviews() {
39 super.layoutSubviews() 46 super.layoutSubviews()
  47 +
40 gradientLayer.frame = self.bounds 48 gradientLayer.frame = self.bounds
41 } 49 }
42 50
@@ -22,8 +22,6 @@ final class PrivacyViewController: UIViewController { @@ -22,8 +22,6 @@ final class PrivacyViewController: UIViewController {
22 22
23 private func initViewController() { 23 private func initViewController() {
24 addTargets() 24 addTargets()
25 - mainView.backgroundColor = .white  
26 -  
27 } 25 }
28 } 26 }
29 27
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 7
8 import UIKit 8 import UIKit
9 9
10 -final class PrivacyView: UIView { 10 +final class PrivacyView: GradientView {
11 private let privacyHeaderLabel: UILabel = { 11 private let privacyHeaderLabel: UILabel = {
12 let obj = UILabel() 12 let obj = UILabel()
13 obj.text = StringConstants.privacyHeaderText 13 obj.text = StringConstants.privacyHeaderText
@@ -20,7 +20,7 @@ final class PrivacyView: UIView { @@ -20,7 +20,7 @@ final class PrivacyView: UIView {
20 20
21 private let privacyMainInfoLabel: UILabel = { 21 private let privacyMainInfoLabel: UILabel = {
22 let obj = UILabel() 22 let obj = UILabel()
23 - obj.text = StringConstants.settingTerms 23 + obj.text = StringConstants.settingPolicy
24 obj.numberOfLines = 0 24 obj.numberOfLines = 0
25 obj.font = FontConstants.regularFont_18 25 obj.font = FontConstants.regularFont_18
26 26
@@ -29,10 +29,10 @@ final class PrivacyView: UIView { @@ -29,10 +29,10 @@ final class PrivacyView: UIView {
29 29
30 let privacyButton: UIButton = { 30 let privacyButton: UIButton = {
31 let obj = UIButton() 31 let obj = UIButton()
32 - obj.backgroundColor = .systemIndigo.withAlphaComponent(0.4) 32 + obj.backgroundColor = ColorConstants.buttonsBackgroundColor
33 obj.layer.cornerRadius = 10 33 obj.layer.cornerRadius = 10
34 obj.setTitle(StringConstants.settingAgreeButtonText, for: .normal) 34 obj.setTitle(StringConstants.settingAgreeButtonText, for: .normal)
35 - obj.setTitleColor(.black, for: .normal) 35 + obj.setTitleColor(.white, for: .normal)
36 36
37 return obj 37 return obj
38 }() 38 }()
@@ -21,8 +21,6 @@ final class TermsViewController: UIViewController { @@ -21,8 +21,6 @@ final class TermsViewController: UIViewController {
21 } 21 }
22 22
23 private func initViewController() { 23 private func initViewController() {
24 - mainView.backgroundColor = .white  
25 -  
26 addTargets() 24 addTargets()
27 } 25 }
28 } 26 }
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 8
9 import UIKit 9 import UIKit
10 10
11 -final class TermsView: UIView { 11 +final class TermsView: GradientView {
12 private let termsHeaderLabel: UILabel = { 12 private let termsHeaderLabel: UILabel = {
13 let obj = UILabel() 13 let obj = UILabel()
14 obj.text = StringConstants.settingHeader 14 obj.text = StringConstants.settingHeader
@@ -30,10 +30,10 @@ final class TermsView: UIView { @@ -30,10 +30,10 @@ final class TermsView: UIView {
30 30
31 let termsButton: UIButton = { 31 let termsButton: UIButton = {
32 let obj = UIButton() 32 let obj = UIButton()
33 - obj.backgroundColor = .systemIndigo.withAlphaComponent(0.4) 33 + obj.backgroundColor = ColorConstants.buttonsBackgroundColor
34 obj.layer.cornerRadius = 10 34 obj.layer.cornerRadius = 10
35 obj.setTitle(StringConstants.settingAgreeButtonText, for: .normal) 35 obj.setTitle(StringConstants.settingAgreeButtonText, for: .normal)
36 - obj.setTitleColor(.black, for: .normal) 36 + obj.setTitleColor(.white, for: .normal)
37 37
38 return obj 38 return obj
39 }() 39 }()
@@ -7,11 +7,12 @@ @@ -7,11 +7,12 @@
7 7
8 import UIKit 8 import UIKit
9 9
10 -final class SettingView: UIView { 10 +final class SettingView: GradientView {
11 let backButton: UIButton = { 11 let backButton: UIButton = {
12 let obj = UIButton() 12 let obj = UIButton()
13 obj.setImage(UIImage(systemName: "arrow.left"), for: .normal) 13 obj.setImage(UIImage(systemName: "arrow.left"), for: .normal)
14 obj.contentMode = .scaleToFill 14 obj.contentMode = .scaleToFill
  15 +
15 return obj 16 return obj
16 }() 17 }()
17 18
@@ -19,6 +20,8 @@ final class SettingView: UIView { @@ -19,6 +20,8 @@ final class SettingView: UIView {
19 let obj = UITableView() 20 let obj = UITableView()
20 obj.isScrollEnabled = false 21 obj.isScrollEnabled = false
21 obj.separatorStyle = .none 22 obj.separatorStyle = .none
  23 + obj.backgroundColor = .clear
  24 +
22 return obj 25 return obj
23 }() 26 }()
24 27
  1 +//
  2 +// SubscriptionViewController.swift
  3 +// browser
  4 +//
  5 +// Created by Artem Talko on 24.11.2023.
  6 +//
  7 +
  8 +import UIKit
  9 +import StoreKit
  10 +
  11 +
  12 +final class SubscriptionViewController: UIViewController {
  13 + private let mainView = SubscriptionView()
  14 +
  15 + private let tableViewData: [String]
  16 +
  17 + override func viewDidLoad() {
  18 + super.viewDidLoad()
  19 +
  20 + initViewController()
  21 + }
  22 +
  23 + init() {
  24 + self.tableViewData = StringConstants.removeAdvertTableViewData
  25 +
  26 + super.init(nibName: nil, bundle: nil)
  27 + }
  28 +
  29 + required init?(coder: NSCoder) {
  30 + fatalError("init(coder:) has not been implemented")
  31 + }
  32 +
  33 + override func loadView() {
  34 + view = mainView
  35 + }
  36 +
  37 + private func initViewController() {
  38 + addTargets()
  39 + setupTableView()
  40 + }
  41 +}
  42 +
  43 +//MARK: - Table View
  44 +extension SubscriptionViewController: UITableViewDelegate, UITableViewDataSource {
  45 + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  46 + return tableViewData.count
  47 + }
  48 +
  49 + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  50 + guard let cell = tableView.dequeueReusableCell(withIdentifier: SubscriptionTableViewCell.cellID) as?
  51 + SubscriptionTableViewCell else {
  52 + return UITableViewCell()
  53 + }
  54 + cell.advantagesCellLabel.text = tableViewData[indexPath.row]
  55 +
  56 + return cell
  57 + }
  58 +}
  59 +
  60 +//MARK: Helpers
  61 +extension SubscriptionViewController {
  62 + private func addTargets() {
  63 + mainView.closeButton.addTarget(self, action: #selector(closeViewController(_ :)), for: .touchUpInside)
  64 + mainView.subscribeButton.addTarget(self, action: #selector(buyAdblocker), for: .touchUpInside)
  65 + }
  66 +
  67 + private func setupTableView() {
  68 + mainView.advantagesTableView.dataSource = self
  69 + mainView.advantagesTableView.delegate = self
  70 + mainView.advantagesTableView.register(SubscriptionTableViewCell.self, forCellReuseIdentifier: SubscriptionTableViewCell.cellID)
  71 + }
  72 +}
  73 +
  74 +
  75 +//MARK: Action
  76 +extension SubscriptionViewController {
  77 + @objc
  78 + private func closeViewController(_ sender: UIButton) {
  79 + dismiss(animated: true, completion: nil)
  80 + }
  81 +
  82 + @objc
  83 + private func buyAdblocker(_ sender: UIButton) {
  84 + guard let navigationController = presentingViewController as? NavigationViewController else {
  85 + return
  86 + }
  87 + for viewController in navigationController.viewControllers {
  88 + guard let removeAdvertViewController = viewController as? RemoveAdvertViewController else {
  89 + return
  90 + }
  91 + Task {
  92 + do {
  93 + if let adblockerProduct = removeAdvertViewController.storeKit.storeProducts.first(where: { $0.id == "com.browser.adblocker" }) {
  94 + if (try await removeAdvertViewController.storeKit.purchase(adblockerProduct)) != nil {
  95 + removeAdvertViewController.successfullPurchaseHandler()
  96 +
  97 + self.dismiss(animated: true)
  98 + } else {
  99 + print("Purchase cancelled or pending.")
  100 + }
  101 + } else {
  102 + print("Adblocker product not found.")
  103 + }
  104 + } catch {
  105 + print("Failed to purchase Adblocker: \(error)")
  106 + }
  107 + }
  108 + }
  109 + }
  110 +}
  1 +//
  2 +// SubscriptionTableViewCell.swift
  3 +// browser
  4 +//
  5 +// Created by Artem Talko on 24.11.2023.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +final class SubscriptionTableViewCell: UITableViewCell {
  11 + static let cellID = String(describing: SubscriptionTableViewCell.self)
  12 +
  13 +
  14 + let advantagesCellLabel: UILabel = {
  15 + let obj = UILabel()
  16 + obj.font = FontConstants.regularFont_14
  17 +
  18 + return obj
  19 + }()
  20 +
  21 + private let advantagesCellImage: UIImageView = {
  22 + let obj = UIImageView()
  23 + let checkmarkImg = UIImage(systemName: "checkmark")?.withTintColor(.white, renderingMode: .alwaysOriginal)
  24 + obj.image = checkmarkImg
  25 + obj.contentMode = .scaleToFill
  26 +
  27 + return obj
  28 + }()
  29 +
  30 + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
  31 + super.init(style: style, reuseIdentifier: reuseIdentifier)
  32 +
  33 + setup()
  34 + }
  35 +
  36 + required init?(coder: NSCoder) {
  37 + fatalError("init(coder:) has not been implemented")
  38 + }
  39 +
  40 + private func setup() {
  41 + selectionStyle = .none
  42 + backgroundColor = .clear
  43 + contentView.addSubview(advantagesCellLabel)
  44 + contentView.addSubview(advantagesCellImage)
  45 +
  46 + setupConstraints()
  47 + }
  48 +
  49 + private func setupConstraints() {
  50 + advantagesCellImage.snp.makeConstraints { make in
  51 + make.top.equalToSuperview().inset(5.sizeH)
  52 + make.leading.equalToSuperview()
  53 + make.bottom.equalToSuperview().inset(5.sizeH)
  54 + make.trailing.equalTo(advantagesCellLabel.snp.leading).offset(-8.sizeW)
  55 + }
  56 + advantagesCellLabel.snp.makeConstraints { make in
  57 + make.top.equalToSuperview().inset(5.sizeH)
  58 + make.leading.equalTo(advantagesCellImage.snp.trailing)
  59 + make.bottom.equalToSuperview().inset(5.sizeH)
  60 + make.trailing.equalToSuperview()
  61 + }
  62 + }
  63 +}
  1 +//
  2 +// SubscriptionView.swift
  3 +// browser
  4 +//
  5 +// Created by Artem Talko on 24.11.2023.
  6 +//
  7 +
  8 +import UIKit
  9 +
  10 +final class SubscriptionView: GradientView {
  11 + let closeButton: UIButton = {
  12 + let obj = UIButton()
  13 + obj.setImage(UIImage(systemName: "xmark"), for: .normal)
  14 + obj.contentMode = .scaleToFill
  15 + obj.tintColor = .gray
  16 +
  17 + return obj
  18 + }()
  19 +
  20 + let shieldView: UIImageView = {
  21 + let obj = UIImageView()
  22 + obj.image = .shield
  23 + obj.contentMode = .scaleAspectFit
  24 +
  25 + return obj
  26 + }()
  27 +
  28 + private let gradientLayer = CAGradientLayer()
  29 +
  30 + private let abvertBlockerModeLabel: UILabel = {
  31 + let obj = UILabel()
  32 + obj.text = StringConstants.advertMode
  33 + obj.font = FontConstants.semiboldFont_18
  34 +
  35 + return obj
  36 + }()
  37 +
  38 + let advantagesTableView: UITableView = {
  39 + let obj = UITableView()
  40 + obj.backgroundColor = .clear
  41 + obj.isScrollEnabled = false
  42 + obj.separatorStyle = .none
  43 +
  44 + return obj
  45 + }()
  46 +
  47 + private let claimOfferLabel: UILabel = {
  48 + let obj = UILabel()
  49 + obj.text = StringConstants.claimOffer
  50 + obj.font = FontConstants.regularFont_12
  51 +
  52 + return obj
  53 + }()
  54 +
  55 + private let priceLabel: UILabel = {
  56 + let obj = UILabel()
  57 + obj.text = StringConstants.price
  58 + obj.font = FontConstants.regularFont_18
  59 +
  60 + return obj
  61 + }()
  62 +
  63 + let subscribeButton: UIButton = {
  64 + let obj = UIButton()
  65 + obj.backgroundColor = .systemIndigo
  66 + obj.setTitle(StringConstants.subscribe, for: .normal)
  67 + obj.titleLabel?.font = FontConstants.semiboldFont_17
  68 + obj.setTitleColor(.white, for: .normal)
  69 + obj.layer.cornerRadius = 10
  70 + obj.layer.masksToBounds = true
  71 +
  72 + return obj
  73 + }()
  74 +
  75 + private let freeTrialLabel: UILabel = {
  76 + let obj = UILabel()
  77 + obj.textAlignment = .center
  78 + obj.font = FontConstants.semiboldFont_12
  79 + obj.text = StringConstants.freeTrial
  80 +
  81 + return obj
  82 + }()
  83 +
  84 + private let discountLabel: UILabel = {
  85 + let obj = UILabel()
  86 + obj.textAlignment = .center
  87 + obj.text = StringConstants.yourDiscount
  88 + obj.font = FontConstants.regularFont_12
  89 +
  90 + return obj
  91 + }()
  92 +
  93 + override init (frame: CGRect) {
  94 + super.init(frame: frame)
  95 +
  96 + setup()
  97 + }
  98 +
  99 + override func layoutSubviews() {
  100 + super.layoutSubviews()
  101 +
  102 + gradientLayer.frame = subscribeButton.bounds
  103 + }
  104 +
  105 + required init?(coder: NSCoder) {
  106 + fatalError("init(coder:) has not been implemented")
  107 + }
  108 +
  109 + private func setup() {
  110 + addSubview(closeButton)
  111 + addSubview(shieldView)
  112 + addSubview(abvertBlockerModeLabel)
  113 + addSubview(advantagesTableView)
  114 + addSubview(claimOfferLabel)
  115 + addSubview(priceLabel)
  116 + addSubview(subscribeButton)
  117 + addSubview(freeTrialLabel)
  118 + addSubview(discountLabel)
  119 +
  120 + setupConstraints()
  121 + gradientSetup()
  122 + }
  123 +
  124 + private func setupConstraints() {
  125 + closeButton.snp.makeConstraints { make in
  126 + make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(16.sizeH)
  127 + make.trailing.equalToSuperview().inset(16.sizeW)
  128 + make.height.equalTo(24.sizeH)
  129 + }
  130 +
  131 + shieldView.snp.makeConstraints { make in
  132 + make.top.equalTo(closeButton.snp.top).offset(8.sizeH)
  133 + make.leading.trailing.equalToSuperview().inset(47.sizeW)
  134 + make.height.equalTo(280.sizeH)
  135 + }
  136 +
  137 + abvertBlockerModeLabel.snp.makeConstraints { make in
  138 + make.top.equalTo(shieldView.snp.bottom).offset(16.sizeH)
  139 + make.centerX.equalToSuperview()
  140 + }
  141 +
  142 + advantagesTableView.snp.makeConstraints { make in
  143 + make.top.equalTo(abvertBlockerModeLabel.snp.bottom).offset(26.sizeH)
  144 + make.leading.equalToSuperview().offset(80.sizeW)
  145 + make.bottom.equalTo(claimOfferLabel.snp.top).offset(-24.sizeH)
  146 + make.trailing.equalToSuperview().offset(-86.sizeW)
  147 + }
  148 +
  149 + claimOfferLabel.snp.makeConstraints { make in
  150 + make.bottom.equalTo(priceLabel.snp.top).offset(-4.sizeH)
  151 + make.centerX.equalToSuperview()
  152 + }
  153 +
  154 + priceLabel.snp.makeConstraints { make in
  155 + make.bottom.equalTo(subscribeButton.snp.top).offset(-16.sizeH)
  156 + make.centerX.equalToSuperview()
  157 + }
  158 +
  159 + subscribeButton.snp.makeConstraints { make in
  160 + make.leading.trailing.equalToSuperview().inset(32.sizeW)
  161 + make.bottom.equalTo(freeTrialLabel.snp.top).offset(-16.sizeH)
  162 + make.height.equalTo(40.sizeH)
  163 + }
  164 +
  165 + freeTrialLabel.snp.makeConstraints { make in
  166 + make.bottom.equalTo(discountLabel.snp.top).offset(-8.sizeH)
  167 + make.centerX.equalToSuperview()
  168 + }
  169 +
  170 + discountLabel.snp.makeConstraints { make in
  171 + make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom).offset(-24.sizeH)
  172 + make.centerX.equalToSuperview()
  173 + }
  174 + }
  175 +}
  176 +
  177 +//MARK: Gradient
  178 +extension SubscriptionView {
  179 + private func gradientSetup() {
  180 + subscribeButton.layer.insertSublayer(gradientLayer, at: 0)
  181 + gradientLayer.colors = [UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 1).cgColor, UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 0.7).cgColor]
  182 + gradientLayer.locations = [0.0, 1.0]
  183 + }
  184 +}
@@ -118,6 +118,10 @@ extension TabsViewController { @@ -118,6 +118,10 @@ extension TabsViewController {
118 mainView.openedTabsCollectionView.register(OpenedTabsCollectionViewCell.self, forCellWithReuseIdentifier: OpenedTabsCollectionViewCell.cellID) 118 mainView.openedTabsCollectionView.register(OpenedTabsCollectionViewCell.self, forCellWithReuseIdentifier: OpenedTabsCollectionViewCell.cellID)
119 } 119 }
120 120
  121 + func removeSelf() {
  122 + navigationController?.popViewController(animated: false)
  123 + }
  124 +
121 private func addTargets() { 125 private func addTargets() {
122 addToolbarTargets() 126 addToolbarTargets()
123 } 127 }
@@ -156,7 +160,7 @@ extension TabsViewController { @@ -156,7 +160,7 @@ extension TabsViewController {
156 } 160 }
157 } 161 }
158 162
159 - private func refreshData() { 163 + func refreshData() {
160 tabsData = TabManager.shared.getAllTabs() 164 tabsData = TabManager.shared.getAllTabs()
161 mainView.openedTabsCollectionView.reloadData() 165 mainView.openedTabsCollectionView.reloadData()
162 } 166 }
@@ -26,7 +26,7 @@ final class OpenedTabsCollectionViewCell: UICollectionViewCell { @@ -26,7 +26,7 @@ final class OpenedTabsCollectionViewCell: UICollectionViewCell {
26 private let siteNameLabel: UILabel = { 26 private let siteNameLabel: UILabel = {
27 let obj = UILabel() 27 let obj = UILabel()
28 obj.font = FontConstants.regularFont_14 28 obj.font = FontConstants.regularFont_14
29 - 29 + obj.textColor = .black
30 return obj 30 return obj
31 }() 31 }()
32 32
@@ -18,7 +18,7 @@ final class TabsToolbarView: UIView { @@ -18,7 +18,7 @@ final class TabsToolbarView: UIView {
18 18
19 private let toolbar: UIToolbar = { 19 private let toolbar: UIToolbar = {
20 let obj = UIToolbar() 20 let obj = UIToolbar()
21 - obj.barTintColor = .white 21 + obj.barTintColor = ColorConstants.customLightBlue
22 22
23 return obj 23 return obj
24 }() 24 }()
@@ -26,7 +26,7 @@ final class TabsToolbarView: UIView { @@ -26,7 +26,7 @@ final class TabsToolbarView: UIView {
26 private let newTabToolbarButtonItem: UIBarButtonItem = { 26 private let newTabToolbarButtonItem: UIBarButtonItem = {
27 let obj = UIBarButtonItem() 27 let obj = UIBarButtonItem()
28 obj.image = UIImage(systemName: "plus") 28 obj.image = UIImage(systemName: "plus")
29 - obj.tintColor = .gray 29 + obj.tintColor = ColorConstants.SearchbarTintBlue
30 30
31 return obj 31 return obj
32 }() 32 }()
@@ -34,7 +34,7 @@ final class TabsToolbarView: UIView { @@ -34,7 +34,7 @@ final class TabsToolbarView: UIView {
34 34
35 let showedCountOfTabs: UIBarButtonItem = { 35 let showedCountOfTabs: UIBarButtonItem = {
36 let obj = UIBarButtonItem() 36 let obj = UIBarButtonItem()
37 - obj.tintColor = .gray 37 + obj.tintColor = ColorConstants.SearchbarTintBlue
38 38
39 return obj 39 return obj
40 }() 40 }()
@@ -42,7 +42,7 @@ final class TabsToolbarView: UIView { @@ -42,7 +42,7 @@ final class TabsToolbarView: UIView {
42 private let doneTabToolbarButtonItem: UIBarButtonItem = { 42 private let doneTabToolbarButtonItem: UIBarButtonItem = {
43 let obj = UIBarButtonItem() 43 let obj = UIBarButtonItem()
44 obj.title = "Done" 44 obj.title = "Done"
45 - 45 + obj.tintColor = ColorConstants.SearchbarTintBlue
46 return obj 46 return obj
47 }() 47 }()
48 48
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 import UIKit 8 import UIKit
9 import SnapKit 9 import SnapKit
10 10
11 -final class TabsView: UIView { 11 +final class TabsView: GradientView {
12 let openedTabsCollectionView: UICollectionView = { 12 let openedTabsCollectionView: UICollectionView = {
13 let obj = UICollectionViewFlowLayout() 13 let obj = UICollectionViewFlowLayout()
14 obj.minimumInteritemSpacing = 4.sizeW 14 obj.minimumInteritemSpacing = 4.sizeW
@@ -23,7 +23,7 @@ final class TabsView: UIView { @@ -23,7 +23,7 @@ final class TabsView: UIView {
23 23
24 let tabsToolbarView: TabsToolbarView = { 24 let tabsToolbarView: TabsToolbarView = {
25 let obj = TabsToolbarView() 25 let obj = TabsToolbarView()
26 - obj.backgroundColor = ColorConstants.lightGray 26 + obj.backgroundColor = ColorConstants.SearchbarTintBlue
27 27
28 return obj 28 return obj
29 }() 29 }()
@@ -53,7 +53,7 @@ final class TabsView: UIView { @@ -53,7 +53,7 @@ final class TabsView: UIView {
53 } 53 }
54 tabsToolbarView.snp.makeConstraints { make in 54 tabsToolbarView.snp.makeConstraints { make in
55 make.leading.equalToSuperview() 55 make.leading.equalToSuperview()
56 - make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom) 56 + make.bottom.equalToSuperview()
57 make.trailing.equalToSuperview() 57 make.trailing.equalToSuperview()
58 } 58 }
59 } 59 }
@@ -8,32 +8,34 @@ @@ -8,32 +8,34 @@
8 import UIKit 8 import UIKit
9 9
10 final class NavigationViewController: UINavigationController { 10 final class NavigationViewController: UINavigationController {
  11 +
11 override func viewDidLoad() { 12 override func viewDidLoad() {
12 super.viewDidLoad() 13 super.viewDidLoad()
  14 +
13 initViewController() 15 initViewController()
14 } 16 }
15 17
16 private func initViewController() { 18 private func initViewController() {
17 - setStartControllers()  
18 - view.backgroundColor = .blue 19 + view.backgroundColor = .black
19 delegate = self 20 delegate = self
  21 +
  22 + setStartControllers()
20 } 23 }
21 } 24 }
22 25
23 // MARK: - Helpers 26 // MARK: - Helpers
24 extension NavigationViewController { 27 extension NavigationViewController {
25 private func setStartControllers() { 28 private func setStartControllers() {
26 - let tabsViewController = TabsViewController()  
27 - let browserHomeViewController = BrowserHomeViewController(url: nil, currentTabId: nil)  
28 let payloadViewController = PayloadViewController() 29 let payloadViewController = PayloadViewController()
  30 + let removeAdvertViewController = RemoveAdvertViewController()
29 let cachingManager = CachingManager.shared 31 let cachingManager = CachingManager.shared
  32 +
30 if cachingManager.isFirstAppLoad == false { 33 if cachingManager.isFirstAppLoad == false {
31 - setViewControllers([tabsViewController, browserHomeViewController, payloadViewController], animated: true) 34 + setViewControllers([removeAdvertViewController, payloadViewController], animated: true)
32 cachingManager.isFirstAppLoad.toggle() 35 cachingManager.isFirstAppLoad.toggle()
33 } else { 36 } else {
34 - setViewControllers([tabsViewController, browserHomeViewController], animated: true) 37 + setViewControllers([removeAdvertViewController], animated: true)
35 } 38 }
36 -  
37 } 39 }
38 } 40 }
39 41
@@ -50,6 +52,13 @@ extension NavigationViewController: UINavigationControllerDelegate { @@ -50,6 +52,13 @@ extension NavigationViewController: UINavigationControllerDelegate {
50 if (fromVC is TabsViewController && toVC is BrowserHomeViewController) { 52 if (fromVC is TabsViewController && toVC is BrowserHomeViewController) {
51 return OpenTabsTransition(operation: operation) 53 return OpenTabsTransition(operation: operation)
52 } 54 }
  55 +
  56 + if (fromVC is RemoveAdvertViewController && toVC is BrowserHomeViewController) {
  57 + return OpenBrowserHomeTransition(operation: operation)
  58 + }
  59 + if (fromVC is BrowserHomeViewController && toVC is RemoveAdvertViewController) {
  60 + return OpenBrowserHomeTransition(operation: operation)
  61 + }
53 return nil 62 return nil
54 } 63 }
55 } 64 }
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>adBlocker</key>
  6 + <string>com.browser.adblocker</string>
  7 +</dict>
  8 +</plist>
@@ -9,7 +9,13 @@ import UIKit @@ -9,7 +9,13 @@ import UIKit
9 9
10 struct ColorConstants { 10 struct ColorConstants {
11 static let lightGray = UIColor(red: 0.984, green: 0.984, blue: 0.984, alpha: 1) 11 static let lightGray = UIColor(red: 0.984, green: 0.984, blue: 0.984, alpha: 1)
12 - static let gray = UIColor(red: 0.62, green: 0.62, blue: 0.62, alpha: 1) 12 + static let SearchbarTintBlue = UIColor(red: 0.35, green: 0.56, blue: 1, alpha: 1)
13 static let payloadTextColor = UIColor(red: 0.121, green: 0.121, blue: 0.121, alpha: 1) 13 static let payloadTextColor = UIColor(red: 0.121, green: 0.121, blue: 0.121, alpha: 1)
14 static let buttonsBackgroundColor = UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 1) 14 static let buttonsBackgroundColor = UIColor(red: 0.349, green: 0.565, blue: 1, alpha: 1)
  15 + static let customLightBlue = UIColor(red: 0.8, green: 0.87, blue: 1, alpha: 1)
  16 +
  17 + static let customPink = UIColor(red: 0.95, green: 0.47, blue: 0.71, alpha: 1)
  18 + static let customPinkForText = UIColor(red: 0.99, green: 0.87, blue: 0.93, alpha: 1)
  19 +
  20 + static let segmentControlBackground = UIColor(red: 0.938, green: 0.938, blue: 0.962, alpha: 0.1)
15 } 21 }
@@ -15,6 +15,7 @@ struct FontConstants { @@ -15,6 +15,7 @@ struct FontConstants {
15 static let regularFont_12 = UIFont(name: "SFProText-Regular", size: 12.sizeW) 15 static let regularFont_12 = UIFont(name: "SFProText-Regular", size: 12.sizeW)
16 16
17 //SFProText-Semibold 17 //SFProText-Semibold
  18 + static let semiboldFont_24 = UIFont(name: "SFProText-Semibold", size: 24.sizeW)
18 static let semiboldFont_18 = UIFont(name: "SFProText-Semibold", size: 18.sizeW) 19 static let semiboldFont_18 = UIFont(name: "SFProText-Semibold", size: 18.sizeW)
19 static let semiboldFont_17 = UIFont(name: "SFProText-Semibold", size: 17.sizeW) 20 static let semiboldFont_17 = UIFont(name: "SFProText-Semibold", size: 17.sizeW)
20 static let semiboldFont_15 = UIFont(name: "SFProText-Semibold", size: 15.sizeW) 21 static let semiboldFont_15 = UIFont(name: "SFProText-Semibold", size: 15.sizeW)
@@ -27,7 +27,7 @@ struct StringConstants { @@ -27,7 +27,7 @@ struct StringConstants {
27 "https://github.com/" ] 27 "https://github.com/" ]
28 28
29 ///SettingView 29 ///SettingView
30 - static let settingViewControllerTableViewData = ["Privacy policy", "Terms and condition", "Share app", "Rate app", "Support"] 30 + static let settingViewControllerTableViewData = ["Privacy policy", "Terms and condition", "Share app", "Rate app", "Support", "Restore"]
31 static let removeAdvertTableViewData = ["Unlimited blocks & uploads", "Enhanced User Experience", "Faster Page Load Times", "Privacy and Security"] 31 static let removeAdvertTableViewData = ["Unlimited blocks & uploads", "Enhanced User Experience", "Faster Page Load Times", "Privacy and Security"]
32 static let search = "Search" 32 static let search = "Search"
33 33
@@ -42,20 +42,21 @@ struct StringConstants { @@ -42,20 +42,21 @@ struct StringConstants {
42 static let turnOff = "Tap to turn off" 42 static let turnOff = "Tap to turn off"
43 static let turnOn = "Tap to turn on" 43 static let turnOn = "Tap to turn on"
44 44
45 -  
46 - ///Cell reuse identifiers  
47 - static let historyTableViewCell = "HistoryTableViewCell"  
48 - static let searchTableViewCell = "SearchingTableViewCell"  
49 - static let removeAdvertTableViewCell = "RemoveAdvertTableViewCell"  
50 - static let settingTableViewCell = "SettingTableViewCell"  
51 - static let advantagesTableViewCell = "AdvantagesTableViewCell"  
52 -  
53 ///setting cell detail info 45 ///setting cell detail info
54 - static let settingTerms = "Thank you for choosing VPN Proxy Master.\n\n We will collect only the minimum data required to offer you a safe and stable VPN experience. For your convenience, hereby enclosed are the bullet points of data collected by us:\n\n · Device’s System Language which we do not retain. This is for settings the in-app language.\n\n · IP address and System Country which we do not retain. Your IP information is only used to provide you with the fastest default server list.\n\n We will strictly follow our no-logs policy and relevant data privacy laws, and will try our best to protect your privacy and security.\n\n For more information, please read our Terms and Service and Privacy Policy." 46 + static let settingPolicy = "GoToWeb Safe Browser Privacy Policy\nCreative Tech LLC built the GoToWeb Safe Browser app as a Commercial app. This SERVICE is provided by Creative Tech LLC and is intended for use as is.\n\nThis page is used to inform visitors regarding our policies with the collection, use, and disclosure of Personal Information if anyone decided to use our Service.\n\nIf you choose to use our Service, then you agree to the collection and use of information in relation to this policy. The Personal Information that we collect is used for providing and improving the Service. We will not use or share your information with anyone except as described in this Privacy Policy.\n\nThe terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, which are accessible at GoToWeb Safe Browser unless otherwise defined in this Privacy Policy.\n\nInformation Collection and Use\n\nFor a better experience, while using our Service, we may require you to provide us with certain personally identifiable information. The information that we request will be retained by us and used as described in this privacy policy.\n\nThe app does use third-party services that may collect information used to identify you.\n\nLink to the privacy policy of third-party service providers used by the app\n\nGoogle Analytics for Firebase\nFirebase Crashlytics\nFacebook\nUnity\nAppLovin\n\nLog Data\n\nWe want to inform you that whenever you use our Service, in a case of an error in the app we collect data and information (through third-party products) on your phone called Log Data. This Log Data may include information such as your device Internet Protocol (“IP”) address, device name, operating system version, the configuration of the app when utilizing our Service, the time and date of your use of the Service, and other statistics.\n\nCookies\n\nCookies are files with a small amount of data that are commonly used as anonymous unique identifiers. These are sent to your browser from the websites that you visit and are stored on your device's internal memory.\n\nThis Service does not use these “cookies” explicitly. However, the app may use third-party code and libraries that use “cookies” to collect information and improve their services. You have the option to either accept or refuse these cookies and know when a cookie is being sent to your device. If you choose to refuse our cookies, you may not be able to use some portions of this Service.\n\nService Providers\n\nWe may employ third-party companies and individuals due to the following reasons:\n\nTo facilitate our Service;\nTo provide the Service on our behalf;\nTo perform Service-related services; or\nTo assist us in analyzing how our Service is used.\nWe want to inform users of this Service that these third parties have access to their Personal Information. The reason is to perform the tasks assigned to them on our behalf. However, they are obligated not to disclose or use the information for any other purpose.\n\nSecurity\n\nWe value your trust in providing us your Personal Information, thus we are striving to use commercially acceptable means of protecting it. But remember that no method of transmission over the internet, or method of electronic storage is 100% secure and reliable, and we cannot guarantee its absolute security.\n\nLinks to Other Sites\n\nThis Service may contain links to other sites. If you click on a third-party link, you will be directed to that site. Note that these external sites are not operated by us. Therefore, we strongly advise you to review the Privacy Policy of these websites. We have no control over and assume no responsibility for the content, privacy policies, or practices of any third-party sites or services.\n\nChildren’s Privacy\n\nThese Services do not address anyone under the age of 13. We do not knowingly collect personally identifiable information from children under 13 years of age. In the case we discover that a child under 13 has provided us with personal information, we immediately delete this from our servers. If you are a parent or guardian and you are aware that your child has provided us with personal information, please contact us so that we will be able to do the necessary actions.\n\nChanges to This Privacy Policy\n\nWe may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. We will notify you of any changes by posting the new Privacy Policy on this page.\n\nThis policy is effective as of 2023-11-24\n\nContact Us\n\nIf you have any questions or suggestions about our Privacy Policy, do not hesitate to contact us at creattechllc@gmail.com.\n\n\n"
  47 +
  48 +
  49 + static let settingTerms = "GoToWeb safe browser Terms & Conditions\nBy downloading or using the app, these terms will automatically apply to you – you should make sure therefore that you read them carefully before using the app. You’re not allowed to copy or modify the app, any part of the app, or our trademarks in any way. You’re not allowed to attempt to extract the source code of the app, and you also shouldn’t try to translate the app into other languages or make derivative versions. The app itself, and all the trademarks, copyright, database rights, and other intellectual property rights related to it, still belong to Creative Tech LLC.\n\nCreative Tech LLC is committed to ensuring that the app is as useful and efficient as possible. For that reason, we reserve the right to make changes to the app or to charge for its services, at any time and for any reason. We will never charge you for the app or its services without making it very clear to you exactly what you’re paying for.\n\nThe GoToWeb safe browser app stores and processes personal data that you have provided to us, to provide our Service. It’s your responsibility to keep your phone and access to the app secure. We therefore recommend that you do not jailbreak or root your phone, which is the process of removing software restrictions and limitations imposed by the official operating system of your device. It could make your phone vulnerable to malware/viruses/malicious programs, compromise your phone’s security features and it could mean that the GoToWeb safe browser app won’t work properly or at all.\n\nThe app does use third-party services that declare their Terms and Conditions.\n\nLink to Terms and Conditions of third-party service providers used by the app\n\nGoogle Analytics for Firebase\nFirebase Crashlytics\nFacebook\nUnity\nAppLovin\n\nYou should be aware that there are certain things that Creative Tech LLC will not take responsibility for. Certain functions of the app will require the app to have an active internet connection. The connection can be Wi-Fi or provided by your mobile network provider, but Creative Tech LLC cannot take responsibility for the app not working at full functionality if you don’t have access to Wi-Fi, and you don’t have any of your data allowance left.\n\nIf you’re using the app outside of an area with Wi-Fi, you should remember that the terms of the agreement with your mobile network provider will still apply. As a result, you may be charged by your mobile provider for the cost of data for the duration of the connection while accessing the app, or other third-party charges. In using the app, you’re accepting responsibility for any such charges, including roaming data charges if you use the app outside of your home territory (i.e. region or country) without turning off data roaming. If you are not the bill payer for the device on which you’re using the app, please be aware that we assume that you have received permission from the bill payer for using the app.\n\nAlong the same lines, Creative Tech LLC cannot always take responsibility for the way you use the app i.e. You need to make sure that your device stays charged – if it runs out of battery and you can’t turn it on to avail the Service, Creative Tech LLC cannot accept responsibility.\n\nWith respect to Creative Tech LLC’s responsibility for your use of the app, when you’re using the app, it’s important to bear in mind that although we endeavor to ensure that it is updated and correct at all times, we do rely on third parties to provide information to us so that we can make it available to you. Creative Tech LLC accepts no liability for any loss, direct or indirect, you experience as a result of relying wholly on this functionality of the app.\n\nAt some point, we may wish to update the app. The app is currently available on iOS – the requirements for the system(and for any additional systems we decide to extend the availability of the app to) may change, and you’ll need to download the updates if you want to keep using the app. Creative Tech LLC does not promise that it will always update the app so that it is relevant to you and/or works with the iOS version that you have installed on your device. However, you promise to always accept updates to the application when offered to you, We may also wish to stop providing the app, and may terminate use of it at any time without giving notice of termination to you. Unless we tell you otherwise, upon any termination, (a) the rights and licenses granted to you in these terms will end; (b) you must stop using the app, and (if needed) delete it from your device.\n\nChanges to This Terms and Conditions\n\nWe may update our Terms and Conditions from time to time. Thus, you are advised to review this page periodically for any changes. We will notify you of any changes by posting the new Terms and Conditions on this page.\n\nThese terms and conditions are effective as of 2023-11-24\n\nContact Us\n\nIf you have any questions or suggestions about our Terms and Conditions, do not hesitate to contact us at creattechllc@gmail.com \n\n\n"
  50 +
  51 +
55 static let settingHeader = "Terms\nand conditions" 52 static let settingHeader = "Terms\nand conditions"
56 static let settingAgreeButtonText = "Agree & Continue" 53 static let settingAgreeButtonText = "Agree & Continue"
57 static let privacyHeaderText = "Your Privacy\n is our top priority" 54 static let privacyHeaderText = "Your Privacy\n is our top priority"
58 55
59 static let menuTitle = "Clearing will remove history, cookies and other browsing data. History will be cleared from devices signed into your iCloud Account. Clear from:" 56 static let menuTitle = "Clearing will remove history, cookies and other browsing data. History will be cleared from devices signed into your iCloud Account. Clear from:"
  57 +
  58 + //mainView labels
  59 + static let adBlockProtectFrom = "Adblock will protect you from:"
  60 + static let tableViewData = ["Harmful ads", "Phishing sites", "Ads in video"]
60 } 61 }
61 62
1 { 1 {
2 "images" : [ 2 "images" : [
3 { 3 {
4 - "filename" : "Image.png",  
5 - "idiom" : "universal",  
6 - "scale" : "1x"  
7 - },  
8 - {  
9 - "idiom" : "universal",  
10 - "scale" : "2x"  
11 - },  
12 - {  
13 - "idiom" : "universal",  
14 - "scale" : "3x" 4 + "filename" : "936 1.pdf",
  5 + "idiom" : "universal"
15 } 6 }
16 ], 7 ],
17 "info" : { 8 "info" : {
1 { 1 {
2 "images" : [ 2 "images" : [
3 { 3 {
4 - "filename" : "Image.png",  
5 - "idiom" : "universal",  
6 - "scale" : "1x"  
7 - },  
8 - {  
9 - "idiom" : "universal",  
10 - "scale" : "2x"  
11 - },  
12 - {  
13 - "idiom" : "universal",  
14 - "scale" : "3x" 4 + "filename" : "0.1. splash.png",
  5 + "idiom" : "universal"
15 } 6 }
16 ], 7 ],
17 "info" : { 8 "info" : {
1 { 1 {
2 "images" : [ 2 "images" : [
3 { 3 {
4 - "filename" : "github.png",  
5 - "idiom" : "universal",  
6 - "scale" : "1x"  
7 - },  
8 - {  
9 - "idiom" : "universal",  
10 - "scale" : "2x"  
11 - },  
12 - {  
13 - "idiom" : "universal",  
14 - "scale" : "3x" 4 + "filename" : "Frame.pdf",
  5 + "idiom" : "universal"
15 } 6 }
16 ], 7 ],
17 "info" : { 8 "info" : {
1 { 1 {
2 "images" : [ 2 "images" : [
3 { 3 {
4 - "filename" : "gmail.png",  
5 - "idiom" : "universal",  
6 - "scale" : "1x"  
7 - },  
8 - {  
9 - "idiom" : "universal",  
10 - "scale" : "2x"  
11 - },  
12 - {  
13 - "idiom" : "universal",  
14 - "scale" : "3x" 4 + "filename" : "Gmail.png",
  5 + "idiom" : "universal"
15 } 6 }
16 ], 7 ],
17 "info" : { 8 "info" : {
1 { 1 {
2 "images" : [ 2 "images" : [
3 { 3 {
4 - "filename" : "Image.png",  
5 - "idiom" : "universal",  
6 - "scale" : "1x"  
7 - },  
8 - {  
9 - "idiom" : "universal",  
10 - "scale" : "2x"  
11 - },  
12 - {  
13 - "idiom" : "universal",  
14 - "scale" : "3x" 4 + "filename" : "Linkedin.pdf``` 📎🔗 `Browser Design Figma.pdf",
  5 + "idiom" : "universal"
15 } 6 }
16 ], 7 ],
17 "info" : { 8 "info" : {
1 { 1 {
2 "images" : [ 2 "images" : [
3 { 3 {
4 - "filename" : "opera.png",  
5 - "idiom" : "universal",  
6 - "scale" : "1x"  
7 - },  
8 - {  
9 - "idiom" : "universal",  
10 - "scale" : "2x"  
11 - },  
12 - {  
13 - "idiom" : "universal",  
14 - "scale" : "3x" 4 + "filename" : "Browser Design.pdf",
  5 + "idiom" : "universal"
15 } 6 }
16 ], 7 ],
17 "info" : { 8 "info" : {
1 { 1 {
2 "images" : [ 2 "images" : [
3 { 3 {
4 - "filename" : "Gotoweb 1.png",  
5 - "idiom" : "universal",  
6 - "scale" : "1x"  
7 - },  
8 - {  
9 - "idiom" : "universal",  
10 - "scale" : "2x"  
11 - },  
12 - {  
13 - "idiom" : "universal",  
14 - "scale" : "3x"  
15 - },  
16 - {  
17 - "filename" : "Gotoweb.png",  
18 - "idiom" : "iphone",  
19 - "scale" : "1x"  
20 - },  
21 - {  
22 - "idiom" : "iphone",  
23 - "scale" : "2x"  
24 - },  
25 - {  
26 - "idiom" : "iphone",  
27 - "scale" : "3x" 4 + "filename" : "Logo browser 2gotoweb.pdf",
  5 + "idiom" : "universal"
28 } 6 }
29 ], 7 ],
30 "info" : { 8 "info" : {
31 "author" : "xcode", 9 "author" : "xcode",
32 "version" : 1 10 "version" : 1
  11 + },
  12 + "properties" : {
  13 + "preserves-vector-representation" : true,
  14 + "template-rendering-intent" : "original"
33 } 15 }
34 } 16 }
1 { 1 {
2 "images" : [ 2 "images" : [
3 { 3 {
4 - "filename" : "Image.png",  
5 - "idiom" : "universal",  
6 - "scale" : "1x"  
7 - },  
8 - {  
9 - "idiom" : "universal",  
10 - "scale" : "2x"  
11 - },  
12 - {  
13 - "idiom" : "universal",  
14 - "scale" : "3x" 4 + "filename" : "Phone.png",
  5 + "idiom" : "universal"
15 } 6 }
16 ], 7 ],
17 "info" : { 8 "info" : {
1 { 1 {
2 "images" : [ 2 "images" : [
3 { 3 {
4 - "filename" : "Image.png",  
5 - "idiom" : "universal",  
6 - "scale" : "1x"  
7 - },  
8 - {  
9 - "idiom" : "universal",  
10 - "scale" : "2x"  
11 - },  
12 - {  
13 - "idiom" : "universal",  
14 - "scale" : "3x" 4 + "filename" : "ZoomedTab.png",
  5 + "idiom" : "universal"
15 } 6 }
16 ], 7 ],
17 "info" : { 8 "info" : {
1 { 1 {
2 "images" : [ 2 "images" : [
3 { 3 {
4 - "filename" : "Image.png",  
5 - "idiom" : "universal",  
6 - "scale" : "1x"  
7 - },  
8 - {  
9 - "idiom" : "universal",  
10 - "scale" : "2x"  
11 - },  
12 - {  
13 - "idiom" : "universal",  
14 - "scale" : "3x" 4 + "filename" : "Group 1adBlockButtonOff.pdf",
  5 + "idiom" : "universal"
15 } 6 }
16 ], 7 ],
17 "info" : { 8 "info" : {
1 { 1 {
2 "images" : [ 2 "images" : [
3 { 3 {
4 - "filename" : "Image.png",  
5 - "idiom" : "universal",  
6 - "scale" : "1x"  
7 - },  
8 - {  
9 - "idiom" : "universal",  
10 - "scale" : "2x"  
11 - },  
12 - {  
13 - "idiom" : "universal",  
14 - "scale" : "3x" 4 + "filename" : "Group 1.png",
  5 + "idiom" : "universal"
15 } 6 }
16 ], 7 ],
17 "info" : { 8 "info" : {
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
1 { 1 {
2 "images" : [ 2 "images" : [
3 { 3 {
4 - "filename" : "Image.png",  
5 - "idiom" : "universal",  
6 - "scale" : "1x"  
7 - },  
8 - {  
9 - "idiom" : "universal",  
10 - "scale" : "2x"  
11 - },  
12 - {  
13 - "idiom" : "universal",  
14 - "scale" : "3x" 4 + "filename" : "kisspng-technology-stock-photography-illustration-tech-point-basemap-5a6d4b9cd23b12 2.pdf",
  5 + "idiom" : "universal"
15 } 6 }
16 ], 7 ],
17 "info" : { 8 "info" : {
1 { 1 {
2 "images" : [ 2 "images" : [
3 { 3 {
4 - "filename" : "Image.png",  
5 - "idiom" : "universal",  
6 - "scale" : "1x"  
7 - },  
8 - {  
9 - "idiom" : "universal",  
10 - "scale" : "2x"  
11 - },  
12 - {  
13 - "idiom" : "universal",  
14 - "scale" : "3x" 4 + "filename" : "kisspng-technology-stock-photography-illustration-tech-point-basemap-5a6d4b9cd23b12 1.png",
  5 + "idiom" : "universal"
15 } 6 }
16 ], 7 ],
17 "info" : { 8 "info" : {
Please register or login to post a comment