Commit 6306e3dda49a4362c0c8505df2e64b64e4f3398c

Authored by Artem Talko
1 parent f1aa2730

subscription added + redesign + fixed tabs open

Showing 106 changed files with 2462 additions and 571 deletions
No preview for this file type
... ... @@ -27,14 +27,23 @@
27 27 191BB87F2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB87E2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift */; };
28 28 191BB8812AC6FF6600A2DEB9 /* RemoveAdvertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 191BB8802AC6FF6600A2DEB9 /* RemoveAdvertView.swift */; };
29 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 31 193B3B832ACAF394002161ED /* BrowserTabDataBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 193B3B822ACAF394002161ED /* BrowserTabDataBase.swift */; };
31 32 193B3B862ACAF480002161ED /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = 193B3B852ACAF480002161ED /* Realm */; };
32 33 193B3B882ACAF480002161ED /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 193B3B872ACAF480002161ED /* RealmSwift */; };
33 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 37 194635D62ADD738E00993D91 /* HistoryDataBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194635D52ADD738E00993D91 /* HistoryDataBase.swift */; };
35 38 19696AF52AE80DBD00D1F8F9 /* blockerList.json in Resources */ = {isa = PBXBuildFile; fileRef = 19696AF42AE80DBD00D1F8F9 /* blockerList.json */; };
36 39 19696AF72AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19696AF62AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift */; };
37 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 47 197FC3EF2AC21E1F007F429C /* PayloadViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3EE2AC21E1F007F429C /* PayloadViewController.swift */; };
39 48 197FC3F22AC2AF9A007F429C /* AdvantagesTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3F12AC2AF9A007F429C /* AdvantagesTableViewCell.swift */; };
40 49 197FC3F42AC2BCD7007F429C /* SearchBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 197FC3F32AC2BCD7007F429C /* SearchBarView.swift */; };
... ... @@ -57,8 +66,8 @@
57 66 19B739712AE157900073AA59 /* FontConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B739702AE157900073AA59 /* FontConstants.swift */; };
58 67 19B739732AE15B3B0073AA59 /* ColorConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B739722AE15B3B0073AA59 /* ColorConstants.swift */; };
59 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 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 71 19C7A70E2AC9F5FD00B954FC /* HistorySearchBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19C7A70D2AC9F5FD00B954FC /* HistorySearchBarView.swift */; };
63 72 19CD89482AC719AC0035CB55 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 19CD89472AC719AC0035CB55 /* SnapKit */; };
64 73 19D1F2E02AC1EF3200510506 /* PayloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19D1F2DF2AC1EF3200510506 /* PayloadView.swift */; };
... ... @@ -119,13 +128,23 @@
119 128 191BB87E2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryToolbarView.swift; sourceTree = "<group>"; };
120 129 191BB8802AC6FF6600A2DEB9 /* RemoveAdvertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveAdvertView.swift; sourceTree = "<group>"; };
121 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 133 193B3B822ACAF394002161ED /* BrowserTabDataBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserTabDataBase.swift; sourceTree = "<group>"; };
123 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 137 194635D52ADD738E00993D91 /* HistoryDataBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryDataBase.swift; sourceTree = "<group>"; };
125 138 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = AdBlocker.appex; sourceTree = BUILT_PRODUCTS_DIR; };
126 139 19696AF42AE80DBD00D1F8F9 /* blockerList.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = blockerList.json; sourceTree = "<group>"; };
127 140 19696AF62AE80DBD00D1F8F9 /* ContentBlockerRequestHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentBlockerRequestHandler.swift; sourceTree = "<group>"; };
128 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 148 197FC3EE2AC21E1F007F429C /* PayloadViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayloadViewController.swift; sourceTree = "<group>"; };
130 149 197FC3F12AC2AF9A007F429C /* AdvantagesTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvantagesTableViewCell.swift; sourceTree = "<group>"; };
131 150 197FC3F32AC2BCD7007F429C /* SearchBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBarView.swift; sourceTree = "<group>"; };
... ... @@ -147,13 +166,13 @@
147 166 19B739702AE157900073AA59 /* FontConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontConstants.swift; sourceTree = "<group>"; };
148 167 19B739722AE15B3B0073AA59 /* ColorConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorConstants.swift; sourceTree = "<group>"; };
149 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 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 171 19C7A70D2AC9F5FD00B954FC /* HistorySearchBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistorySearchBarView.swift; sourceTree = "<group>"; };
153 172 19D1F2DF2AC1EF3200510506 /* PayloadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayloadView.swift; sourceTree = "<group>"; };
154 173 19EECA442ACED45A00094AFB /* SearchResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultView.swift; sourceTree = "<group>"; };
155 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 176 19FCBF212AC1727800F83A7F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
158 177 19FCBF252AC1727800F83A7F /* BrowserHomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHomeViewController.swift; sourceTree = "<group>"; };
159 178 19FCBF2A2AC1727900F83A7F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
... ... @@ -178,6 +197,7 @@
178 197 files = (
179 198 193B3B882ACAF480002161ED /* RealmSwift in Frameworks */,
180 199 199DB1F12AD3FDEE007E6A81 /* Alamofire in Frameworks */,
  200 + 192BC8202B16173700A8A426 /* StoreKit.framework in Frameworks */,
181 201 193B3B862ACAF480002161ED /* Realm in Frameworks */,
182 202 19CD89482AC719AC0035CB55 /* SnapKit in Frameworks */,
183 203 );
... ... @@ -198,7 +218,8 @@
198 218 190DB9F82AC44FD4000A7BF3 /* View */ = {
199 219 isa = PBXGroup;
200 220 children = (
201   - 19C7A70A2AC9EB9B00B954FC /* Cell */,
  221 + 194206C62B10DFAF000C1263 /* Cell */,
  222 + 197C2A222B0E3A420010B386 /* Components */,
202 223 191BB8802AC6FF6600A2DEB9 /* RemoveAdvertView.swift */,
203 224 );
204 225 path = View;
... ... @@ -215,6 +236,7 @@
215 236 190DB9FD2AC459CD000A7BF3 /* Managers */ = {
216 237 isa = PBXGroup;
217 238 children = (
  239 + 197C2A2C2B0F9EEB0010B386 /* StoreKitManager.swift */,
218 240 190DB9FF2AC45A3C000A7BF3 /* CachingManager.swift */,
219 241 193B3B892ACAF714002161ED /* TabManager.swift */,
220 242 1907D6962ADE766F00C40E9F /* HistoryDBManager.swift */,
... ... @@ -373,6 +395,14 @@
373 395 path = Components;
374 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 406 193B3B812ACAF36C002161ED /* DataBases */ = {
377 407 isa = PBXGroup;
378 408 children = (
... ... @@ -382,6 +412,14 @@
382 412 path = DataBases;
383 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 423 19696AF32AE80DBD00D1F8F9 /* AdBlocker */ = {
386 424 isa = PBXGroup;
387 425 children = (
... ... @@ -391,6 +429,48 @@
391 429 path = AdBlocker;
392 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 474 197FC3F02AC2AF8A007F429C /* Cell */ = {
395 475 isa = PBXGroup;
396 476 children = (
... ... @@ -555,12 +635,12 @@
555 635 path = Models;
556 636 sourceTree = "<group>";
557 637 };
558   - 19C7A70A2AC9EB9B00B954FC /* Cell */ = {
  638 + 19C33E972B0DF8FA006BFD72 /* ReusableElements */ = {
559 639 isa = PBXGroup;
560 640 children = (
561   - 19C7A70B2AC9EBB800B954FC /* RemoveAdvertTableViewCell.swift */,
  641 + 19C33E982B0DF91D006BFD72 /* GradientView.swift */,
562 642 );
563   - path = Cell;
  643 + path = ReusableElements;
564 644 sourceTree = "<group>";
565 645 };
566 646 19D1F2DC2AC1EE6200510506 /* Payload */ = {
... ... @@ -621,6 +701,7 @@
621 701 isa = PBXGroup;
622 702 children = (
623 703 1989A15F2AE29D4B00292680 /* OpenTabsTransition.swift */,
  704 + 197C2A272B0F65830010B386 /* OpenBrowserHomeTransition.swift */,
624 705 );
625 706 path = Transitions;
626 707 sourceTree = "<group>";
... ... @@ -628,16 +709,18 @@
628 709 19FCBF152AC1727800F83A7F = {
629 710 isa = PBXGroup;
630 711 children = (
  712 + 192BC8212B16326B00A8A426 /* StoreKitSubscription.storekit */,
631 713 19FCBF202AC1727800F83A7F /* browser */,
632 714 19696AF32AE80DBD00D1F8F9 /* AdBlocker */,
633 715 19FCBF1F2AC1727800F83A7F /* Products */,
  716 + 192BC81E2B16173700A8A426 /* Frameworks */,
634 717 );
635 718 sourceTree = "<group>";
636 719 };
637 720 19FCBF1F2AC1727800F83A7F /* Products */ = {
638 721 isa = PBXGroup;
639 722 children = (
640   - 19FCBF1E2AC1727800F83A7F /* browser.app */,
  723 + 19FCBF1E2AC1727800F83A7F /* Pro-Seecurity-VPN.app */,
641 724 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */,
642 725 );
643 726 name = Products;
... ... @@ -657,6 +740,7 @@
657 740 19FCBF352AC1779800F83A7F /* Navigation */,
658 741 19FCBF212AC1727800F83A7F /* AppDelegate.swift */,
659 742 19FCBF2F2AC1727900F83A7F /* Info.plist */,
  743 + 194206C42B10D267000C1263 /* ProductList.plist */,
660 744 );
661 745 path = browser;
662 746 sourceTree = "<group>";
... ... @@ -672,6 +756,8 @@
672 756 19FCBF382AC17A4800F83A7F /* Modules */ = {
673 757 isa = PBXGroup;
674 758 children = (
  759 + 197534722B10965F000818D3 /* Subscription */,
  760 + 19C33E972B0DF8FA006BFD72 /* ReusableElements */,
675 761 19B2D0AF2ACDEAB600D20CE8 /* SearchResult */,
676 762 191BB8702AC6B19F00A2DEB9 /* History */,
677 763 191BB85D2AC69FC800A2DEB9 /* Searching */,
... ... @@ -739,9 +825,9 @@
739 825 productReference = 19696AF22AE80DBC00D1F8F9 /* AdBlocker.appex */;
740 826 productType = "com.apple.product-type.app-extension";
741 827 };
742   - 19FCBF1D2AC1727800F83A7F /* browser */ = {
  828 + 19FCBF1D2AC1727800F83A7F /* Pro-Seecurity-VPN */ = {
743 829 isa = PBXNativeTarget;
744   - buildConfigurationList = 19FCBF322AC1727900F83A7F /* Build configuration list for PBXNativeTarget "browser" */;
  830 + buildConfigurationList = 19FCBF322AC1727900F83A7F /* Build configuration list for PBXNativeTarget "Pro-Seecurity-VPN" */;
745 831 buildPhases = (
746 832 19FCBF1A2AC1727800F83A7F /* Sources */,
747 833 19FCBF1B2AC1727800F83A7F /* Frameworks */,
... ... @@ -753,7 +839,7 @@
753 839 dependencies = (
754 840 19696AFA2AE80DBD00D1F8F9 /* PBXTargetDependency */,
755 841 );
756   - name = browser;
  842 + name = "Pro-Seecurity-VPN";
757 843 packageProductDependencies = (
758 844 19CD89472AC719AC0035CB55 /* SnapKit */,
759 845 193B3B852ACAF480002161ED /* Realm */,
... ... @@ -761,7 +847,7 @@
761 847 199DB1F02AD3FDEE007E6A81 /* Alamofire */,
762 848 );
763 849 productName = browser;
764   - productReference = 19FCBF1E2AC1727800F83A7F /* browser.app */;
  850 + productReference = 19FCBF1E2AC1727800F83A7F /* Pro-Seecurity-VPN.app */;
765 851 productType = "com.apple.product-type.application";
766 852 };
767 853 /* End PBXNativeTarget section */
... ... @@ -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 872 compatibilityVersion = "Xcode 14.0";
787 873 developmentRegion = en;
788 874 hasScannedForEncodings = 0;
... ... @@ -800,7 +886,7 @@
800 886 projectDirPath = "";
801 887 projectRoot = "";
802 888 targets = (
803   - 19FCBF1D2AC1727800F83A7F /* browser */,
  889 + 19FCBF1D2AC1727800F83A7F /* Pro-Seecurity-VPN */,
804 890 19696AF12AE80DBC00D1F8F9 /* AdBlocker */,
805 891 );
806 892 };
... ... @@ -819,6 +905,7 @@
819 905 isa = PBXResourcesBuildPhase;
820 906 buildActionMask = 2147483647;
821 907 files = (
  908 + 194206C52B10D267000C1263 /* ProductList.plist in Resources */,
822 909 1904ED472AC56BDB0035DB66 /* FontsFree-Net-SFProText-Semibold.ttf in Resources */,
823 910 19FCBF2E2AC1727900F83A7F /* LaunchScreen.storyboard in Resources */,
824 911 1904ED482AC56BDB0035DB66 /* FontsFree-Net-SFProText-Regular.ttf in Resources */,
... ... @@ -850,11 +937,15 @@
850 937 19FCBF262AC1727800F83A7F /* BrowserHomeViewController.swift in Sources */,
851 938 197FC3FF2AC30746007F429C /* SettingTableViewCell.swift in Sources */,
852 939 19B41DA12AD81A70002C0D31 /* SearchBarContainer.swift in Sources */,
  940 + 19C33E992B0DF91D006BFD72 /* GradientView.swift in Sources */,
853 941 19EECA452ACED45A00094AFB /* SearchResultView.swift in Sources */,
854 942 1907D6972ADE766F00C40E9F /* HistoryDBManager.swift in Sources */,
855 943 19B739762AE276360073AA59 /* HistoryElement.swift in Sources */,
  944 + 197534762B10968E000818D3 /* SubscriptionViewController.swift in Sources */,
856 945 197FC4032AC41EB7007F429C /* ToolbarView.swift in Sources */,
857 946 19B7396A2AE1554E0073AA59 /* URLConstants.swift in Sources */,
  947 + 197534782B1096A7000818D3 /* SubscriptionView.swift in Sources */,
  948 + 197C2A2D2B0F9EEB0010B386 /* StoreKitManager.swift in Sources */,
858 949 19EECA472ACED48000094AFB /* SearchResultViewController.swift in Sources */,
859 950 191BB8572AC5B4AC00A2DEB9 /* OpenedTabsCollectionViewCell.swift in Sources */,
860 951 190DB9FC2AC450F6000A7BF3 /* RemoveAdvertViewController.swift in Sources */,
... ... @@ -875,12 +966,14 @@
875 966 191BB8692AC6A66900A2DEB9 /* SearchingTableViewCell.swift in Sources */,
876 967 1990C69C2AEFDF89004AF856 /* UICollectionViewCell+convertFrameToScreenCoordinates.swift in Sources */,
877 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 971 19D1F2E02AC1EF3200510506 /* PayloadView.swift in Sources */,
880 972 19FFD6BF2AE64A7B00D0F768 /* SnapshotService.swift in Sources */,
881 973 190DBA0D2AC47701000A7BF3 /* BinaryFloatingPoint.swift in Sources */,
882 974 191BB8772AC6B47700A2DEB9 /* HistoryView.swift in Sources */,
883 975 19FCBF3D2AC17AB000F83A7F /* BrowserHomeView.swift in Sources */,
  976 + 194206C82B10DFC6000C1263 /* RemoveAdvertTableViewCell.swift in Sources */,
884 977 191BB87F2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift in Sources */,
885 978 1984BF582AFB970F0050F816 /* TermsViewController.swift in Sources */,
886 979 193B3B8A2ACAF714002161ED /* TabManager.swift in Sources */,
... ... @@ -890,6 +983,7 @@
890 983 1984BF5A2AFB973C0050F816 /* TermsView.swift in Sources */,
891 984 197FC3FC2AC2FBA0007F429C /* SettingView.swift in Sources */,
892 985 191BB8622AC6A01500A2DEB9 /* SearchingViewController.swift in Sources */,
  986 + 1975347B2B109A37000818D3 /* SubscriptionTableViewCell.swift in Sources */,
893 987 197FC4012AC31D5C007F429C /* NavigationViewController.swift in Sources */,
894 988 19C5F0572AD9784400133BD7 /* DataExtention+toImage.swift in Sources */,
895 989 1989A1602AE29D4C00292680 /* OpenTabsTransition.swift in Sources */,
... ... @@ -938,7 +1032,7 @@
938 1032 "@executable_path/../../Frameworks",
939 1033 );
940 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 1036 PRODUCT_NAME = "$(TARGET_NAME)";
943 1037 SKIP_INSTALL = YES;
944 1038 SWIFT_EMIT_LOC_STRINGS = YES;
... ... @@ -965,7 +1059,7 @@
965 1059 "@executable_path/../../Frameworks",
966 1060 );
967 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 1063 PRODUCT_NAME = "$(TARGET_NAME)";
970 1064 SKIP_INSTALL = YES;
971 1065 SWIFT_EMIT_LOC_STRINGS = YES;
... ... @@ -1107,18 +1201,21 @@
1107 1201 INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
1108 1202 INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
1109 1203 INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
1110   - INFOPLIST_KEY_UIUserInterfaceStyle = Light;
  1204 + INFOPLIST_KEY_UIUserInterfaceStyle = Dark;
1111 1205 IPHONEOS_DEPLOYMENT_TARGET = 15.0;
1112 1206 LD_RUNPATH_SEARCH_PATHS = (
1113 1207 "$(inherited)",
1114 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 1212 PRODUCT_NAME = "$(TARGET_NAME)";
  1213 + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
  1214 + SUPPORTS_MACCATALYST = NO;
  1215 + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
1119 1216 SWIFT_EMIT_LOC_STRINGS = YES;
1120 1217 SWIFT_VERSION = 5.0;
1121   - TARGETED_DEVICE_FAMILY = "1,2";
  1218 + TARGETED_DEVICE_FAMILY = 1;
1122 1219 };
1123 1220 name = Debug;
1124 1221 };
... ... @@ -1136,18 +1233,21 @@
1136 1233 INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
1137 1234 INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
1138 1235 INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
1139   - INFOPLIST_KEY_UIUserInterfaceStyle = Light;
  1236 + INFOPLIST_KEY_UIUserInterfaceStyle = Dark;
1140 1237 IPHONEOS_DEPLOYMENT_TARGET = 15.0;
1141 1238 LD_RUNPATH_SEARCH_PATHS = (
1142 1239 "$(inherited)",
1143 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 1244 PRODUCT_NAME = "$(TARGET_NAME)";
  1245 + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
  1246 + SUPPORTS_MACCATALYST = NO;
  1247 + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
1148 1248 SWIFT_EMIT_LOC_STRINGS = YES;
1149 1249 SWIFT_VERSION = 5.0;
1150   - TARGETED_DEVICE_FAMILY = "1,2";
  1250 + TARGETED_DEVICE_FAMILY = 1;
1151 1251 };
1152 1252 name = Release;
1153 1253 };
... ... @@ -1163,7 +1263,7 @@
1163 1263 defaultConfigurationIsVisible = 0;
1164 1264 defaultConfigurationName = Release;
1165 1265 };
1166   - 19FCBF192AC1727800F83A7F /* Build configuration list for PBXProject "browser" */ = {
  1266 + 19FCBF192AC1727800F83A7F /* Build configuration list for PBXProject "Pro-Seecurity-VPN" */ = {
1167 1267 isa = XCConfigurationList;
1168 1268 buildConfigurations = (
1169 1269 19FCBF302AC1727900F83A7F /* Debug */,
... ... @@ -1172,7 +1272,7 @@
1172 1272 defaultConfigurationIsVisible = 0;
1173 1273 defaultConfigurationName = Release;
1174 1274 };
1175   - 19FCBF322AC1727900F83A7F /* Build configuration list for PBXNativeTarget "browser" */ = {
  1275 + 19FCBF322AC1727900F83A7F /* Build configuration list for PBXNativeTarget "Pro-Seecurity-VPN" */ = {
1176 1276 isa = XCConfigurationList;
1177 1277 buildConfigurations = (
1178 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 7 <key>AdBlocker.xcscheme_^#shared#^_</key>
8 8 <dict>
9 9 <key>orderHint</key>
10   - <integer>0</integer>
  10 + <integer>1</integer>
11 11 </dict>
12 12 <key>GettingStarted (Playground) 1.xcscheme</key>
13 13 <dict>
14 14 <key>isShown</key>
15 15 <false/>
16 16 <key>orderHint</key>
17   - <integer>5</integer>
  17 + <integer>6</integer>
18 18 </dict>
19 19 <key>GettingStarted (Playground) 2.xcscheme</key>
20 20 <dict>
21 21 <key>isShown</key>
22 22 <false/>
23 23 <key>orderHint</key>
24   - <integer>6</integer>
  24 + <integer>7</integer>
25 25 </dict>
26 26 <key>GettingStarted (Playground).xcscheme</key>
27 27 <dict>
28 28 <key>isShown</key>
29 29 <false/>
30 30 <key>orderHint</key>
31   - <integer>2</integer>
  31 + <integer>3</integer>
32 32 </dict>
33 33 <key>SnapKitPlayground (Playground) 1.xcscheme</key>
34 34 <dict>
35 35 <key>isShown</key>
36 36 <false/>
37 37 <key>orderHint</key>
38   - <integer>3</integer>
  38 + <integer>4</integer>
39 39 </dict>
40 40 <key>SnapKitPlayground (Playground) 2.xcscheme</key>
41 41 <dict>
42 42 <key>isShown</key>
43 43 <false/>
44 44 <key>orderHint</key>
45   - <integer>4</integer>
  45 + <integer>5</integer>
46 46 </dict>
47 47 <key>SnapKitPlayground (Playground) 3.xcscheme</key>
48 48 <dict>
... ... @@ -70,12 +70,25 @@
70 70 <key>isShown</key>
71 71 <false/>
72 72 <key>orderHint</key>
73   - <integer>1</integer>
  73 + <integer>2</integer>
74 74 </dict>
75 75 <key>browser.xcscheme_^#shared#^_</key>
76 76 <dict>
77 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 92 </dict>
80 93 </dict>
81 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 5 var window: UIWindow?
6 6
7 7 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
8   -
9 8 let screenRect = UIScreen.main.bounds
10 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 10 final class OpenTabsTransition: NSObject, UIViewControllerAnimatedTransitioning {
11 11 private var operation: UINavigationController.Operation
12 12
13   - init( operation: UINavigationController.Operation ) {
  13 + init(operation: UINavigationController.Operation) {
14 14 self.operation = operation
  15 +
15 16 super.init()
16 17 }
17 18
18 19 func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
19   - return 0.4
  20 + return 0.6
20 21 }
21 22
22 23 func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
... ...
... ... @@ -2,6 +2,8 @@
2 2 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 3 <plist version="1.0">
4 4 <dict>
  5 + <key>ITSAppUsesNonExemptEncryption</key>
  6 + <false/>
5 7 <key>NSAppTransportSecurity</key>
6 8 <dict>
7 9 <key>NSAllowsArbitraryLoads</key>
... ...
... ... @@ -28,7 +28,7 @@ final class HistoryDBManager {
28 28 try realm.write {
29 29 realm.add(historyCell)
30 30 }
31   -
  31 +
32 32 } catch {
33 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 20 private let searchImageLogo: UIImageView = {
21 21 let obj = UIImageView()
22 22 obj.image = UIImage(systemName: "magnifyingglass")
23   - obj.tintColor = .gray
  23 + obj.tintColor = .white
24 24 obj.contentMode = .scaleAspectFit
  25 +
25 26 return obj
26 27 }()
27 28
28 29 private let lastVisitSiteLabel: UILabel = {
29 30 let obj = UILabel()
30 31 obj.font = FontConstants.regularFont_14
  32 +
31 33 return obj
32 34 }()
33 35
34 36 private let lastVisitSiteUrlLabel: UILabel = {
35 37 let obj = UILabel()
36   - obj.textColor = .gray
  38 + obj.textColor = .white
37 39 obj.font = FontConstants.regularFont_12
  40 +
38 41 return obj
39 42 }()
40 43
41 44 private let lastVisitDateLabel: UILabel = {
42 45 let obj = UILabel()
43 46 obj.font = FontConstants.regularFont_12
44   - obj.textColor = .gray
  47 + obj.textColor = .white
45 48 return obj
46 49 }()
47 50
... ... @@ -56,6 +59,7 @@ final class HistoryTableViewCell: UITableViewCell {
56 59 }
57 60
58 61 private func setup() {
  62 + self.backgroundColor = .clear
59 63 contentView.addSubview(searchImageLogo)
60 64 contentView.addSubview(lastVisitSiteLabel)
61 65 contentView.addSubview(lastVisitSiteUrlLabel)
... ...
... ... @@ -20,7 +20,7 @@ final class HistorySearchBarView: UIView {
20 20 let searchTextFieldView: UITextField = {
21 21 let obj = UITextField()
22 22 obj.text = StringConstants.search
23   - obj.textColor = ColorConstants.gray
  23 + obj.textColor = ColorConstants.SearchbarTintBlue
24 24
25 25 return obj
26 26 }()
... ...
... ... @@ -7,11 +7,11 @@
7 7
8 8 import UIKit
9 9
10   -final class HistoryView: UIView {
  10 +final class HistoryView: GradientView {
11 11 let historySearchBar: HistorySearchBarView = {
12 12 let obj = HistorySearchBarView()
13 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 16 return obj
17 17 }()
... ... @@ -19,13 +19,14 @@ final class HistoryView: UIView {
19 19 let historyTabsTableView: UITableView = {
20 20 let obj = UITableView()
21 21 obj.separatorStyle = .none
  22 + obj.backgroundColor = .clear
22 23
23 24 return obj
24 25 }()
25 26
26 27 let historyToolbarView: HistoryToolbarView = {
27 28 let obj = HistoryToolbarView()
28   -
  29 + obj.backgroundColor = ColorConstants.customLightBlue
29 30 return obj
30 31 }()
31 32
... ...
... ... @@ -16,7 +16,7 @@ final class BrowserHomeViewController: UIViewController {
16 16
17 17 private let searchingViewController: SearchingViewController
18 18 private let searchResultViewController: SearchResultViewController
19   - private let tabsViewController: TabsViewController
  19 + private var tabsViewController: TabsViewController?
20 20
21 21 private var subscriptions: Set<AnyCancellable>
22 22 private var searchRequestURL: String
... ... @@ -33,7 +33,6 @@ final class BrowserHomeViewController: UIViewController {
33 33 override func viewDidLoad() {
34 34 super.viewDidLoad()
35 35 view.backgroundColor = ColorConstants.lightGray
36   -
37 36 initViewController()
38 37 }
39 38
... ... @@ -51,6 +50,8 @@ final class BrowserHomeViewController: UIViewController {
51 50
52 51 override func viewIsAppearing(_ animated: Bool) {
53 52 navigationController?.isNavigationBarHidden = true
  53 +
  54 + tabsViewController = getTabsViewController()
54 55 }
55 56
56 57 override func loadView() {
... ... @@ -60,7 +61,9 @@ final class BrowserHomeViewController: UIViewController {
60 61 init(url: String?, currentTabId: Int?) {
61 62 searchResultViewController = SearchResultViewController(searchLink: String())
62 63 searchingViewController = SearchingViewController(dataForReq: [])
63   - tabsViewController = TabsViewController()
  64 +
  65 +
  66 +
64 67
65 68 subscriptions = []
66 69 searchRequestURL = URLConstants.googleURL
... ... @@ -169,9 +172,9 @@ extension BrowserHomeViewController {
169 172 }
170 173
171 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 180 @objc
... ... @@ -180,9 +183,18 @@ extension BrowserHomeViewController {
180 183 }
181 184 }
182 185
183   -
184 186 //MARK: - Helpers
185 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 198 private func didTabButtonTapped(type: ToolbarElementType) {
187 199 switch type {
188 200 case .history:
... ... @@ -222,7 +234,7 @@ extension BrowserHomeViewController {
222 234
223 235 private func addTargets() {
224 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 238 mainView.searchBarContainer.searchBarView.searchTextFieldView.addTarget(self, action: #selector(searchBarTextChanged), for: .editingChanged)
227 239 searchingViewController.mainView.searchingButton.addTarget(self, action: #selector(removeSearchingViewController(_ :)), for: .touchUpInside)
228 240 addToolbarTargets()
... ... @@ -261,7 +273,6 @@ extension BrowserHomeViewController {
261 273 private func tabsButtonHandler() {
262 274 if currentTabId == nil {
263 275 addNewTab()
264   - navigationController?.popViewController(animated: true)
265 276 } else {
266 277 updateCurrentTab()
267 278 }
... ... @@ -277,16 +288,20 @@ extension BrowserHomeViewController {
277 288 }
278 289 let finalUrl = siteUrl.absoluteString
279 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 297 HistoryDBManager.shared.saveToHistory(siteTitle: siteTitle, siteUrl: finalUrl, lastVisit: lastVisit)
  298 + navigationController?.popViewController(animated: true)
286 299 } else {
287 300 let homeViewSnapshot = SnapshotService.shared.makeSnapshot(mainView)
288 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 310 let chosenTab = allTabs[self.currentTabId ?? Int()]
296 311 let gottedCellId = chosenTab.tabId
297 312 let imageForUpdatedTab = SnapshotService.shared.makeSnapshot(self.mainView)
  313 +
298 314 if let childViewController = self.children.first as? SearchResultViewController {
299 315 guard let siteTitle = childViewController.mainView.searchResultView.title else {
300 316 return
... ...
... ... @@ -8,23 +8,19 @@
8 8 import UIKit
9 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 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 22 return obj
26 23 }()
27   -
28 24 let settingButton: UIButton = {
29 25 let obj = UIButton()
30 26 obj.setImage(UIImage(named: "Settings")?.withTintColor(.systemBlue), for: .normal)
... ... @@ -55,6 +51,7 @@ final class BrowserHomeView: UIView {
55 51
56 52 let toolbarView: ToolbarView = {
57 53 let obj = ToolbarView()
  54 + obj.backgroundColor = ColorConstants.customLightBlue
58 55
59 56 return obj
60 57 }()
... ... @@ -79,7 +76,7 @@ final class BrowserHomeView: UIView {
79 76 private func setup() {
80 77 addSubview(titleLabel)
81 78 addSubview(frequentlyVisitedCollectionView)
82   - addSubview(removeAddButton)
  79 + addSubview(removeAdvertSegmentControl)
83 80 addSubview(settingButton)
84 81 addSubview(searchBarContainer)
85 82 addSubview(toolbarView)
... ... @@ -88,19 +85,20 @@ final class BrowserHomeView: UIView {
88 85 }
89 86
90 87 private func setupConstraints() {
91   - removeAddButton.snp.makeConstraints { make in
  88 + removeAdvertSegmentControl.snp.makeConstraints { make in
92 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 94 settingButton.snp.makeConstraints { make in
97 95 make.trailing.equalToSuperview().offset(-16.sizeW)
98 96 make.height.equalTo(24.sizeH)
99 97 make.width.equalTo(24.sizeH)
100   - make.centerY.equalTo(removeAddButton)
  98 + make.centerY.equalTo(removeAdvertSegmentControl)
101 99 }
102 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 102 make.leading.equalTo(safeAreaLayoutGuide.snp.leading).offset(16.sizeW)
105 103 }
106 104 frequentlyVisitedCollectionView.snp.makeConstraints { make in
... ... @@ -110,7 +108,7 @@ final class BrowserHomeView: UIView {
110 108 }
111 109 toolbarView.snp.makeConstraints { make in
112 110 make.leading.equalToSuperview()
113   - make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom)
  111 + make.bottom.equalToSuperview()
114 112 make.trailing.equalToSuperview()
115 113 }
116 114 searchBarContainer.snp.makeConstraints { make in
... ... @@ -123,7 +121,7 @@ final class BrowserHomeView: UIView {
123 121
124 122 //MARK: - childView extension
125 123 extension BrowserHomeView {
126   - func addSearchView(_ childView: UIView){
  124 + func addSearchView(_ childView: UIView) {
127 125 addSubview(childView)
128 126
129 127 childView.snp.makeConstraints { make in
... ... @@ -138,7 +136,10 @@ extension BrowserHomeView {
138 136 extension BrowserHomeView {
139 137 func animateSearchBar(_ keyboardHeight: CGFloat) {
140 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 143 self.searchBarContainer.snp.updateConstraints { make in
143 144 make.leading.equalToSuperview()
144 145 make.trailing.equalToSuperview()
... ... @@ -150,7 +151,7 @@ extension BrowserHomeView {
150 151
151 152 func animateSearchBarDismiss() {
152 153 BrowserHomeView.animate(withDuration: 0.3) {
153   - self.searchBarContainer.backgroundColor = .clear
  154 + self.searchBarContainer.searchBarView.backgroundColor = ColorConstants.customLightBlue
154 155 self.searchBarContainer.snp.updateConstraints { make in
155 156 make.leading.equalToSuperview()
156 157 make.trailing.equalToSuperview()
... ...
... ... @@ -10,7 +10,7 @@ import UIKit
10 10 final class SearchBarContainer: UIView {
11 11 let searchBarView: SearchBarView = {
12 12 let obj = SearchBarView()
13   - obj.backgroundColor = .white
  13 + obj.backgroundColor = ColorConstants.customLightBlue
14 14 obj.layer.cornerRadius = 10
15 15 obj.layer.shadowColor = UIColor.black.withAlphaComponent(0.1).cgColor
16 16 obj.layer.shadowOpacity = 1
... ...
... ... @@ -10,7 +10,7 @@ import UIKit
10 10 final class SearchBarView: UIView {
11 11 private let searchImageView: UIImageView = {
12 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 14 obj.image = magnifyImage
15 15
16 16 return obj
... ... @@ -19,7 +19,7 @@ final class SearchBarView: UIView {
19 19 let searchTextFieldView: UITextField = {
20 20 let obj = UITextField()
21 21 obj.text = "Search"
22   - obj.textColor = ColorConstants.gray
  22 + obj.textColor = ColorConstants.SearchbarTintBlue
23 23
24 24 return obj
25 25 }()
... ... @@ -27,7 +27,7 @@ final class SearchBarView: UIView {
27 27 let cleanTextFieldButton: UIButton = {
28 28 let obj = UIButton()
29 29 obj.setImage(UIImage(systemName: "xmark.circle.fill"), for: .normal)
30   - obj.tintColor = .black
  30 + obj.tintColor = ColorConstants.SearchbarTintBlue
31 31 obj.isHidden = true
32 32
33 33 return obj
... ...
... ... @@ -21,7 +21,7 @@ final class ToolbarView: UIView {
21 21 private let toolbar: UIToolbar = {
22 22 let obj = UIToolbar()
23 23 obj.sizeToFit()
24   - obj.barTintColor = ColorConstants.lightGray
  24 + obj.barTintColor = ColorConstants.customLightBlue
25 25 obj.clipsToBounds = true
26 26
27 27 return obj
... ...
... ... @@ -13,8 +13,6 @@ final class PayloadViewController: UIViewController {
13 13
14 14 override func viewDidLoad() {
15 15 super.viewDidLoad()
16   - view.backgroundColor = ColorConstants.lightGray
17   -
18 16 initViewController()
19 17 }
20 18
... ...
... ... @@ -19,7 +19,7 @@ final class AdvantagesTableViewCell: UITableViewCell {
19 19
20 20 private let advantagesCellImage: UIImageView = {
21 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 23 obj.image = checkmarkImg
24 24 obj.contentMode = .scaleToFill
25 25
... ...
... ... @@ -7,10 +7,10 @@
7 7
8 8 import UIKit
9 9
10   -final class PayloadView: UIView {
  10 +final class PayloadView: GradientView {
11 11 private let logoImageView: UIImageView = {
12 12 let obj = UIImageView()
13   - obj.image = UIImage(named: "Gotoweb")
  13 + obj.image = UIImage(named: "gotoweb")
14 14 obj.contentMode = .scaleAspectFit
15 15
16 16 return obj
... ... @@ -34,6 +34,7 @@ final class PayloadView: UIView {
34 34
35 35 let infoLabel: UILabel = {
36 36 let obj = UILabel()
  37 + obj.textColor = .white
37 38 obj.text = StringConstants.ourBrowser
38 39 obj.font = FontConstants.regularFont_12
39 40 obj.numberOfLines = 0
... ... @@ -50,7 +51,7 @@ final class PayloadView: UIView {
50 51 return obj
51 52 }()
52 53
53   - private let gradientLayer = CAGradientLayer()
  54 + private let gradientButtonLayer = CAGradientLayer()
54 55
55 56 let getStartedButton: UIButton = {
56 57 let obj = UIButton()
... ... @@ -66,12 +67,12 @@ final class PayloadView: UIView {
66 67 let privacyLabelView: UILabel = {
67 68 let obj = UILabel()
68 69 obj.textAlignment = .center
69   -
  70 + obj.textColor = .white
70 71 let fullText = "By starting, you agree to our Terms and Condition and Privacy Policy."
71 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 76 obj.attributedText = attributedText
76 77 obj.font = FontConstants.regularFont_12
77 78 obj.numberOfLines = 0
... ... @@ -93,7 +94,7 @@ final class PayloadView: UIView {
93 94 override func layoutSubviews() {
94 95 super.layoutSubviews()
95 96
96   - gradientLayer.frame = getStartedButton.bounds
  97 + gradientButtonLayer.frame = getStartedButton.bounds
97 98 }
98 99
99 100 private func setup() {
... ... @@ -112,7 +113,7 @@ final class PayloadView: UIView {
112 113 private func setupConstraints() {
113 114 logoImageView.snp.makeConstraints { make in
114 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 117 make.height.equalTo(26.sizeH)
117 118 }
118 119
... ... @@ -156,11 +157,11 @@ final class PayloadView: UIView {
156 157 }
157 158 }
158 159
159   -//MARK: Gradient
  160 +//MARK: Gradients
160 161 extension PayloadView {
161 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 9
10 10 final class RemoveAdvertViewController: UIViewController {
11 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 17 override func viewDidLoad() {
15 18 super.viewDidLoad()
16   -
  19 +
17 20 initViewController()
18 21 }
19 22
20 23 private func initViewController() {
21   - view.backgroundColor = ColorConstants.lightGray
22   -
23   - setupTableView()
24 24 addTargets()
  25 + setupTableView()
25 26 }
26   -
27   - override func loadView() {
28   - view = mainView
29   - }
30   -
  27 +
31 28 init() {
32   - removeTableViewCellsData = StringConstants.removeAdvertTableViewData
  29 + self.storeKit = StoreKitManager()
33 30
34 31 super.init(nibName: nil, bundle: nil)
35 32 }
... ... @@ -37,70 +34,94 @@ final class RemoveAdvertViewController: UIViewController {
37 34 required init?(coder: NSCoder) {
38 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 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 97 CachingManager.shared.isAdBlocking = false
77 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 2 // RemoveAdvertTableViewCell.swift
3 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 8 import UIKit
... ... @@ -10,52 +10,55 @@ import UIKit
10 10 final class RemoveAdvertTableViewCell: UITableViewCell {
11 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 8 import UIKit
9 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 16 obj.contentMode = .scaleAspectFit
31 17
32 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 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 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 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 51 return obj
68 52 }()
69 53
70   - private let priceLabel: UILabel = {
  54 + let tapActionLabel: UILabel = {
71 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 67 return obj
88 68 }()
89 69
90   - private let freeTrialLabel: UILabel = {
  70 + private let protectFromLabel: UILabel = {
91 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 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 84 return obj
106 85 }()
... ... @@ -111,95 +90,67 @@ final class RemoveAdvertView: UIView {
111 90 setup()
112 91 }
113 92
114   - override func layoutSubviews() {
115   - super.layoutSubviews()
116   -
117   - gradientLayer.frame = subscribeButton.bounds
118   - }
119   -
120 93 required init?(coder: NSCoder) {
121 94 fatalError("init(coder:) has not been implemented")
122 95 }
123 96
124 97 private func setup() {
125   - addSubview(closeButton)
126   - addSubview(shieldView)
127   - addSubview(abvertBlockerModeLabel)
  98 + addSubview(appLogoImageView)
  99 + addSubview(adBlockButton)
128 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 107 setupConstraints()
137   - gradientSetup()
138 108 }
139 109
140 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 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 19 private var searchImage: UIImageView = {
20 20 let obj = UIImageView()
21 21 obj.image = UIImage(systemName: "magnifyingglass")
22   - obj.tintColor = .gray
  22 + obj.tintColor = .white
23 23
24 24 return obj
25 25 }()
... ... @@ -40,7 +40,7 @@ final class SearchingTableViewCell: UITableViewCell {
40 40 private var linkImage: UIImageView = {
41 41 let obj = UIImageView()
42 42 obj.image = UIImage(systemName: "arrow.up.left")
43   - obj.tintColor = .gray
  43 + obj.tintColor = .white
44 44
45 45 return obj
46 46 }()
... ... @@ -57,6 +57,7 @@ final class SearchingTableViewCell: UITableViewCell {
57 57 }
58 58
59 59 private func setup() {
  60 + self.backgroundColor = .clear
60 61 contentView.addSubview(searchImage)
61 62 contentView.addSubview(searchLabel)
62 63 contentView.addSubview(siteLogoImage)
... ...
... ... @@ -7,7 +7,7 @@
7 7
8 8 import UIKit
9 9
10   -final class SearchingView: UIView, UITextFieldDelegate {
  10 +final class SearchingView: GradientView {
11 11 let searchingButton: UIButton = {
12 12 let obj = UIButton()
13 13 obj.setImage(UIImage(systemName: "arrow.left"), for: .normal)
... ... @@ -15,7 +15,7 @@ final class SearchingView: UIView, UITextFieldDelegate {
15 15 return obj
16 16 }()
17 17
18   - let searchingLabel: UILabel = {
  18 + private let searchingLabel: UILabel = {
19 19 let obj = UILabel()
20 20 obj.text = "Searching"
21 21 obj.font = FontConstants.semiboldFont_18
... ...
... ... @@ -7,10 +7,13 @@
7 7
8 8 import UIKit
9 9 import MessageUI
  10 +import StoreKit
10 11
11 12 final class SettingViewController: UIViewController {
  13 +
12 14 private let mainView = SettingView()
13   - private let param = StringConstants.settingViewControllerTableViewData
  15 + private let settingTableViewData = StringConstants.settingViewControllerTableViewData
  16 +
14 17 init() {
15 18 super.init(nibName: nil, bundle: nil)
16 19 }
... ... @@ -40,15 +43,18 @@ final class SettingViewController: UIViewController {
40 43 //MARK: SettingTableView
41 44 extension SettingViewController: UITableViewDelegate, UITableViewDataSource {
42 45 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
43   - return param.count
  46 + return settingTableViewData.count
44 47 }
45 48
46 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 55 cell.settingTableViewLabel.text = info
51 56 cell.selectionStyle = .none
  57 +
52 58 return cell
53 59 }
54 60
... ... @@ -68,7 +74,7 @@ extension SettingViewController {
68 74 private func setupSettingTableView() {
69 75 mainView.settingTableView.delegate = self
70 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 80 private func setupMessage() {
... ... @@ -77,7 +83,7 @@ extension SettingViewController {
77 83 }
78 84 let composer = MFMailComposeViewController()
79 85 composer.mailComposeDelegate = self
80   - composer.setToRecipients(["test@gmail.com"])
  86 + composer.setToRecipients(["creattechllc@gmail.com"])
81 87 composer.setSubject("Browser")
82 88 present(composer, animated: true, completion: nil)
83 89 }
... ... @@ -96,6 +102,10 @@ extension SettingViewController {
96 102 break
97 103 case 4:
98 104 setupMessage()
  105 + case 5:
  106 + Task {
  107 + try? await AppStore.sync()
  108 + }
99 109 default:
100 110 break
101 111 }
... ... @@ -116,14 +126,15 @@ extension SettingViewController {
116 126 private func shareButtonPressed() {
117 127 let items = [URL(string: URLConstants.shareAppLink)]
118 128 let shareView = UIActivityViewController(activityItems: items as [Any], applicationActivities: nil)
  129 +
119 130 present(shareView, animated: true)
120 131 }
121 132
122 133 private func presentViewController(_ viewController: UIViewController) {
123 134 viewController.modalPresentationStyle = .fullScreen
  135 +
124 136 present(viewController, animated: true)
125 137 }
126   -
127 138 }
128 139
129 140 //MARK: Mail helper
... ...
... ... @@ -8,14 +8,18 @@
8 8 import UIKit
9 9
10 10 final class SettingTableViewCell: UITableViewCell {
  11 + static let cellId = String(describing: SettingTableViewCell.self)
  12 +
11 13 let settingTableViewLabel: UILabel = {
12 14 let obj = UILabel()
13 15 obj.font = FontConstants.semiboldFont_17
14 16 obj.textColor = ColorConstants.lightGray
15 17 obj.textAlignment = .center
  18 +
16 19 obj.backgroundColor = ColorConstants.buttonsBackgroundColor
17 20 obj.layer.cornerRadius = 10
18 21 obj.layer.masksToBounds = true
  22 +
19 23 return obj
20 24 }()
21 25
... ... @@ -23,6 +27,7 @@ final class SettingTableViewCell: UITableViewCell {
23 27
24 28 override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
25 29 super.init(style: style, reuseIdentifier: reuseIdentifier)
  30 +
26 31 setup()
27 32 }
28 33
... ... @@ -31,12 +36,15 @@ final class SettingTableViewCell: UITableViewCell {
31 36 }
32 37
33 38 private func setup() {
  39 + self.backgroundColor = .clear
34 40 contentView.addSubview(settingTableViewLabel)
  41 +
35 42 setupConstraints()
36 43 }
37 44
38 45 override func layoutSubviews() {
39 46 super.layoutSubviews()
  47 +
40 48 gradientLayer.frame = self.bounds
41 49 }
42 50
... ...
... ... @@ -22,8 +22,6 @@ final class PrivacyViewController: UIViewController {
22 22
23 23 private func initViewController() {
24 24 addTargets()
25   - mainView.backgroundColor = .white
26   -
27 25 }
28 26 }
29 27
... ...
... ... @@ -7,7 +7,7 @@
7 7
8 8 import UIKit
9 9
10   -final class PrivacyView: UIView {
  10 +final class PrivacyView: GradientView {
11 11 private let privacyHeaderLabel: UILabel = {
12 12 let obj = UILabel()
13 13 obj.text = StringConstants.privacyHeaderText
... ... @@ -20,7 +20,7 @@ final class PrivacyView: UIView {
20 20
21 21 private let privacyMainInfoLabel: UILabel = {
22 22 let obj = UILabel()
23   - obj.text = StringConstants.settingTerms
  23 + obj.text = StringConstants.settingPolicy
24 24 obj.numberOfLines = 0
25 25 obj.font = FontConstants.regularFont_18
26 26
... ... @@ -29,10 +29,10 @@ final class PrivacyView: UIView {
29 29
30 30 let privacyButton: UIButton = {
31 31 let obj = UIButton()
32   - obj.backgroundColor = .systemIndigo.withAlphaComponent(0.4)
  32 + obj.backgroundColor = ColorConstants.buttonsBackgroundColor
33 33 obj.layer.cornerRadius = 10
34 34 obj.setTitle(StringConstants.settingAgreeButtonText, for: .normal)
35   - obj.setTitleColor(.black, for: .normal)
  35 + obj.setTitleColor(.white, for: .normal)
36 36
37 37 return obj
38 38 }()
... ...
... ... @@ -21,8 +21,6 @@ final class TermsViewController: UIViewController {
21 21 }
22 22
23 23 private func initViewController() {
24   - mainView.backgroundColor = .white
25   -
26 24 addTargets()
27 25 }
28 26 }
... ...
... ... @@ -8,7 +8,7 @@
8 8
9 9 import UIKit
10 10
11   -final class TermsView: UIView {
  11 +final class TermsView: GradientView {
12 12 private let termsHeaderLabel: UILabel = {
13 13 let obj = UILabel()
14 14 obj.text = StringConstants.settingHeader
... ... @@ -30,10 +30,10 @@ final class TermsView: UIView {
30 30
31 31 let termsButton: UIButton = {
32 32 let obj = UIButton()
33   - obj.backgroundColor = .systemIndigo.withAlphaComponent(0.4)
  33 + obj.backgroundColor = ColorConstants.buttonsBackgroundColor
34 34 obj.layer.cornerRadius = 10
35 35 obj.setTitle(StringConstants.settingAgreeButtonText, for: .normal)
36   - obj.setTitleColor(.black, for: .normal)
  36 + obj.setTitleColor(.white, for: .normal)
37 37
38 38 return obj
39 39 }()
... ...
... ... @@ -7,11 +7,12 @@
7 7
8 8 import UIKit
9 9
10   -final class SettingView: UIView {
  10 +final class SettingView: GradientView {
11 11 let backButton: UIButton = {
12 12 let obj = UIButton()
13 13 obj.setImage(UIImage(systemName: "arrow.left"), for: .normal)
14 14 obj.contentMode = .scaleToFill
  15 +
15 16 return obj
16 17 }()
17 18
... ... @@ -19,6 +20,8 @@ final class SettingView: UIView {
19 20 let obj = UITableView()
20 21 obj.isScrollEnabled = false
21 22 obj.separatorStyle = .none
  23 + obj.backgroundColor = .clear
  24 +
22 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 118 mainView.openedTabsCollectionView.register(OpenedTabsCollectionViewCell.self, forCellWithReuseIdentifier: OpenedTabsCollectionViewCell.cellID)
119 119 }
120 120
  121 + func removeSelf() {
  122 + navigationController?.popViewController(animated: false)
  123 + }
  124 +
121 125 private func addTargets() {
122 126 addToolbarTargets()
123 127 }
... ... @@ -156,7 +160,7 @@ extension TabsViewController {
156 160 }
157 161 }
158 162
159   - private func refreshData() {
  163 + func refreshData() {
160 164 tabsData = TabManager.shared.getAllTabs()
161 165 mainView.openedTabsCollectionView.reloadData()
162 166 }
... ...
... ... @@ -26,7 +26,7 @@ final class OpenedTabsCollectionViewCell: UICollectionViewCell {
26 26 private let siteNameLabel: UILabel = {
27 27 let obj = UILabel()
28 28 obj.font = FontConstants.regularFont_14
29   -
  29 + obj.textColor = .black
30 30 return obj
31 31 }()
32 32
... ...
... ... @@ -18,7 +18,7 @@ final class TabsToolbarView: UIView {
18 18
19 19 private let toolbar: UIToolbar = {
20 20 let obj = UIToolbar()
21   - obj.barTintColor = .white
  21 + obj.barTintColor = ColorConstants.customLightBlue
22 22
23 23 return obj
24 24 }()
... ... @@ -26,7 +26,7 @@ final class TabsToolbarView: UIView {
26 26 private let newTabToolbarButtonItem: UIBarButtonItem = {
27 27 let obj = UIBarButtonItem()
28 28 obj.image = UIImage(systemName: "plus")
29   - obj.tintColor = .gray
  29 + obj.tintColor = ColorConstants.SearchbarTintBlue
30 30
31 31 return obj
32 32 }()
... ... @@ -34,7 +34,7 @@ final class TabsToolbarView: UIView {
34 34
35 35 let showedCountOfTabs: UIBarButtonItem = {
36 36 let obj = UIBarButtonItem()
37   - obj.tintColor = .gray
  37 + obj.tintColor = ColorConstants.SearchbarTintBlue
38 38
39 39 return obj
40 40 }()
... ... @@ -42,7 +42,7 @@ final class TabsToolbarView: UIView {
42 42 private let doneTabToolbarButtonItem: UIBarButtonItem = {
43 43 let obj = UIBarButtonItem()
44 44 obj.title = "Done"
45   -
  45 + obj.tintColor = ColorConstants.SearchbarTintBlue
46 46 return obj
47 47 }()
48 48
... ...
... ... @@ -8,7 +8,7 @@
8 8 import UIKit
9 9 import SnapKit
10 10
11   -final class TabsView: UIView {
  11 +final class TabsView: GradientView {
12 12 let openedTabsCollectionView: UICollectionView = {
13 13 let obj = UICollectionViewFlowLayout()
14 14 obj.minimumInteritemSpacing = 4.sizeW
... ... @@ -23,7 +23,7 @@ final class TabsView: UIView {
23 23
24 24 let tabsToolbarView: TabsToolbarView = {
25 25 let obj = TabsToolbarView()
26   - obj.backgroundColor = ColorConstants.lightGray
  26 + obj.backgroundColor = ColorConstants.SearchbarTintBlue
27 27
28 28 return obj
29 29 }()
... ... @@ -53,7 +53,7 @@ final class TabsView: UIView {
53 53 }
54 54 tabsToolbarView.snp.makeConstraints { make in
55 55 make.leading.equalToSuperview()
56   - make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom)
  56 + make.bottom.equalToSuperview()
57 57 make.trailing.equalToSuperview()
58 58 }
59 59 }
... ...
... ... @@ -8,32 +8,34 @@
8 8 import UIKit
9 9
10 10 final class NavigationViewController: UINavigationController {
  11 +
11 12 override func viewDidLoad() {
12 13 super.viewDidLoad()
  14 +
13 15 initViewController()
14 16 }
15 17
16 18 private func initViewController() {
17   - setStartControllers()
18   - view.backgroundColor = .blue
  19 + view.backgroundColor = .black
19 20 delegate = self
  21 +
  22 + setStartControllers()
20 23 }
21 24 }
22 25
23 26 // MARK: - Helpers
24 27 extension NavigationViewController {
25 28 private func setStartControllers() {
26   - let tabsViewController = TabsViewController()
27   - let browserHomeViewController = BrowserHomeViewController(url: nil, currentTabId: nil)
28 29 let payloadViewController = PayloadViewController()
  30 + let removeAdvertViewController = RemoveAdvertViewController()
29 31 let cachingManager = CachingManager.shared
  32 +
30 33 if cachingManager.isFirstAppLoad == false {
31   - setViewControllers([tabsViewController, browserHomeViewController, payloadViewController], animated: true)
  34 + setViewControllers([removeAdvertViewController, payloadViewController], animated: true)
32 35 cachingManager.isFirstAppLoad.toggle()
33 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 52 if (fromVC is TabsViewController && toVC is BrowserHomeViewController) {
51 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 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 9
10 10 struct ColorConstants {
11 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 13 static let payloadTextColor = UIColor(red: 0.121, green: 0.121, blue: 0.121, alpha: 1)
14 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 15 static let regularFont_12 = UIFont(name: "SFProText-Regular", size: 12.sizeW)
16 16
17 17 //SFProText-Semibold
  18 + static let semiboldFont_24 = UIFont(name: "SFProText-Semibold", size: 24.sizeW)
18 19 static let semiboldFont_18 = UIFont(name: "SFProText-Semibold", size: 18.sizeW)
19 20 static let semiboldFont_17 = UIFont(name: "SFProText-Semibold", size: 17.sizeW)
20 21 static let semiboldFont_15 = UIFont(name: "SFProText-Semibold", size: 15.sizeW)
... ...
... ... @@ -27,7 +27,7 @@ struct StringConstants {
27 27 "https://github.com/" ]
28 28
29 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 31 static let removeAdvertTableViewData = ["Unlimited blocks & uploads", "Enhanced User Experience", "Faster Page Load Times", "Privacy and Security"]
32 32 static let search = "Search"
33 33
... ... @@ -42,20 +42,21 @@ struct StringConstants {
42 42 static let turnOff = "Tap to turn off"
43 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 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 52 static let settingHeader = "Terms\nand conditions"
56 53 static let settingAgreeButtonText = "Agree & Continue"
57 54 static let privacyHeaderText = "Your Privacy\n is our top priority"
58 55
59 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 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 8 "info" : {
... ...
1 1 {
2 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 8 "info" : {
... ...
1 1 {
2 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 8 "info" : {
... ...
1 1 {
2 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 8 "info" : {
... ...
1 1 {
2 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 8 "info" : {
... ...
1 1 {
2 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 8 "info" : {
... ...
1 1 {
2 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 8 "info" : {
31 9 "author" : "xcode",
32 10 "version" : 1
  11 + },
  12 + "properties" : {
  13 + "preserves-vector-representation" : true,
  14 + "template-rendering-intent" : "original"
33 15 }
34 16 }
... ...
1 1 {
2 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 8 "info" : {
... ...
1 1 {
2 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 8 "info" : {
... ...
1 1 {
2 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 8 "info" : {
... ...
1 1 {
2 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 8 "info" : {
... ...
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
... ...
1 1 {
2 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 8 "info" : {
... ...
1 1 {
2 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 8 "info" : {
... ...
1   -{
2   - "images" : [
3   - {
4   - "filename" : "defaultTabImage.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   - "info" : {
18   - "author" : "xcode",
19   - "version" : 1
20   - }
21   -}
1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2 <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22155" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
3   - <device id="retina6_12" orientation="portrait" appearance="light"/>
  3 + <device id="retina6_72" orientation="portrait" appearance="light"/>
4 4 <dependencies>
5 5 <deployment identifier="iOS"/>
6 6 <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22131"/>
... ... @@ -13,25 +13,35 @@
13 13 <objects>
14 14 <viewController id="01J-lp-oVM" sceneMemberID="viewController">
15 15 <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
16   - <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
  16 + <rect key="frame" x="0.0" y="0.0" width="430" height="932"/>
17 17 <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
18 18 <subviews>
19   - <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="Gotoweb" translatesAutoresizingMaskIntoConstraints="NO" id="M9l-6x-NJv">
20   - <rect key="frame" x="128" y="395" width="136" height="62"/>
21   - <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
22   - <edgeInsets key="layoutMargins" top="8" left="8" bottom="8" right="8"/>
  19 + <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="background" translatesAutoresizingMaskIntoConstraints="NO" id="0eA-6M-kND">
  20 + <rect key="frame" x="0.0" y="0.0" width="430" height="932"/>
  21 + </imageView>
  22 + <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="gotoweb" translatesAutoresizingMaskIntoConstraints="NO" id="nOe-mG-Ga9">
  23 + <rect key="frame" x="118" y="438" width="194" height="56"/>
  24 + <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
  25 + <preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="default"/>
23 26 </imageView>
24 27 </subviews>
25   - <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
26   - <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
  28 + <viewLayoutGuide key="safeArea" id="R3V-Gq-Ybi"/>
  29 + <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
  30 + <constraints>
  31 + <constraint firstItem="0eA-6M-kND" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="BXR-MA-cEH"/>
  32 + <constraint firstItem="0eA-6M-kND" firstAttribute="trailing" secondItem="R3V-Gq-Ybi" secondAttribute="trailing" id="VDj-67-7du"/>
  33 + <constraint firstAttribute="bottom" secondItem="0eA-6M-kND" secondAttribute="bottom" id="fEE-j8-go1"/>
  34 + <constraint firstItem="0eA-6M-kND" firstAttribute="leading" secondItem="R3V-Gq-Ybi" secondAttribute="leading" id="hJs-nY-YnN"/>
  35 + </constraints>
27 36 </view>
28 37 </viewController>
29 38 <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
30 39 </objects>
31   - <point key="canvasLocation" x="52.671755725190835" y="374.64788732394368"/>
  40 + <point key="canvasLocation" x="51.627906976744185" y="373.39055793991417"/>
32 41 </scene>
33 42 </scenes>
34 43 <resources>
35   - <image name="Gotoweb" width="178" height="52"/>
  44 + <image name="background" width="375" height="812"/>
  45 + <image name="gotoweb" width="113" height="34"/>
36 46 </resources>
37 47 </document>
... ...
Please register or login to post a comment