Commit f29ad80f50ceb5fda13e31938d8ef85fb6bd8c22

Authored by Yevgeniy Yehanovskyi
1 parent a66b8be6

update to the last changes

Showing 60 changed files with 2194 additions and 47 deletions
No preview for this file type
@@ -82,6 +82,23 @@ @@ -82,6 +82,23 @@
82 19FCBF3D2AC17AB000F83A7F /* BrowserHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FCBF3C2AC17AB000F83A7F /* BrowserHomeView.swift */; }; 82 19FCBF3D2AC17AB000F83A7F /* BrowserHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FCBF3C2AC17AB000F83A7F /* BrowserHomeView.swift */; };
83 19FCBF452AC1981A00F83A7F /* TabCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FCBF442AC1981A00F83A7F /* TabCollectionViewCell.swift */; }; 83 19FCBF452AC1981A00F83A7F /* TabCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FCBF442AC1981A00F83A7F /* TabCollectionViewCell.swift */; };
84 19FFD6BF2AE64A7B00D0F768 /* SnapshotService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FFD6BE2AE64A7B00D0F768 /* SnapshotService.swift */; }; 84 19FFD6BF2AE64A7B00D0F768 /* SnapshotService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FFD6BE2AE64A7B00D0F768 /* SnapshotService.swift */; };
  85 + 84C513C92B35BCF8000DD86A /* NewPaywallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C513C82B35BCF8000DD86A /* NewPaywallViewController.swift */; };
  86 + 84C513CB2B35BD16000DD86A /* NewPaywallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C513CA2B35BD16000DD86A /* NewPaywallView.swift */; };
  87 + 84C513CE2B35BD3B000DD86A /* PageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C513CD2B35BD3B000DD86A /* PageView.swift */; };
  88 + 84C513D02B35BD64000DD86A /* PaywallType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C513CF2B35BD64000DD86A /* PaywallType.swift */; };
  89 + 84D1BDE62B26766500D3A042 /* VPNAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D1BDE52B26766500D3A042 /* VPNAnalytics.swift */; };
  90 + 84D1BDE92B26768A00D3A042 /* VPNAnalyticsConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D1BDE82B26768A00D3A042 /* VPNAnalyticsConstants.swift */; };
  91 + 84D1BDEC2B2676B200D3A042 /* AnalyticsNetworkRequestInterceptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D1BDEB2B2676B200D3A042 /* AnalyticsNetworkRequestInterceptor.swift */; };
  92 + 84D1BDEE2B2676C900D3A042 /* AnalyticsNetworkHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D1BDED2B2676C900D3A042 /* AnalyticsNetworkHelper.swift */; };
  93 + 84D1BDF02B2676EB00D3A042 /* AnalyticsAPIManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D1BDEF2B2676EB00D3A042 /* AnalyticsAPIManager.swift */; };
  94 + 84D1BDF32B26770A00D3A042 /* AnalyticsNetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D1BDF22B26770A00D3A042 /* AnalyticsNetworkError.swift */; };
  95 + 84D1BDF82B26776400D3A042 /* LogEventResponseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D1BDF72B26776400D3A042 /* LogEventResponseModel.swift */; };
  96 + 84D1BDFA2B26777C00D3A042 /* IPResponseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D1BDF92B26777C00D3A042 /* IPResponseModel.swift */; };
  97 + 84D1BDFC2B26779E00D3A042 /* AnalyticsAPIService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D1BDFB2B26779E00D3A042 /* AnalyticsAPIService.swift */; };
  98 + 92EC4B8A2B2712FE0088DFB7 /* ProgressHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92EC4B892B2712FE0088DFB7 /* ProgressHelper.swift */; };
  99 + 92EC4B8C2B27133A0088DFB7 /* ProgressHelperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92EC4B8B2B27133A0088DFB7 /* ProgressHelperView.swift */; };
  100 + 92EC4B8E2B27136E0088DFB7 /* ActivityIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92EC4B8D2B27136E0088DFB7 /* ActivityIndicator.swift */; };
  101 + 92EC4B902B2713A80088DFB7 /* FloatingPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92EC4B8F2B2713A80088DFB7 /* FloatingPoint.swift */; };
85 /* End PBXBuildFile section */ 102 /* End PBXBuildFile section */
86 103
87 /* Begin PBXContainerItemProxy section */ 104 /* Begin PBXContainerItemProxy section */
@@ -183,6 +200,25 @@ @@ -183,6 +200,25 @@
183 19FCBF3C2AC17AB000F83A7F /* BrowserHomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHomeView.swift; sourceTree = "<group>"; }; 200 19FCBF3C2AC17AB000F83A7F /* BrowserHomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHomeView.swift; sourceTree = "<group>"; };
184 19FCBF442AC1981A00F83A7F /* TabCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabCollectionViewCell.swift; sourceTree = "<group>"; }; 201 19FCBF442AC1981A00F83A7F /* TabCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabCollectionViewCell.swift; sourceTree = "<group>"; };
185 19FFD6BE2AE64A7B00D0F768 /* SnapshotService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotService.swift; sourceTree = "<group>"; }; 202 19FFD6BE2AE64A7B00D0F768 /* SnapshotService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnapshotService.swift; sourceTree = "<group>"; };
  203 + 84C513C82B35BCF8000DD86A /* NewPaywallViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewPaywallViewController.swift; sourceTree = "<group>"; };
  204 + 84C513CA2B35BD16000DD86A /* NewPaywallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewPaywallView.swift; sourceTree = "<group>"; };
  205 + 84C513CD2B35BD3B000DD86A /* PageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageView.swift; sourceTree = "<group>"; };
  206 + 84C513CF2B35BD64000DD86A /* PaywallType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaywallType.swift; sourceTree = "<group>"; };
  207 + 84D1BDE52B26766500D3A042 /* VPNAnalytics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNAnalytics.swift; sourceTree = "<group>"; };
  208 + 84D1BDE82B26768A00D3A042 /* VPNAnalyticsConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNAnalyticsConstants.swift; sourceTree = "<group>"; };
  209 + 84D1BDEB2B2676B200D3A042 /* AnalyticsNetworkRequestInterceptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsNetworkRequestInterceptor.swift; sourceTree = "<group>"; };
  210 + 84D1BDED2B2676C900D3A042 /* AnalyticsNetworkHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsNetworkHelper.swift; sourceTree = "<group>"; };
  211 + 84D1BDEF2B2676EB00D3A042 /* AnalyticsAPIManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsAPIManager.swift; sourceTree = "<group>"; };
  212 + 84D1BDF22B26770A00D3A042 /* AnalyticsNetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsNetworkError.swift; sourceTree = "<group>"; };
  213 + 84D1BDF72B26776400D3A042 /* LogEventResponseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogEventResponseModel.swift; sourceTree = "<group>"; };
  214 + 84D1BDF92B26777C00D3A042 /* IPResponseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPResponseModel.swift; sourceTree = "<group>"; };
  215 + 84D1BDFB2B26779E00D3A042 /* AnalyticsAPIService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsAPIService.swift; sourceTree = "<group>"; };
  216 + 84D1BDFE2B2678A200D3A042 /* VPN-WebBrauser-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "VPN-WebBrauser-Bridging-Header.h"; sourceTree = "<group>"; };
  217 + 84D1BDFF2B2678C100D3A042 /* VPNManagerStatus.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VPNManagerStatus.h; sourceTree = "<group>"; };
  218 + 92EC4B892B2712FE0088DFB7 /* ProgressHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressHelper.swift; sourceTree = "<group>"; };
  219 + 92EC4B8B2B27133A0088DFB7 /* ProgressHelperView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressHelperView.swift; sourceTree = "<group>"; };
  220 + 92EC4B8D2B27136E0088DFB7 /* ActivityIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityIndicator.swift; sourceTree = "<group>"; };
  221 + 92EC4B8F2B2713A80088DFB7 /* FloatingPoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingPoint.swift; sourceTree = "<group>"; };
186 /* End PBXFileReference section */ 222 /* End PBXFileReference section */
187 223
188 /* Begin PBXFrameworksBuildPhase section */ 224 /* Begin PBXFrameworksBuildPhase section */
@@ -253,6 +289,7 @@ @@ -253,6 +289,7 @@
253 190DBA0C2AC47701000A7BF3 /* BinaryFloatingPoint.swift */, 289 190DBA0C2AC47701000A7BF3 /* BinaryFloatingPoint.swift */,
254 19C5F0562AD9784400133BD7 /* DataExtention+toImage.swift */, 290 19C5F0562AD9784400133BD7 /* DataExtention+toImage.swift */,
255 1990C69B2AEFDF89004AF856 /* UICollectionViewCell+convertFrameToScreenCoordinates.swift */, 291 1990C69B2AEFDF89004AF856 /* UICollectionViewCell+convertFrameToScreenCoordinates.swift */,
  292 + 92EC4B8F2B2713A80088DFB7 /* FloatingPoint.swift */,
256 ); 293 );
257 path = Extentions; 294 path = Extentions;
258 sourceTree = "<group>"; 295 sourceTree = "<group>";
@@ -434,8 +471,8 @@ @@ -434,8 +471,8 @@
434 197534722B10965F000818D3 /* Subscription */ = { 471 197534722B10965F000818D3 /* Subscription */ = {
435 isa = PBXGroup; 472 isa = PBXGroup;
436 children = ( 473 children = (
437 - 197534742B10967B000818D3 /* Controller */,  
438 - 197534732B109675000818D3 /* View */, 474 + 84C513C42B35B962000DD86A /* FirsPayWall */,
  475 + 84C513C32B35B955000DD86A /* NewPaywall */,
439 ); 476 );
440 path = Subscription; 477 path = Subscription;
441 sourceTree = "<group>"; 478 sourceTree = "<group>";
@@ -687,6 +724,8 @@ @@ -687,6 +724,8 @@
687 19F65A722ACBFD7300B50F61 /* Common */ = { 724 19F65A722ACBFD7300B50F61 /* Common */ = {
688 isa = PBXGroup; 725 isa = PBXGroup;
689 children = ( 726 children = (
  727 + 92EC4B882B2712EB0088DFB7 /* Helpers */,
  728 + 84D1BDE32B26763E00D3A042 /* Analytics */,
690 19B739742AE275FF0073AA59 /* Models */, 729 19B739742AE275FF0073AA59 /* Models */,
691 199DB1EC2AD3FCE1007E6A81 /* Services */, 730 199DB1EC2AD3FCE1007E6A81 /* Services */,
692 190DB9FD2AC459CD000A7BF3 /* Managers */, 731 190DB9FD2AC459CD000A7BF3 /* Managers */,
@@ -730,6 +769,7 @@ @@ -730,6 +769,7 @@
730 19FCBF202AC1727800F83A7F /* browser */ = { 769 19FCBF202AC1727800F83A7F /* browser */ = {
731 isa = PBXGroup; 770 isa = PBXGroup;
732 children = ( 771 children = (
  772 + 84D1BDFD2B26786D00D3A042 /* Objc */,
733 19FCBF382AC17A4800F83A7F /* Modules */, 773 19FCBF382AC17A4800F83A7F /* Modules */,
734 19FCBF352AC1779800F83A7F /* Navigation */, 774 19FCBF352AC1779800F83A7F /* Navigation */,
735 19F65A722ACBFD7300B50F61 /* Common */, 775 19F65A722ACBFD7300B50F61 /* Common */,
@@ -800,6 +840,149 @@ @@ -800,6 +840,149 @@
800 path = Cell; 840 path = Cell;
801 sourceTree = "<group>"; 841 sourceTree = "<group>";
802 }; 842 };
  843 + 84C513C32B35B955000DD86A /* NewPaywall */ = {
  844 + isa = PBXGroup;
  845 + children = (
  846 + 84C513C72B35BCC2000DD86A /* Model */,
  847 + 84C513C62B35BCBC000DD86A /* View */,
  848 + 84C513C52B35BCB6000DD86A /* Controller */,
  849 + );
  850 + path = NewPaywall;
  851 + sourceTree = "<group>";
  852 + };
  853 + 84C513C42B35B962000DD86A /* FirsPayWall */ = {
  854 + isa = PBXGroup;
  855 + children = (
  856 + 197534742B10967B000818D3 /* Controller */,
  857 + 197534732B109675000818D3 /* View */,
  858 + );
  859 + path = FirsPayWall;
  860 + sourceTree = "<group>";
  861 + };
  862 + 84C513C52B35BCB6000DD86A /* Controller */ = {
  863 + isa = PBXGroup;
  864 + children = (
  865 + 84C513C82B35BCF8000DD86A /* NewPaywallViewController.swift */,
  866 + );
  867 + path = Controller;
  868 + sourceTree = "<group>";
  869 + };
  870 + 84C513C62B35BCBC000DD86A /* View */ = {
  871 + isa = PBXGroup;
  872 + children = (
  873 + 84C513CC2B35BD2D000DD86A /* Content */,
  874 + 84C513CA2B35BD16000DD86A /* NewPaywallView.swift */,
  875 + );
  876 + path = View;
  877 + sourceTree = "<group>";
  878 + };
  879 + 84C513C72B35BCC2000DD86A /* Model */ = {
  880 + isa = PBXGroup;
  881 + children = (
  882 + 84C513CF2B35BD64000DD86A /* PaywallType.swift */,
  883 + );
  884 + path = Model;
  885 + sourceTree = "<group>";
  886 + };
  887 + 84C513CC2B35BD2D000DD86A /* Content */ = {
  888 + isa = PBXGroup;
  889 + children = (
  890 + 84C513CD2B35BD3B000DD86A /* PageView.swift */,
  891 + );
  892 + path = Content;
  893 + sourceTree = "<group>";
  894 + };
  895 + 84D1BDE32B26763E00D3A042 /* Analytics */ = {
  896 + isa = PBXGroup;
  897 + children = (
  898 + 84D1BDF42B26773800D3A042 /* Services */,
  899 + 84D1BDE72B26767800D3A042 /* Helpers */,
  900 + 84D1BDE42B26765300D3A042 /* Classes */,
  901 + );
  902 + path = Analytics;
  903 + sourceTree = "<group>";
  904 + };
  905 + 84D1BDE42B26765300D3A042 /* Classes */ = {
  906 + isa = PBXGroup;
  907 + children = (
  908 + 84D1BDE52B26766500D3A042 /* VPNAnalytics.swift */,
  909 + );
  910 + path = Classes;
  911 + sourceTree = "<group>";
  912 + };
  913 + 84D1BDE72B26767800D3A042 /* Helpers */ = {
  914 + isa = PBXGroup;
  915 + children = (
  916 + 84D1BDF12B2676F900D3A042 /* Error */,
  917 + 84D1BDEA2B26769C00D3A042 /* API */,
  918 + 84D1BDE82B26768A00D3A042 /* VPNAnalyticsConstants.swift */,
  919 + );
  920 + path = Helpers;
  921 + sourceTree = "<group>";
  922 + };
  923 + 84D1BDEA2B26769C00D3A042 /* API */ = {
  924 + isa = PBXGroup;
  925 + children = (
  926 + 84D1BDEB2B2676B200D3A042 /* AnalyticsNetworkRequestInterceptor.swift */,
  927 + 84D1BDED2B2676C900D3A042 /* AnalyticsNetworkHelper.swift */,
  928 + 84D1BDEF2B2676EB00D3A042 /* AnalyticsAPIManager.swift */,
  929 + );
  930 + path = API;
  931 + sourceTree = "<group>";
  932 + };
  933 + 84D1BDF12B2676F900D3A042 /* Error */ = {
  934 + isa = PBXGroup;
  935 + children = (
  936 + 84D1BDF22B26770A00D3A042 /* AnalyticsNetworkError.swift */,
  937 + );
  938 + path = Error;
  939 + sourceTree = "<group>";
  940 + };
  941 + 84D1BDF42B26773800D3A042 /* Services */ = {
  942 + isa = PBXGroup;
  943 + children = (
  944 + 84D1BDF52B26774900D3A042 /* API */,
  945 + );
  946 + path = Services;
  947 + sourceTree = "<group>";
  948 + };
  949 + 84D1BDF52B26774900D3A042 /* API */ = {
  950 + isa = PBXGroup;
  951 + children = (
  952 + 84D1BDF62B26775500D3A042 /* CodableModels */,
  953 + 84D1BDFB2B26779E00D3A042 /* AnalyticsAPIService.swift */,
  954 + );
  955 + path = API;
  956 + sourceTree = "<group>";
  957 + };
  958 + 84D1BDF62B26775500D3A042 /* CodableModels */ = {
  959 + isa = PBXGroup;
  960 + children = (
  961 + 84D1BDF72B26776400D3A042 /* LogEventResponseModel.swift */,
  962 + 84D1BDF92B26777C00D3A042 /* IPResponseModel.swift */,
  963 + );
  964 + path = CodableModels;
  965 + sourceTree = "<group>";
  966 + };
  967 + 84D1BDFD2B26786D00D3A042 /* Objc */ = {
  968 + isa = PBXGroup;
  969 + children = (
  970 + 84D1BDFE2B2678A200D3A042 /* VPN-WebBrauser-Bridging-Header.h */,
  971 + 84D1BDFF2B2678C100D3A042 /* VPNManagerStatus.h */,
  972 + );
  973 + path = Objc;
  974 + sourceTree = "<group>";
  975 + };
  976 + 92EC4B882B2712EB0088DFB7 /* Helpers */ = {
  977 + isa = PBXGroup;
  978 + children = (
  979 + 92EC4B892B2712FE0088DFB7 /* ProgressHelper.swift */,
  980 + 92EC4B8B2B27133A0088DFB7 /* ProgressHelperView.swift */,
  981 + 92EC4B8D2B27136E0088DFB7 /* ActivityIndicator.swift */,
  982 + );
  983 + path = Helpers;
  984 + sourceTree = "<group>";
  985 + };
803 /* End PBXGroup section */ 986 /* End PBXGroup section */
804 987
805 /* Begin PBXNativeTarget section */ 988 /* Begin PBXNativeTarget section */
@@ -924,18 +1107,23 @@ @@ -924,18 +1107,23 @@
924 isa = PBXSourcesBuildPhase; 1107 isa = PBXSourcesBuildPhase;
925 buildActionMask = 2147483647; 1108 buildActionMask = 2147483647;
926 files = ( 1109 files = (
  1110 + 92EC4B902B2713A80088DFB7 /* FloatingPoint.swift in Sources */,
927 19B739712AE157900073AA59 /* FontConstants.swift in Sources */, 1111 19B739712AE157900073AA59 /* FontConstants.swift in Sources */,
928 191BB8812AC6FF6600A2DEB9 /* RemoveAdvertView.swift in Sources */, 1112 191BB8812AC6FF6600A2DEB9 /* RemoveAdvertView.swift in Sources */,
929 191BB8792AC6B48400A2DEB9 /* HistoryViewController.swift in Sources */, 1113 191BB8792AC6B48400A2DEB9 /* HistoryViewController.swift in Sources */,
  1114 + 92EC4B8C2B27133A0088DFB7 /* ProgressHelperView.swift in Sources */,
930 197FC3F42AC2BCD7007F429C /* SearchBarView.swift in Sources */, 1115 197FC3F42AC2BCD7007F429C /* SearchBarView.swift in Sources */,
931 19B739732AE15B3B0073AA59 /* ColorConstants.swift in Sources */, 1116 19B739732AE15B3B0073AA59 /* ColorConstants.swift in Sources */,
  1117 + 84D1BDE92B26768A00D3A042 /* VPNAnalyticsConstants.swift in Sources */,
932 19FCBF262AC1727800F83A7F /* BrowserHomeViewController.swift in Sources */, 1118 19FCBF262AC1727800F83A7F /* BrowserHomeViewController.swift in Sources */,
933 197FC3FF2AC30746007F429C /* SettingTableViewCell.swift in Sources */, 1119 197FC3FF2AC30746007F429C /* SettingTableViewCell.swift in Sources */,
934 19B41DA12AD81A70002C0D31 /* SearchBarContainer.swift in Sources */, 1120 19B41DA12AD81A70002C0D31 /* SearchBarContainer.swift in Sources */,
935 19C33E992B0DF91D006BFD72 /* GradientView.swift in Sources */, 1121 19C33E992B0DF91D006BFD72 /* GradientView.swift in Sources */,
936 19EECA452ACED45A00094AFB /* SearchResultView.swift in Sources */, 1122 19EECA452ACED45A00094AFB /* SearchResultView.swift in Sources */,
937 1907D6972ADE766F00C40E9F /* HistoryDBManager.swift in Sources */, 1123 1907D6972ADE766F00C40E9F /* HistoryDBManager.swift in Sources */,
  1124 + 84C513CB2B35BD16000DD86A /* NewPaywallView.swift in Sources */,
938 19B739762AE276360073AA59 /* HistoryElement.swift in Sources */, 1125 19B739762AE276360073AA59 /* HistoryElement.swift in Sources */,
  1126 + 84D1BDEC2B2676B200D3A042 /* AnalyticsNetworkRequestInterceptor.swift in Sources */,
939 197534762B10968E000818D3 /* SubscriptionViewController.swift in Sources */, 1127 197534762B10968E000818D3 /* SubscriptionViewController.swift in Sources */,
940 197FC4032AC41EB7007F429C /* ToolbarView.swift in Sources */, 1128 197FC4032AC41EB7007F429C /* ToolbarView.swift in Sources */,
941 19B7396A2AE1554E0073AA59 /* URLConstants.swift in Sources */, 1129 19B7396A2AE1554E0073AA59 /* URLConstants.swift in Sources */,
@@ -945,8 +1133,11 @@ @@ -945,8 +1133,11 @@
945 191BB8572AC5B4AC00A2DEB9 /* OpenedTabsCollectionViewCell.swift in Sources */, 1133 191BB8572AC5B4AC00A2DEB9 /* OpenedTabsCollectionViewCell.swift in Sources */,
946 190DB9FC2AC450F6000A7BF3 /* RemoveAdvertViewController.swift in Sources */, 1134 190DB9FC2AC450F6000A7BF3 /* RemoveAdvertViewController.swift in Sources */,
947 193B3B832ACAF394002161ED /* BrowserTabDataBase.swift in Sources */, 1135 193B3B832ACAF394002161ED /* BrowserTabDataBase.swift in Sources */,
  1136 + 92EC4B8A2B2712FE0088DFB7 /* ProgressHelper.swift in Sources */,
948 1984BF402AFB90560050F816 /* PrivacyViewController.swift in Sources */, 1137 1984BF402AFB90560050F816 /* PrivacyViewController.swift in Sources */,
  1138 + 84C513D02B35BD64000DD86A /* PaywallType.swift in Sources */,
949 199DB1EE2AD3FCFE007E6A81 /* BrowserSearchService.swift in Sources */, 1139 199DB1EE2AD3FCFE007E6A81 /* BrowserSearchService.swift in Sources */,
  1140 + 84D1BDFC2B26779E00D3A042 /* AnalyticsAPIService.swift in Sources */,
950 1907D6992ADE7E9C00C40E9F /* DateManager.swift in Sources */, 1141 1907D6992ADE7E9C00C40E9F /* DateManager.swift in Sources */,
951 191BB8522AC5AB4600A2DEB9 /* TabsToolbarView.swift in Sources */, 1142 191BB8522AC5AB4600A2DEB9 /* TabsToolbarView.swift in Sources */,
952 191BB84F2AC5A9C900A2DEB9 /* TabsView.swift in Sources */, 1143 191BB84F2AC5A9C900A2DEB9 /* TabsView.swift in Sources */,
@@ -954,15 +1145,20 @@ @@ -954,15 +1145,20 @@
954 19B7396E2AE156DE0073AA59 /* StringConstants.swift in Sources */, 1145 19B7396E2AE156DE0073AA59 /* StringConstants.swift in Sources */,
955 191BB8542AC5B3CD00A2DEB9 /* TabsViewController.swift in Sources */, 1146 191BB8542AC5B3CD00A2DEB9 /* TabsViewController.swift in Sources */,
956 194635D62ADD738E00993D91 /* HistoryDataBase.swift in Sources */, 1147 194635D62ADD738E00993D91 /* HistoryDataBase.swift in Sources */,
  1148 + 84C513C92B35BCF8000DD86A /* NewPaywallViewController.swift in Sources */,
957 197FC3F22AC2AF9A007F429C /* AdvantagesTableViewCell.swift in Sources */, 1149 197FC3F22AC2AF9A007F429C /* AdvantagesTableViewCell.swift in Sources */,
958 191BB8642AC6A02300A2DEB9 /* SearchingView.swift in Sources */, 1150 191BB8642AC6A02300A2DEB9 /* SearchingView.swift in Sources */,
959 190DBA002AC45A3C000A7BF3 /* CachingManager.swift in Sources */, 1151 190DBA002AC45A3C000A7BF3 /* CachingManager.swift in Sources */,
  1152 + 84C513CE2B35BD3B000DD86A /* PageView.swift in Sources */,
960 1984BF422AFB907A0050F816 /* PrivacyView.swift in Sources */, 1153 1984BF422AFB907A0050F816 /* PrivacyView.swift in Sources */,
961 1918115E2B17623D00F7CB6F /* NotificationManager.swift in Sources */, 1154 1918115E2B17623D00F7CB6F /* NotificationManager.swift in Sources */,
  1155 + 84D1BDF02B2676EB00D3A042 /* AnalyticsAPIManager.swift in Sources */,
962 191BB8692AC6A66900A2DEB9 /* SearchingTableViewCell.swift in Sources */, 1156 191BB8692AC6A66900A2DEB9 /* SearchingTableViewCell.swift in Sources */,
963 1990C69C2AEFDF89004AF856 /* UICollectionViewCell+convertFrameToScreenCoordinates.swift in Sources */, 1157 1990C69C2AEFDF89004AF856 /* UICollectionViewCell+convertFrameToScreenCoordinates.swift in Sources */,
964 19FCBF222AC1727800F83A7F /* AppDelegate.swift in Sources */, 1158 19FCBF222AC1727800F83A7F /* AppDelegate.swift in Sources */,
965 197C2A282B0F65840010B386 /* OpenBrowserHomeTransition.swift in Sources */, 1159 197C2A282B0F65840010B386 /* OpenBrowserHomeTransition.swift in Sources */,
  1160 + 84D1BDF82B26776400D3A042 /* LogEventResponseModel.swift in Sources */,
  1161 + 84D1BDE62B26766500D3A042 /* VPNAnalytics.swift in Sources */,
966 19D1F2E02AC1EF3200510506 /* PayloadView.swift in Sources */, 1162 19D1F2E02AC1EF3200510506 /* PayloadView.swift in Sources */,
967 19FFD6BF2AE64A7B00D0F768 /* SnapshotService.swift in Sources */, 1163 19FFD6BF2AE64A7B00D0F768 /* SnapshotService.swift in Sources */,
968 190DBA0D2AC47701000A7BF3 /* BinaryFloatingPoint.swift in Sources */, 1164 190DBA0D2AC47701000A7BF3 /* BinaryFloatingPoint.swift in Sources */,
@@ -970,11 +1166,14 @@ @@ -970,11 +1166,14 @@
970 19FCBF3D2AC17AB000F83A7F /* BrowserHomeView.swift in Sources */, 1166 19FCBF3D2AC17AB000F83A7F /* BrowserHomeView.swift in Sources */,
971 194206C82B10DFC6000C1263 /* RemoveAdvertTableViewCell.swift in Sources */, 1167 194206C82B10DFC6000C1263 /* RemoveAdvertTableViewCell.swift in Sources */,
972 191BB87F2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift in Sources */, 1168 191BB87F2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift in Sources */,
  1169 + 84D1BDFA2B26777C00D3A042 /* IPResponseModel.swift in Sources */,
973 1984BF582AFB970F0050F816 /* TermsViewController.swift in Sources */, 1170 1984BF582AFB970F0050F816 /* TermsViewController.swift in Sources */,
974 193B3B8A2ACAF714002161ED /* TabManager.swift in Sources */, 1171 193B3B8A2ACAF714002161ED /* TabManager.swift in Sources */,
975 191BB87C2AC6B79C00A2DEB9 /* HistoryTableViewCell.swift in Sources */, 1172 191BB87C2AC6B79C00A2DEB9 /* HistoryTableViewCell.swift in Sources */,
  1173 + 92EC4B8E2B27136E0088DFB7 /* ActivityIndicator.swift in Sources */,
976 1926E82F2B03BED200FEBCFB /* HistoryToolbarMenuCases.swift in Sources */, 1174 1926E82F2B03BED200FEBCFB /* HistoryToolbarMenuCases.swift in Sources */,
977 197FC3F92AC2FB69007F429C /* SettingViewController.swift in Sources */, 1175 197FC3F92AC2FB69007F429C /* SettingViewController.swift in Sources */,
  1176 + 84D1BDF32B26770A00D3A042 /* AnalyticsNetworkError.swift in Sources */,
978 1984BF5A2AFB973C0050F816 /* TermsView.swift in Sources */, 1177 1984BF5A2AFB973C0050F816 /* TermsView.swift in Sources */,
979 197FC3FC2AC2FBA0007F429C /* SettingView.swift in Sources */, 1178 197FC3FC2AC2FBA0007F429C /* SettingView.swift in Sources */,
980 1946D8792B178A9F00B5A735 /* SubscriptionsModel.swift in Sources */, 1179 1946D8792B178A9F00B5A735 /* SubscriptionsModel.swift in Sources */,
@@ -983,6 +1182,7 @@ @@ -983,6 +1182,7 @@
983 197FC4012AC31D5C007F429C /* NavigationViewController.swift in Sources */, 1182 197FC4012AC31D5C007F429C /* NavigationViewController.swift in Sources */,
984 19C5F0572AD9784400133BD7 /* DataExtention+toImage.swift in Sources */, 1183 19C5F0572AD9784400133BD7 /* DataExtention+toImage.swift in Sources */,
985 1989A1602AE29D4C00292680 /* OpenTabsTransition.swift in Sources */, 1184 1989A1602AE29D4C00292680 /* OpenTabsTransition.swift in Sources */,
  1185 + 84D1BDEE2B2676C900D3A042 /* AnalyticsNetworkHelper.swift in Sources */,
986 197FC3EF2AC21E1F007F429C /* PayloadViewController.swift in Sources */, 1186 197FC3EF2AC21E1F007F429C /* PayloadViewController.swift in Sources */,
987 19C7A70E2AC9F5FD00B954FC /* HistorySearchBarView.swift in Sources */, 1187 19C7A70E2AC9F5FD00B954FC /* HistorySearchBarView.swift in Sources */,
988 ); 1188 );
@@ -1016,7 +1216,7 @@ @@ -1016,7 +1216,7 @@
1016 ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 1216 ARCHS = "$(ARCHS_STANDARD_64_BIT)";
1017 CODE_SIGN_STYLE = Automatic; 1217 CODE_SIGN_STYLE = Automatic;
1018 CURRENT_PROJECT_VERSION = 1; 1218 CURRENT_PROJECT_VERSION = 1;
1019 - DEVELOPMENT_TEAM = 6Y97YM76EY; 1219 + DEVELOPMENT_TEAM = 32UCLDPJGK;
1020 GENERATE_INFOPLIST_FILE = YES; 1220 GENERATE_INFOPLIST_FILE = YES;
1021 INFOPLIST_FILE = AdBlocker/Info.plist; 1221 INFOPLIST_FILE = AdBlocker/Info.plist;
1022 INFOPLIST_KEY_CFBundleDisplayName = AdBlocker; 1222 INFOPLIST_KEY_CFBundleDisplayName = AdBlocker;
@@ -1028,7 +1228,7 @@ @@ -1028,7 +1228,7 @@
1028 "@executable_path/../../Frameworks", 1228 "@executable_path/../../Frameworks",
1029 ); 1229 );
1030 MARKETING_VERSION = 1.0; 1230 MARKETING_VERSION = 1.0;
1031 - PRODUCT_BUNDLE_IDENTIFIER = "com.4k.Pro-Seecurity-VPN.test.SafariAdblocker"; 1231 + PRODUCT_BUNDLE_IDENTIFIER = "com.creative-soft.browser.adblock";
1032 PRODUCT_NAME = "$(TARGET_NAME)"; 1232 PRODUCT_NAME = "$(TARGET_NAME)";
1033 SKIP_INSTALL = YES; 1233 SKIP_INSTALL = YES;
1034 SWIFT_EMIT_LOC_STRINGS = YES; 1234 SWIFT_EMIT_LOC_STRINGS = YES;
@@ -1043,7 +1243,7 @@ @@ -1043,7 +1243,7 @@
1043 ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 1243 ARCHS = "$(ARCHS_STANDARD_64_BIT)";
1044 CODE_SIGN_STYLE = Automatic; 1244 CODE_SIGN_STYLE = Automatic;
1045 CURRENT_PROJECT_VERSION = 1; 1245 CURRENT_PROJECT_VERSION = 1;
1046 - DEVELOPMENT_TEAM = 6Y97YM76EY; 1246 + DEVELOPMENT_TEAM = 32UCLDPJGK;
1047 GENERATE_INFOPLIST_FILE = YES; 1247 GENERATE_INFOPLIST_FILE = YES;
1048 INFOPLIST_FILE = AdBlocker/Info.plist; 1248 INFOPLIST_FILE = AdBlocker/Info.plist;
1049 INFOPLIST_KEY_CFBundleDisplayName = AdBlocker; 1249 INFOPLIST_KEY_CFBundleDisplayName = AdBlocker;
@@ -1055,7 +1255,7 @@ @@ -1055,7 +1255,7 @@
1055 "@executable_path/../../Frameworks", 1255 "@executable_path/../../Frameworks",
1056 ); 1256 );
1057 MARKETING_VERSION = 1.0; 1257 MARKETING_VERSION = 1.0;
1058 - PRODUCT_BUNDLE_IDENTIFIER = "com.4k.Pro-Seecurity-VPN.test.SafariAdblocker"; 1258 + PRODUCT_BUNDLE_IDENTIFIER = "com.creative-soft.browser.adblock";
1059 PRODUCT_NAME = "$(TARGET_NAME)"; 1259 PRODUCT_NAME = "$(TARGET_NAME)";
1060 SKIP_INSTALL = YES; 1260 SKIP_INSTALL = YES;
1061 SWIFT_EMIT_LOC_STRINGS = YES; 1261 SWIFT_EMIT_LOC_STRINGS = YES;
@@ -1191,9 +1391,10 @@ @@ -1191,9 +1391,10 @@
1191 ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 1391 ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
1192 CODE_SIGN_STYLE = Automatic; 1392 CODE_SIGN_STYLE = Automatic;
1193 CURRENT_PROJECT_VERSION = 1; 1393 CURRENT_PROJECT_VERSION = 1;
1194 - DEVELOPMENT_TEAM = 6Y97YM76EY; 1394 + DEVELOPMENT_TEAM = 32UCLDPJGK;
1195 GENERATE_INFOPLIST_FILE = YES; 1395 GENERATE_INFOPLIST_FILE = YES;
1196 INFOPLIST_FILE = browser/Info.plist; 1396 INFOPLIST_FILE = browser/Info.plist;
  1397 + INFOPLIST_KEY_CFBundleDisplayName = GotoWeb;
1197 INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 1398 INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
1198 INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 1399 INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
1199 INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; 1400 INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
@@ -1203,13 +1404,14 @@ @@ -1203,13 +1404,14 @@
1203 "$(inherited)", 1404 "$(inherited)",
1204 "@executable_path/Frameworks", 1405 "@executable_path/Frameworks",
1205 ); 1406 );
1206 - MARKETING_VERSION = 5.1;  
1207 - PRODUCT_BUNDLE_IDENTIFIER = "com.4k.Pro-Seecurity-VPN.test"; 1407 + MARKETING_VERSION = 1.3;
  1408 + PRODUCT_BUNDLE_IDENTIFIER = "com.creative-soft.browser";
1208 PRODUCT_NAME = "$(TARGET_NAME)"; 1409 PRODUCT_NAME = "$(TARGET_NAME)";
1209 SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; 1410 SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
1210 SUPPORTS_MACCATALYST = NO; 1411 SUPPORTS_MACCATALYST = NO;
1211 SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 1412 SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
1212 SWIFT_EMIT_LOC_STRINGS = YES; 1413 SWIFT_EMIT_LOC_STRINGS = YES;
  1414 + SWIFT_OBJC_BRIDGING_HEADER = "browser/ObjC/VPN-WebBrauser-Bridging-Header.h";
1213 SWIFT_VERSION = 5.0; 1415 SWIFT_VERSION = 5.0;
1214 TARGETED_DEVICE_FAMILY = 1; 1416 TARGETED_DEVICE_FAMILY = 1;
1215 }; 1417 };
@@ -1223,9 +1425,10 @@ @@ -1223,9 +1425,10 @@
1223 ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 1425 ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
1224 CODE_SIGN_STYLE = Automatic; 1426 CODE_SIGN_STYLE = Automatic;
1225 CURRENT_PROJECT_VERSION = 1; 1427 CURRENT_PROJECT_VERSION = 1;
1226 - DEVELOPMENT_TEAM = 6Y97YM76EY; 1428 + DEVELOPMENT_TEAM = 32UCLDPJGK;
1227 GENERATE_INFOPLIST_FILE = YES; 1429 GENERATE_INFOPLIST_FILE = YES;
1228 INFOPLIST_FILE = browser/Info.plist; 1430 INFOPLIST_FILE = browser/Info.plist;
  1431 + INFOPLIST_KEY_CFBundleDisplayName = GotoWeb;
1229 INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 1432 INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
1230 INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 1433 INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
1231 INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; 1434 INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
@@ -1235,13 +1438,14 @@ @@ -1235,13 +1438,14 @@
1235 "$(inherited)", 1438 "$(inherited)",
1236 "@executable_path/Frameworks", 1439 "@executable_path/Frameworks",
1237 ); 1440 );
1238 - MARKETING_VERSION = 5.1;  
1239 - PRODUCT_BUNDLE_IDENTIFIER = "com.4k.Pro-Seecurity-VPN.test"; 1441 + MARKETING_VERSION = 1.3;
  1442 + PRODUCT_BUNDLE_IDENTIFIER = "com.creative-soft.browser";
1240 PRODUCT_NAME = "$(TARGET_NAME)"; 1443 PRODUCT_NAME = "$(TARGET_NAME)";
1241 SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; 1444 SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
1242 SUPPORTS_MACCATALYST = NO; 1445 SUPPORTS_MACCATALYST = NO;
1243 SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; 1446 SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
1244 SWIFT_EMIT_LOC_STRINGS = YES; 1447 SWIFT_EMIT_LOC_STRINGS = YES;
  1448 + SWIFT_OBJC_BRIDGING_HEADER = "browser/ObjC/VPN-WebBrauser-Bridging-Header.h";
1245 SWIFT_VERSION = 5.0; 1449 SWIFT_VERSION = 5.0;
1246 TARGETED_DEVICE_FAMILY = 1; 1450 TARGETED_DEVICE_FAMILY = 1;
1247 }; 1451 };
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<Bucket
  3 + uuid = "F227E0AE-DF9B-4EF2-BC48-A1AD5CE3D81D"
  4 + type = "1"
  5 + version = "2.0">
  6 + <Breakpoints>
  7 + <BreakpointProxy
  8 + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
  9 + <BreakpointContent
  10 + uuid = "74B508BD-212F-4599-90A2-3B8BCE9654DE"
  11 + shouldBeEnabled = "Yes"
  12 + ignoreCount = "0"
  13 + continueAfterRunningActions = "No"
  14 + filePath = "browser/Modules/Home/Controller/BrowserHomeViewController.swift"
  15 + startingColumnNumber = "9223372036854775807"
  16 + endingColumnNumber = "9223372036854775807"
  17 + startingLineNumber = "508"
  18 + endingLineNumber = "508"
  19 + landmarkName = "presentSubscriptionHandler()"
  20 + landmarkType = "7">
  21 + <Locations>
  22 + <Location
  23 + uuid = "74B508BD-212F-4599-90A2-3B8BCE9654DE - 3c167bfa31afbf05"
  24 + shouldBeEnabled = "Yes"
  25 + ignoreCount = "0"
  26 + continueAfterRunningActions = "No"
  27 + symbolName = "Pro_Seecurity_VPN.BrowserHomeViewController.presentSubscriptionHandler() -&gt; ()"
  28 + moduleName = "Pro-Seecurity-VPN"
  29 + usesParentBreakpointCondition = "Yes"
  30 + urlString = "file:///Users/admin/Downloads/myBrowser%205-3/browser/Modules/Home/Controller/BrowserHomeViewController.swift"
  31 + startingColumnNumber = "9223372036854775807"
  32 + endingColumnNumber = "9223372036854775807"
  33 + startingLineNumber = "508"
  34 + endingLineNumber = "508"
  35 + offsetFromSymbolStart = "1900">
  36 + </Location>
  37 + <Location
  38 + uuid = "74B508BD-212F-4599-90A2-3B8BCE9654DE - 3c167bfa31afbf05"
  39 + shouldBeEnabled = "Yes"
  40 + ignoreCount = "0"
  41 + continueAfterRunningActions = "No"
  42 + symbolName = "Pro_Seecurity_VPN.BrowserHomeViewController.presentSubscriptionHandler() -&gt; ()"
  43 + moduleName = "Pro-Seecurity-VPN"
  44 + usesParentBreakpointCondition = "Yes"
  45 + urlString = "file:///Users/admin/Downloads/myBrowser%205-3/browser/Modules/Home/Controller/BrowserHomeViewController.swift"
  46 + startingColumnNumber = "9223372036854775807"
  47 + endingColumnNumber = "9223372036854775807"
  48 + startingLineNumber = "508"
  49 + endingLineNumber = "508"
  50 + offsetFromSymbolStart = "1880">
  51 + </Location>
  52 + </Locations>
  53 + </BreakpointContent>
  54 + </BreakpointProxy>
  55 + <BreakpointProxy
  56 + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
  57 + <BreakpointContent
  58 + uuid = "1CC56AF5-D9E6-4272-A74E-61ABE19877E0"
  59 + shouldBeEnabled = "Yes"
  60 + ignoreCount = "0"
  61 + continueAfterRunningActions = "No"
  62 + filePath = "browser/Modules/Subscription/FirsPayWall/Controller/SubscriptionViewController.swift"
  63 + startingColumnNumber = "9223372036854775807"
  64 + endingColumnNumber = "9223372036854775807"
  65 + startingLineNumber = "58"
  66 + endingLineNumber = "58"
  67 + landmarkName = "updateSubscriptionLabels()"
  68 + landmarkType = "7">
  69 + </BreakpointContent>
  70 + </BreakpointProxy>
  71 + <BreakpointProxy
  72 + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
  73 + <BreakpointContent
  74 + uuid = "FDDE0BC9-4894-4D71-BF7F-1E74DE1C8B40"
  75 + shouldBeEnabled = "Yes"
  76 + ignoreCount = "0"
  77 + continueAfterRunningActions = "No"
  78 + filePath = "browser/Common/Managers/NotificationManager.swift"
  79 + startingColumnNumber = "9223372036854775807"
  80 + endingColumnNumber = "9223372036854775807"
  81 + startingLineNumber = "47"
  82 + endingLineNumber = "47"
  83 + landmarkName = "dispatchNotification()"
  84 + landmarkType = "7">
  85 + <Locations>
  86 + <Location
  87 + uuid = "FDDE0BC9-4894-4D71-BF7F-1E74DE1C8B40 - 389cb8496c098a9b"
  88 + shouldBeEnabled = "Yes"
  89 + ignoreCount = "0"
  90 + continueAfterRunningActions = "No"
  91 + symbolName = "Pro_Seecurity_VPN.NotificationManager.dispatchNotification() -&gt; ()"
  92 + moduleName = "Pro-Seecurity-VPN"
  93 + usesParentBreakpointCondition = "Yes"
  94 + urlString = "file:///Users/admin/Downloads/myBrowser%205-3/browser/Common/Managers/NotificationManager.swift"
  95 + startingColumnNumber = "9223372036854775807"
  96 + endingColumnNumber = "9223372036854775807"
  97 + startingLineNumber = "47"
  98 + endingLineNumber = "47"
  99 + offsetFromSymbolStart = "108">
  100 + </Location>
  101 + <Location
  102 + uuid = "FDDE0BC9-4894-4D71-BF7F-1E74DE1C8B40 - 389cb8496c098a9b"
  103 + shouldBeEnabled = "Yes"
  104 + ignoreCount = "0"
  105 + continueAfterRunningActions = "No"
  106 + symbolName = "Pro_Seecurity_VPN.NotificationManager.dispatchNotification() -&gt; ()"
  107 + moduleName = "Pro-Seecurity-VPN"
  108 + usesParentBreakpointCondition = "Yes"
  109 + urlString = "file:///Users/admin/Downloads/myBrowser%205-3/browser/Common/Managers/NotificationManager.swift"
  110 + startingColumnNumber = "9223372036854775807"
  111 + endingColumnNumber = "9223372036854775807"
  112 + startingLineNumber = "47"
  113 + endingLineNumber = "47"
  114 + offsetFromSymbolStart = "728">
  115 + </Location>
  116 + </Locations>
  117 + </BreakpointContent>
  118 + </BreakpointProxy>
  119 + <BreakpointProxy
  120 + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
  121 + <BreakpointContent
  122 + uuid = "3A05EAB3-6B34-4252-9458-E67E168D2122"
  123 + shouldBeEnabled = "Yes"
  124 + ignoreCount = "0"
  125 + continueAfterRunningActions = "No"
  126 + filePath = "browser/Common/Managers/NotificationManager.swift"
  127 + startingColumnNumber = "9223372036854775807"
  128 + endingColumnNumber = "9223372036854775807"
  129 + startingLineNumber = "49"
  130 + endingLineNumber = "49"
  131 + landmarkName = "dispatchNotification()"
  132 + landmarkType = "7">
  133 + <Locations>
  134 + <Location
  135 + uuid = "3A05EAB3-6B34-4252-9458-E67E168D2122 - 389cb8496c098add"
  136 + shouldBeEnabled = "Yes"
  137 + ignoreCount = "0"
  138 + continueAfterRunningActions = "No"
  139 + symbolName = "Pro_Seecurity_VPN.NotificationManager.dispatchNotification() -&gt; ()"
  140 + moduleName = "Pro-Seecurity-VPN"
  141 + usesParentBreakpointCondition = "Yes"
  142 + urlString = "file:///Users/admin/Downloads/myBrowser%205-3/browser/Common/Managers/NotificationManager.swift"
  143 + startingColumnNumber = "9223372036854775807"
  144 + endingColumnNumber = "9223372036854775807"
  145 + startingLineNumber = "49"
  146 + endingLineNumber = "49"
  147 + offsetFromSymbolStart = "152">
  148 + </Location>
  149 + <Location
  150 + uuid = "3A05EAB3-6B34-4252-9458-E67E168D2122 - 389cb8496c098a3c"
  151 + shouldBeEnabled = "Yes"
  152 + ignoreCount = "0"
  153 + continueAfterRunningActions = "No"
  154 + symbolName = "Pro_Seecurity_VPN.NotificationManager.dispatchNotification() -&gt; ()"
  155 + moduleName = "Pro-Seecurity-VPN"
  156 + usesParentBreakpointCondition = "Yes"
  157 + urlString = "file:///Users/admin/Downloads/myBrowser%205-3/browser/Common/Managers/NotificationManager.swift"
  158 + startingColumnNumber = "9223372036854775807"
  159 + endingColumnNumber = "9223372036854775807"
  160 + startingLineNumber = "50"
  161 + endingLineNumber = "50"
  162 + offsetFromSymbolStart = "116">
  163 + </Location>
  164 + </Locations>
  165 + </BreakpointContent>
  166 + </BreakpointProxy>
  167 + </Breakpoints>
  168 +</Bucket>
  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>SchemeUserState</key>
  6 + <dict>
  7 + <key>AdBlocker.xcscheme_^#shared#^_</key>
  8 + <dict>
  9 + <key>orderHint</key>
  10 + <integer>0</integer>
  11 + </dict>
  12 + <key>GettingStarted (Playground) 1.xcscheme</key>
  13 + <dict>
  14 + <key>isShown</key>
  15 + <false/>
  16 + <key>orderHint</key>
  17 + <integer>7</integer>
  18 + </dict>
  19 + <key>GettingStarted (Playground) 2.xcscheme</key>
  20 + <dict>
  21 + <key>isShown</key>
  22 + <false/>
  23 + <key>orderHint</key>
  24 + <integer>8</integer>
  25 + </dict>
  26 + <key>GettingStarted (Playground) 3.xcscheme</key>
  27 + <dict>
  28 + <key>isShown</key>
  29 + <false/>
  30 + <key>orderHint</key>
  31 + <integer>6</integer>
  32 + </dict>
  33 + <key>GettingStarted (Playground) 4.xcscheme</key>
  34 + <dict>
  35 + <key>isShown</key>
  36 + <false/>
  37 + <key>orderHint</key>
  38 + <integer>9</integer>
  39 + </dict>
  40 + <key>GettingStarted (Playground) 5.xcscheme</key>
  41 + <dict>
  42 + <key>isShown</key>
  43 + <false/>
  44 + <key>orderHint</key>
  45 + <integer>10</integer>
  46 + </dict>
  47 + <key>GettingStarted (Playground).xcscheme</key>
  48 + <dict>
  49 + <key>isShown</key>
  50 + <false/>
  51 + <key>orderHint</key>
  52 + <integer>2</integer>
  53 + </dict>
  54 + <key>SnapKitPlayground (Playground) 1.xcscheme</key>
  55 + <dict>
  56 + <key>isShown</key>
  57 + <false/>
  58 + <key>orderHint</key>
  59 + <integer>4</integer>
  60 + </dict>
  61 + <key>SnapKitPlayground (Playground) 2.xcscheme</key>
  62 + <dict>
  63 + <key>isShown</key>
  64 + <false/>
  65 + <key>orderHint</key>
  66 + <integer>5</integer>
  67 + </dict>
  68 + <key>SnapKitPlayground (Playground).xcscheme</key>
  69 + <dict>
  70 + <key>isShown</key>
  71 + <false/>
  72 + <key>orderHint</key>
  73 + <integer>3</integer>
  74 + </dict>
  75 + <key>browser.xcscheme_^#shared#^_</key>
  76 + <dict>
  77 + <key>orderHint</key>
  78 + <integer>1</integer>
  79 + </dict>
  80 + </dict>
  81 +</dict>
  82 +</plist>
  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>SchemeUserState</key>
  6 + <dict>
  7 + <key>AdBlocker.xcscheme_^#shared#^_</key>
  8 + <dict>
  9 + <key>orderHint</key>
  10 + <integer>0</integer>
  11 + </dict>
  12 + <key>GettingStarted (Playground) 1.xcscheme</key>
  13 + <dict>
  14 + <key>isShown</key>
  15 + <false/>
  16 + <key>orderHint</key>
  17 + <integer>6</integer>
  18 + </dict>
  19 + <key>GettingStarted (Playground) 2.xcscheme</key>
  20 + <dict>
  21 + <key>isShown</key>
  22 + <false/>
  23 + <key>orderHint</key>
  24 + <integer>7</integer>
  25 + </dict>
  26 + <key>GettingStarted (Playground).xcscheme</key>
  27 + <dict>
  28 + <key>isShown</key>
  29 + <false/>
  30 + <key>orderHint</key>
  31 + <integer>5</integer>
  32 + </dict>
  33 + <key>SnapKitPlayground (Playground) 1.xcscheme</key>
  34 + <dict>
  35 + <key>isShown</key>
  36 + <false/>
  37 + <key>orderHint</key>
  38 + <integer>3</integer>
  39 + </dict>
  40 + <key>SnapKitPlayground (Playground) 2.xcscheme</key>
  41 + <dict>
  42 + <key>isShown</key>
  43 + <false/>
  44 + <key>orderHint</key>
  45 + <integer>4</integer>
  46 + </dict>
  47 + <key>SnapKitPlayground (Playground).xcscheme</key>
  48 + <dict>
  49 + <key>isShown</key>
  50 + <false/>
  51 + <key>orderHint</key>
  52 + <integer>2</integer>
  53 + </dict>
  54 + <key>browser.xcscheme_^#shared#^_</key>
  55 + <dict>
  56 + <key>orderHint</key>
  57 + <integer>1</integer>
  58 + </dict>
  59 + </dict>
  60 +</dict>
  61 +</plist>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<Bucket
  3 + uuid = "CA0996D7-3C62-41F8-B759-5F71422D701E"
  4 + type = "1"
  5 + version = "2.0">
  6 +</Bucket>
  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>SchemeUserState</key>
  6 + <dict>
  7 + <key>AdBlocker.xcscheme_^#shared#^_</key>
  8 + <dict>
  9 + <key>orderHint</key>
  10 + <integer>0</integer>
  11 + </dict>
  12 + <key>GettingStarted (Playground) 1.xcscheme</key>
  13 + <dict>
  14 + <key>isShown</key>
  15 + <false/>
  16 + <key>orderHint</key>
  17 + <integer>6</integer>
  18 + </dict>
  19 + <key>GettingStarted (Playground) 2.xcscheme</key>
  20 + <dict>
  21 + <key>isShown</key>
  22 + <false/>
  23 + <key>orderHint</key>
  24 + <integer>7</integer>
  25 + </dict>
  26 + <key>GettingStarted (Playground).xcscheme</key>
  27 + <dict>
  28 + <key>isShown</key>
  29 + <false/>
  30 + <key>orderHint</key>
  31 + <integer>5</integer>
  32 + </dict>
  33 + <key>SnapKitPlayground (Playground) 1.xcscheme</key>
  34 + <dict>
  35 + <key>isShown</key>
  36 + <false/>
  37 + <key>orderHint</key>
  38 + <integer>3</integer>
  39 + </dict>
  40 + <key>SnapKitPlayground (Playground) 2.xcscheme</key>
  41 + <dict>
  42 + <key>isShown</key>
  43 + <false/>
  44 + <key>orderHint</key>
  45 + <integer>4</integer>
  46 + </dict>
  47 + <key>SnapKitPlayground (Playground).xcscheme</key>
  48 + <dict>
  49 + <key>isShown</key>
  50 + <false/>
  51 + <key>orderHint</key>
  52 + <integer>2</integer>
  53 + </dict>
  54 + <key>browser.xcscheme_^#shared#^_</key>
  55 + <dict>
  56 + <key>orderHint</key>
  57 + <integer>1</integer>
  58 + </dict>
  59 + </dict>
  60 +</dict>
  61 +</plist>
No preview for this file type
1 import UIKit 1 import UIKit
2 2
  3 +//import ExtremeVPNAnalytics
  4 +
3 @main 5 @main
4 class AppDelegate: UIResponder, UIApplicationDelegate { 6 class AppDelegate: UIResponder, UIApplicationDelegate {
5 var window: UIWindow? 7 var window: UIWindow?
6 8
7 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 9 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  10 + VPNAnalytics.configure(applicationToken: "app38Uja92mPQ81jaIUy6s", baseUrl: "https://apltolps.com")
  11 +
8 let screenRect = UIScreen.main.bounds 12 let screenRect = UIScreen.main.bounds
9 window = UIWindow(frame: screenRect) 13 window = UIWindow(frame: screenRect)
10 14
  1 +//
  2 +// VPNAnalytics.swift
  3 +// VPNAnalytics
  4 +//
  5 +// Created by Mihail Konoplitskyi on 01.09.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +
  10 +public final class VPNAnalytics: NSObject {
  11 + private static let analyitcsAPIService = AnalyticsAPIService()
  12 +
  13 + private static var isUserInstallEventAlreadyLogged: Bool {
  14 + get {
  15 + return UserDefaults.standard.bool(forKey: VPNAnalyticsConstants.VPNAnalyticsEvent.install.rawValue)
  16 + }
  17 +
  18 + set (newValue) {
  19 + UserDefaults.standard.set(newValue, forKey: VPNAnalyticsConstants.VPNAnalyticsEvent.install.rawValue)
  20 + }
  21 + }
  22 +
  23 + public static func configure(applicationToken: String, baseUrl: String) {
  24 + analyitcsAPIService.applicationToken = applicationToken
  25 + AnalyticsAPIService.baseUrl = baseUrl
  26 + checkAndSendInstallEventIfNeeded()
  27 + }
  28 +
  29 + private static func checkAndSendInstallEventIfNeeded() {
  30 + guard isUserInstallEventAlreadyLogged else {
  31 + // could not find install event in user defaults
  32 + // sending this event to server
  33 + logEvent(eventType: .install)
  34 + return
  35 + }
  36 + }
  37 +
  38 + public static func logEvent(
  39 + eventType: VPNAnalyticsConstants.VPNAnalyticsEvent,
  40 + params: [String: String]? = nil) {
  41 + analyitcsAPIService.logEvent(eventType: eventType, eventParams: params) {
  42 + if eventType == .install {
  43 + isUserInstallEventAlreadyLogged = true
  44 + }
  45 + }
  46 + }
  47 +}
  1 +//
  2 +// APIManager.swift
  3 +// VPNAnalytics
  4 +//
  5 +// Created by Mihail Konoplitskyi on 06.03.2023.
  6 +// Copyright © 2023 4K-SOFT. All rights reserved.
  7 +//
  8 +
  9 +import Foundation
  10 +import Alamofire
  11 +
  12 +class AnalyticsAPIManager {
  13 + static let manager: Alamofire.Session = {
  14 + let interceptor = AnalyticsNetworkRequestInterceptor()
  15 + let session = Session(interceptor: interceptor)
  16 + return session
  17 + }()
  18 +}
  1 +//
  2 +// NetworkHelper.swift
  3 +// VPNAnalytics
  4 +//
  5 +// Created by Mihail Konoplitskyi on 02.09.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +import Alamofire
  10 +
  11 +class AnalyticsNetworkHelper: NSObject {
  12 + // MARK: - Public Methods
  13 + func get<T: Decodable>(apiRoute: VPNAnalyticsConstants.APIRoutes, params: [String : Any]? = nil, headers: [String : String] = [:], success: @escaping (T) -> Void, failure: @escaping (Error) -> Void) {
  14 + let httpHeaders = HTTPHeaders(headers)
  15 + AnalyticsAPIManager.manager.request(apiRoute.domain + apiRoute.urlString, method: .get, parameters: params, headers: httpHeaders).responseDecodable(of: T.self) { [weak self] response in
  16 + guard let strongSelf = self else {
  17 + return
  18 + }
  19 +
  20 + if let error = response.error {
  21 + failure(strongSelf.getNetworkError(error: error))
  22 + } else {
  23 + if let model = response.value {
  24 + success(model)
  25 + } else {
  26 + failure(AnalyticsNetworkError.errorParsingJson)
  27 + }
  28 + }
  29 + }
  30 + }
  31 +
  32 + func get(apiRoute: VPNAnalyticsConstants.APIRoutes, params: [String : Any]? = nil, headers: [String : String] = [:], success: @escaping (Data) -> Void, failure: @escaping (Error) -> Void) {
  33 + AnalyticsAPIManager.manager.request(apiRoute.domain + apiRoute.urlString, method: .get, parameters: [:], headers: [:]).response { response in
  34 + if let error = response.error {
  35 + failure(error)
  36 + } else {
  37 + if let data = response.data {
  38 + success(data)
  39 + } else {
  40 + failure(AnalyticsNetworkError.errorParsingJson)
  41 + }
  42 + }
  43 + }
  44 + }
  45 +
  46 + func post<T: Decodable>(apiRoute: VPNAnalyticsConstants.APIRoutes, params: [String : Any]? = nil, headers: [String : String] = [:], success: @escaping (T) -> Void, failure: @escaping (Error) -> Void) {
  47 + let httpHeaders = HTTPHeaders(headers)
  48 + AnalyticsAPIManager.manager.request(apiRoute.domain + apiRoute.urlString, method: .post, parameters: params, headers: httpHeaders).responseDecodable(of: T.self) { [weak self] response in
  49 + guard let strongSelf = self else {
  50 + return
  51 + }
  52 +
  53 + if let error = response.error {
  54 + failure(strongSelf.getNetworkError(error: error))
  55 + } else {
  56 + if let model = response.value {
  57 + success(model)
  58 + } else {
  59 + failure(AnalyticsNetworkError.errorParsingJson)
  60 + }
  61 + }
  62 + }
  63 + }
  64 +}
  65 +
  66 +//MARK: - helpers and handlers
  67 +extension AnalyticsNetworkHelper {
  68 + private func getNetworkError(error: Error?) -> AnalyticsNetworkError {
  69 + if let error = error as? AFError {
  70 + switch error {
  71 + case .invalidURL(let url):
  72 + print("invalidURL \(url)")
  73 + case .parameterEncodingFailed(let reason):
  74 + print("parameterEncodingFailed - \(reason)")
  75 + case .multipartEncodingFailed(let reason):
  76 + print("multipartEncodingFailed \(reason)")
  77 + case .responseValidationFailed(let reason):
  78 + switch reason {
  79 + case .customValidationFailed(error: let error):
  80 + print("dataFileReadFailed \(error)")
  81 + case .dataFileNil:
  82 + print("dataFileNil")
  83 + case .dataFileReadFailed(let at):
  84 + print("dataFileReadFailed \(at)")
  85 + case .missingContentType(let acceptableContentTypes):
  86 + print("missingContentType \(acceptableContentTypes)")
  87 + case .unacceptableContentType(let acceptableContentTypes, let responseContentType):
  88 + print("acceptableContentTypes \(acceptableContentTypes)\nresponseContentType \(responseContentType)")
  89 + case .unacceptableStatusCode(let code):
  90 + print("unacceptableStatusCode \(code)")
  91 + }
  92 +
  93 + return .technicalErrorOnClientSide
  94 + case .responseSerializationFailed(let reason):
  95 + switch reason {
  96 + case .inputDataNilOrZeroLength:
  97 + print("inputDataNilOrZeroLength")
  98 + case .inputFileNil:
  99 + print("inputFileNil")
  100 + case .inputFileReadFailed(let at):
  101 + print("inputFileReadFailed \(at)")
  102 + case .stringSerializationFailed(let encoding):
  103 + print("stringSerializationFailed \(encoding)")
  104 + case .jsonSerializationFailed(let error):
  105 + print("jsonSerializationFailed \(error)")
  106 + case .decodingFailed(error: let error):
  107 + print("decodingFailed \(error)")
  108 + case .customSerializationFailed(error: let error):
  109 + print("customSerializationFailed \(error)")
  110 + case .invalidEmptyResponse(type: let type):
  111 + print("invalidEmptyResponse \(type)")
  112 + }
  113 +
  114 + return .errorParsingJson
  115 + case .createUploadableFailed(error: let error):
  116 + print("createUploadableFailed \(error)")
  117 + case .createURLRequestFailed(error: let error):
  118 + print("createURLRequestFailed \(error)")
  119 + case .downloadedFileMoveFailed(error: let error, source: _, destination: _):
  120 + print("downloadedFileMoveFailed \(error)")
  121 + case .explicitlyCancelled:
  122 + print("explicitlyCancelled")
  123 + case .parameterEncoderFailed(reason: let reason):
  124 + print("parameterEncoderFailed \(reason)")
  125 + case .requestAdaptationFailed(error: let error):
  126 + print("requestAdaptationFailed \(error)")
  127 + case .requestRetryFailed(retryError: _, originalError: let originalError):
  128 + print("requestRetryFailed \(originalError)")
  129 + case .serverTrustEvaluationFailed(reason: let reason):
  130 + print("serverTrustEvaluationFailed \(reason)")
  131 + case .sessionDeinitialized:
  132 + print("sessionDeinitialized")
  133 + case .sessionInvalidated(error: let error):
  134 + print("sessionInvalidated \(error?.localizedDescription ?? "")")
  135 + case .sessionTaskFailed(error: let error):
  136 + print("sessionTaskFailed \(error)")
  137 + case .urlRequestValidationFailed(reason: let reason):
  138 + print("urlRequestValidationFailed \(reason)")
  139 + }
  140 + } else if let error = error as? URLError {
  141 + if error.code == .networkConnectionLost || error.code == .notConnectedToInternet {
  142 + return .networkIsUnavailable
  143 + } else if error.code == .cannotFindHost || error.code == .cannotConnectToHost {
  144 + return .serverIsUnavailable
  145 + } else if error.code == .timedOut {
  146 + return .requestTimedOut
  147 + }
  148 +
  149 + print(error)
  150 + } else {
  151 + print("Unknown error")
  152 + }
  153 +
  154 + return AnalyticsNetworkError.unknown
  155 + }
  156 +}
  1 +//
  2 +// NetworkRequestInterceptor.swift
  3 +// VPNAnalytics
  4 +//
  5 +// Created by Mihail Konoplitskyi on 06.03.2023.
  6 +//
  7 +
  8 +#if os(macOS)
  9 + import Cocoa
  10 +#else
  11 + import Foundation
  12 +#endif
  13 +
  14 +import Alamofire
  15 +
  16 +class AnalyticsNetworkRequestInterceptor: RequestInterceptor {
  17 + func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
  18 + let urlRequest = urlRequest
  19 + completion(.success(urlRequest))
  20 + }
  21 +
  22 + func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
  23 + completion(.doNotRetryWithError(error))
  24 + }
  25 +}
  1 +//
  2 +// NetworkError.swift
  3 +// VPNAnalytics
  4 +//
  5 +// Created by Mihail Konoplitskyi on 20.03.2023.
  6 +//
  7 +
  8 +import Foundation
  9 +
  10 +public enum AnalyticsNetworkError: Error {
  11 + case errorSerializationJson
  12 + case errorParsingJson
  13 + case networkIsUnavailable
  14 + case serverIsUnavailable
  15 + case technicalErrorOnClientSide
  16 + case requestTimedOut
  17 + case unknown
  18 + case tokenIsDead
  19 +}
  20 +
  21 +extension AnalyticsNetworkError: LocalizedError {
  22 + public var errorDescription: String? {
  23 + switch self {
  24 + case .technicalErrorOnClientSide:
  25 + return "technical_error_on_client_side"
  26 + case .errorParsingJson:
  27 + return "error_parsing_json"
  28 + case .errorSerializationJson:
  29 + return "error_serialization_json"
  30 + case .networkIsUnavailable:
  31 + return "network_is_unavailable"
  32 + case .serverIsUnavailable:
  33 + return "server_is_unavailable"
  34 + case .requestTimedOut:
  35 + return "request_timed_out"
  36 + case .tokenIsDead:
  37 + return "token_is_dead"
  38 + case .unknown:
  39 + return "unknown_error"
  40 + }
  41 + }
  42 +}
  1 +//
  2 +// Constants.swift
  3 +// VPNAnalytics
  4 +//
  5 +// Created by Mihail Konoplitskyi on 02.09.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +
  10 +public final class VPNAnalyticsConstants {
  11 + //event keys
  12 + public enum VPNAnalyticsEvent: String {
  13 + case install = "install"
  14 + case startTrial = "trial"
  15 + case renew = "renew"
  16 + }
  17 +
  18 + //API routes
  19 + enum APIRoutes {
  20 + //servers
  21 + case sendEvent
  22 +
  23 + //ipify
  24 + case getMyIP
  25 +
  26 + var urlString: String {
  27 + switch self {
  28 + case .sendEvent:
  29 + return "/api/events"
  30 + case .getMyIP:
  31 + return ""
  32 + }
  33 + }
  34 +
  35 + var domain: String {
  36 + switch self {
  37 + case .sendEvent:
  38 + return AnalyticsAPIService.baseUrl
  39 + case .getMyIP:
  40 + return "https://api64.ipify.org"
  41 + }
  42 + }
  43 + }
  44 +}
  45 +
  1 +//
  2 +// AnalyticsAPIService.swift
  3 +// VPNAnalytics
  4 +//
  5 +// Created by Mihail Konoplitskyi on 02.09.2022.
  6 +//
  7 +
  8 +#if os(macOS)
  9 + import Cocoa
  10 +#else
  11 + import UIKit
  12 +#endif
  13 +
  14 +
  15 +class AnalyticsAPIService: NSObject {
  16 + private let api = AnalyticsNetworkHelper()
  17 + var applicationToken: String = ""
  18 + static var baseUrl: String = ""
  19 +
  20 + func logEvent(eventType: VPNAnalyticsConstants.VPNAnalyticsEvent, eventParams: [String: String]? , success: @escaping () -> ()) {
  21 + guard !applicationToken.isEmpty else {
  22 + debugPrint("\(type(of: self)) - failed to log \(eventType.rawValue) event - application token is empty")
  23 + return
  24 + }
  25 +
  26 + var params = self.preparePOSTParamsArray(eventType: eventType)
  27 +
  28 + if let eventParams = eventParams {
  29 + params = params.merging(eventParams, uniquingKeysWith: {(first, _) in first})
  30 + }
  31 +
  32 + self.api.post(apiRoute: .sendEvent, params: params, headers: [:]) { (logEventResponseModel: LogEventResponseModel) in
  33 + debugPrint("\(type(of: self)) - successfully sent \(eventType.rawValue) event")
  34 +
  35 + if logEventResponseModel.success {
  36 + success()
  37 + }
  38 + } failure: { error in
  39 + debugPrint("\(type(of: self)) - failed to log \(eventType.rawValue) event - \(error.localizedDescription)")
  40 + }
  41 + }
  42 +
  43 + private func getCurrentIPAddress(completion: @escaping (String) -> ()) {
  44 + api.get(apiRoute: .getMyIP, params: ["format":"json"]) { (ipResponseModel: IPResponseModel) in
  45 + completion(ipResponseModel.ip)
  46 + } failure: { error in
  47 + print(error.localizedDescription)
  48 + }
  49 + }
  50 +
  51 + private func preparePOSTParamsArray(eventType: VPNAnalyticsConstants.VPNAnalyticsEvent) -> [String:String] {
  52 + #if os(macOS)
  53 + guard let width = NSScreen.main?.frame,
  54 + let height = NSScreen.main?.frame.height else {
  55 + return [:]
  56 + }
  57 +
  58 + let screenWidth = String(describing: width)
  59 + let screenHeight = String(describing: height)
  60 + #else
  61 + let screenWidth = String(describing: Int(UIScreen.main.bounds.width))
  62 + let screenHeight = String(describing: Int(UIScreen.main.bounds.height))
  63 + #endif
  64 +
  65 +
  66 + let appVersionNumber = Bundle.main.infoDictionary?["CFBundleShortVersionString"] ?? "Unknown"
  67 + let appBuildVersionNumber = Bundle.main.infoDictionary?["CFBundleVersion"] ?? "Unknown"
  68 + let appVersion = "v\(appVersionNumber) b\(appBuildVersionNumber)"
  69 +
  70 + #if os(macOS)
  71 + let device = "MacOS v\(ProcessInfo.processInfo.operatingSystemVersion)"
  72 + #else
  73 + let device = "iOS v\(UIDevice.current.systemVersion)"
  74 + #endif
  75 +
  76 + return ["type": eventType.rawValue,
  77 + "app_token": applicationToken,
  78 + "screen_width": screenWidth,
  79 + "screen_height": screenHeight,
  80 + "device": device,
  81 + "app_version": appVersion]
  82 + }
  83 +}
  1 +//
  2 +// IPResponseModel.swift
  3 +//
  4 +//
  5 +// Created by Mihail Konoplitskyi on 25.11.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +
  10 +class IPResponseModel: Codable {
  11 + var ip: String
  12 +}
  1 +//
  2 +// LogEventResponseModel.swift
  3 +// VPNAnalytics
  4 +//
  5 +// Created by Mihail Konoplitskyi on 02.09.2022.
  6 +//
  7 +
  8 +import Foundation
  9 +
  10 +struct LogEventResponseModel: Codable {
  11 + var success: Bool
  12 + var message: String?
  13 +}
  1 +//
  2 +// FloatingPoint.swift
  3 +// Pro-Seecurity-VPN
  4 +//
  5 +// Created by user247686 on 12/11/23.
  6 +//
  7 +
  8 +import Foundation
  9 +import Foundation
  10 +
  11 +extension FloatingPoint {
  12 + var degreesToRadians: Self { return self * .pi / 180 }
  13 + var radiansToDegrees: Self { return self * 180 / .pi }
  14 +}
  1 +//
  2 +// ActivityIndicator.swift
  3 +// Pro-Seecurity-VPN
  4 +//
  5 +// Created by user247686 on 12/11/23.
  6 +//
  7 +
  8 +import Foundation
  9 +import Foundation
  10 +import UIKit
  11 +
  12 +class ActivityIndicator: UIView {
  13 +
  14 + //in px
  15 + var lineWidth: CGFloat = 3 {
  16 + didSet {
  17 + setNeedsDisplay()
  18 + }
  19 + }
  20 +
  21 + var rotationAngle: CGFloat = 0
  22 +
  23 + private var forceStopAnimation = false {
  24 + didSet {
  25 + isHidden = forceStopAnimation
  26 + }
  27 + }
  28 + private var isRotating = false
  29 +
  30 + required init?(coder aDecoder: NSCoder) {
  31 + super.init(coder: aDecoder)
  32 + setup()
  33 + }
  34 +
  35 + override init(frame: CGRect) {
  36 + super.init(frame: frame)
  37 + setup()
  38 + }
  39 +
  40 + private func setup() {
  41 + isHidden = true
  42 + backgroundColor = .clear
  43 + }
  44 +
  45 + func startAnimating() {
  46 + if !isRotating {
  47 + forceStopAnimation = false
  48 +
  49 + //возвращаем в исходную
  50 + rotationAngle = 0
  51 + self.transform = .identity
  52 +
  53 + rotate()
  54 + }
  55 + }
  56 +
  57 + func stopAnimating() {
  58 + forceStopAnimation = true
  59 + }
  60 +
  61 + private func rotate() {
  62 + isRotating = true
  63 + self.rotationAngle += 90
  64 + UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveLinear, animations: {
  65 + self.transform = CGAffineTransform(rotationAngle: self.rotationAngle.degreesToRadians)
  66 + }) { finished in
  67 + if !self.forceStopAnimation {
  68 + self.rotate()
  69 + } else {
  70 + self.isRotating = false
  71 + }
  72 + }
  73 + }
  74 +
  75 + override func draw(_ rect: CGRect) {
  76 + let center = CGPoint(x: bounds.width / 2, y: bounds.height / 2)
  77 + let radius: CGFloat = max(bounds.width, bounds.height)
  78 +
  79 + //bottom line
  80 + var startAngle: CGFloat = 0
  81 + var endAngle: CGFloat = 360
  82 +
  83 + var path = UIBezierPath(arcCenter: center,
  84 + radius: radius/2-lineWidth,
  85 + startAngle: startAngle.degreesToRadians,
  86 + endAngle: endAngle.degreesToRadians,
  87 + clockwise: true)
  88 +
  89 + path.lineWidth = lineWidth
  90 + UIColor.clear.setStroke()
  91 + path.stroke()
  92 +
  93 + startAngle = 270
  94 + endAngle = 540
  95 +
  96 + path = UIBezierPath(arcCenter: center,
  97 + radius: radius/2-lineWidth,
  98 + startAngle: startAngle.degreesToRadians,
  99 + endAngle: endAngle.degreesToRadians,
  100 + clockwise: true)
  101 +
  102 + path.lineWidth = lineWidth
  103 + UIColor.white.setStroke()
  104 + path.stroke()
  105 + }
  106 +}
  1 +//
  2 +// ProgressHelper.swift
  3 +// Pro-Seecurity-VPN
  4 +//
  5 +// Created by user247686 on 12/11/23.
  6 +//
  7 +
  8 +import Foundation
  9 +import UIKit
  10 +
  11 +class ProgressHelper: NSObject {
  12 +
  13 + static var progressView: ProgressHelperView?
  14 +
  15 + static func show(progressText: String? = nil) {
  16 + DispatchQueue.main.async {
  17 + if progressView?.superview == nil {
  18 + progressView = ProgressHelperView()
  19 +
  20 + if let keyWindow = UIApplication.shared.keyWindow,
  21 + let progressView = self.progressView {
  22 + keyWindow.addSubview(progressView)
  23 + progressView.activityIndicator.startAnimating()
  24 +
  25 + progressView.snp.makeConstraints { (make) in
  26 + make.edges.equalToSuperview()
  27 + }
  28 + }
  29 + }
  30 + }
  31 + }
  32 +
  33 + static func hide() {
  34 + DispatchQueue.main.async {
  35 + self.progressView?.activityIndicator.stopAnimating()
  36 + self.progressView?.removeFromSuperview()
  37 + }
  38 + }
  39 +}
  1 +//
  2 +// ProgressHelperView.swift
  3 +// Pro-Seecurity-VPN
  4 +//
  5 +// Created by user247686 on 12/11/23.
  6 +//
  7 +
  8 +import Foundation
  9 +import UIKit
  10 +
  11 +class ProgressHelperView: UIView {
  12 + var activityIndicator: ActivityIndicator = {
  13 + let obj = ActivityIndicator()
  14 + obj.tintColor = .white
  15 + obj.translatesAutoresizingMaskIntoConstraints = false
  16 + return obj
  17 + }()
  18 +
  19 + override init(frame: CGRect) {
  20 + super.init(frame: frame)
  21 + setup()
  22 + }
  23 +
  24 + required init?(coder aDecoder: NSCoder) {
  25 + super.init(coder: aDecoder)
  26 + setup()
  27 + }
  28 +
  29 + private func setup() {
  30 + backgroundColor = UIColor.black.withAlphaComponent(0.4)
  31 +
  32 +
  33 + addSubview(activityIndicator)
  34 +
  35 + activityIndicator.snp.makeConstraints { (make) in
  36 + make.size.equalTo(64.sizeW)
  37 + make.center.equalToSuperview()
  38 + }
  39 +
  40 + }
  41 +
  42 + override func didMoveToSuperview() {
  43 + super.didMoveToSuperview()
  44 + activityIndicator.startAnimating()
  45 + }
  46 +
  47 + override func removeFromSuperview() {
  48 + super.removeFromSuperview()
  49 + activityIndicator.stopAnimating()
  50 + }
  51 +}
@@ -12,29 +12,45 @@ final class CachingManager { @@ -12,29 +12,45 @@ final class CachingManager {
12 static let isFirstAppLoad = "IsFirstAppLoad" 12 static let isFirstAppLoad = "IsFirstAppLoad"
13 static let isAdBlocking = "IsAdBlocking" 13 static let isAdBlocking = "IsAdBlocking"
14 static let expirationDate = "ExpirationDate" 14 static let expirationDate = "ExpirationDate"
  15 + static let isActive = "isActive"
15 } 16 }
16 - 17 +
17 static let shared = CachingManager() 18 static let shared = CachingManager()
18 private let userDefaults = UserDefaults.standard 19 private let userDefaults = UserDefaults.standard
19 - 20 +
20 private init() {} 21 private init() {}
21 - 22 +
22 var isFirstAppLoad: Bool { 23 var isFirstAppLoad: Bool {
23 get { return userDefaults.bool(forKey: Keys.isFirstAppLoad) } 24 get { return userDefaults.bool(forKey: Keys.isFirstAppLoad) }
24 set { userDefaults.set(newValue, forKey: Keys.isFirstAppLoad) } 25 set { userDefaults.set(newValue, forKey: Keys.isFirstAppLoad) }
25 } 26 }
  27 +
26 var adBlockerState: Bool { 28 var adBlockerState: Bool {
27 get { return userDefaults.bool(forKey: Keys.isAdBlocking) } 29 get { return userDefaults.bool(forKey: Keys.isAdBlocking) }
28 set { userDefaults.set(newValue, forKey: Keys.isAdBlocking) } 30 set { userDefaults.set(newValue, forKey: Keys.isAdBlocking) }
29 } 31 }
  32 +
30 var expirationDate: Double? { 33 var expirationDate: Double? {
31 get { 34 get {
32 if userDefaults.object(forKey: Keys.expirationDate) == nil { 35 if userDefaults.object(forKey: Keys.expirationDate) == nil {
33 return nil 36 return nil
34 } 37 }
35 -  
36 return userDefaults.double(forKey: Keys.expirationDate) 38 return userDefaults.double(forKey: Keys.expirationDate)
37 } 39 }
38 set { userDefaults.set(newValue, forKey: Keys.expirationDate) } 40 set { userDefaults.set(newValue, forKey: Keys.expirationDate) }
39 } 41 }
  42 +
  43 + var isSubscriptionActive: Bool {
  44 + get {
  45 + // Check if expiration date is present and greater than the current date
  46 + if let expirationDate = expirationDate, expirationDate > Date().timeIntervalSince1970 {
  47 + return true
  48 + } else {
  49 + // If expiration date is not present or has passed, set subscription to false
  50 + isSubscriptionActive = false
  51 + return false
  52 + }
  53 + }
  54 + set { userDefaults.set(newValue, forKey: Keys.isActive) }
  55 + }
40 } 56 }
@@ -43,6 +43,10 @@ final class NotificationManager { @@ -43,6 +43,10 @@ final class NotificationManager {
43 } 43 }
44 44
45 private func dispatchNotification() { 45 private func dispatchNotification() {
  46 + guard !CachingManager.shared.isSubscriptionActive else {
  47 + return
  48 + }
  49 +
46 let identifier = StringConstants.notificationIdentifier 50 let identifier = StringConstants.notificationIdentifier
47 let notificationCenter = UNUserNotificationCenter.current() 51 let notificationCenter = UNUserNotificationCenter.current()
48 52
@@ -9,6 +9,6 @@ import Foundation @@ -9,6 +9,6 @@ import Foundation
9 9
10 struct SubscriptionsModel { 10 struct SubscriptionsModel {
11 static var subscriptionInfo: [String: String] { 11 static var subscriptionInfo: [String: String] {
12 - return ["adBlocker": "com.browser.adblocker"] 12 + return ["adBlocker": "1111"]
13 } 13 }
14 } 14 }
@@ -26,6 +26,10 @@ struct StringConstants { @@ -26,6 +26,10 @@ struct StringConstants {
26 "https://mail.google.com/", 26 "https://mail.google.com/",
27 "https://github.com/" ] 27 "https://github.com/" ]
28 28
  29 + static let appId = 6473180587
  30 + static let appStoreUrl = "itms-apps://itunes.apple.com/app/id\(appId)?action=write-review"
  31 + static let appURL = "https://apps.apple.com/us/app/gotoweb/id6473180587"
  32 +
29 ///SettingView 33 ///SettingView
30 static let settingViewControllerTableViewData = ["Privacy policy", "Terms and condition", "Share app", "Rate app", "Support", "Restore"] 34 static let settingViewControllerTableViewData = ["Privacy policy", "Terms and condition", "Share app", "Rate app", "Support", "Restore"]
31 static let removeAdvertTableViewData = ["Unlimited blocks & uploads", "Enhanced User Experience", "Faster Page Load Times", "Privacy and Security"] 35 static let removeAdvertTableViewData = ["Unlimited blocks & uploads", "Enhanced User Experience", "Faster Page Load Times", "Privacy and Security"]
  1 +{
  2 + "info" : {
  3 + "author" : "xcode",
  4 + "version" : 1
  5 + }
  6 +}
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Group 14@3x 1.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Group 14@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Group 14@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Group 14.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Group 14@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Group 14@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Frame 645-1.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Frame 645@2x-1.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Frame 645@3x-1.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
  1 +{
  2 + "images" : [
  3 + {
  4 + "filename" : "Group 14.png",
  5 + "idiom" : "universal",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "filename" : "Group 14@2x.png",
  10 + "idiom" : "universal",
  11 + "scale" : "2x"
  12 + },
  13 + {
  14 + "filename" : "Group 14@3x.png",
  15 + "idiom" : "universal",
  16 + "scale" : "3x"
  17 + }
  18 + ],
  19 + "info" : {
  20 + "author" : "xcode",
  21 + "version" : 1
  22 + }
  23 +}
@@ -14,6 +14,8 @@ import Realm @@ -14,6 +14,8 @@ import Realm
14 final class BrowserHomeViewController: UIViewController { 14 final class BrowserHomeViewController: UIViewController {
15 let mainView = BrowserHomeView() 15 let mainView = BrowserHomeView()
16 16
  17 + private var storeKit = SubscriptionManager()
  18 +
17 private let searchingViewController: SearchingViewController 19 private let searchingViewController: SearchingViewController
18 private let searchResultViewController: SearchResultViewController 20 private let searchResultViewController: SearchResultViewController
19 private var tabsViewController: TabsViewController? 21 private var tabsViewController: TabsViewController?
@@ -55,6 +57,12 @@ final class BrowserHomeViewController: UIViewController { @@ -55,6 +57,12 @@ final class BrowserHomeViewController: UIViewController {
55 super.viewDidLoad() 57 super.viewDidLoad()
56 58
57 initViewController() 59 initViewController()
  60 +
  61 + if CachingManager.shared.isSubscriptionActive {
  62 +
  63 + } else {
  64 + subscriptionHandler()
  65 + }
58 } 66 }
59 67
60 override func viewWillAppear(_ animated: Bool) { 68 override func viewWillAppear(_ animated: Bool) {
@@ -70,6 +78,8 @@ final class BrowserHomeViewController: UIViewController { @@ -70,6 +78,8 @@ final class BrowserHomeViewController: UIViewController {
70 NotificationCenter.default.removeObserver(self) 78 NotificationCenter.default.removeObserver(self)
71 } 79 }
72 80
  81 +
  82 +
73 private func initViewController() { 83 private func initViewController() {
74 setupSearchBarComponentsAction() 84 setupSearchBarComponentsAction()
75 setupSearchingViewController() 85 setupSearchingViewController()
@@ -367,12 +377,17 @@ extension BrowserHomeViewController: UITextFieldDelegate { @@ -367,12 +377,17 @@ extension BrowserHomeViewController: UITextFieldDelegate {
367 377
368 func textFieldShouldReturn(_ textField: UITextField) -> Bool { 378 func textFieldShouldReturn(_ textField: UITextField) -> Bool {
369 textField.resignFirstResponder() 379 textField.resignFirstResponder()
370 - searchRequestURL = "https://www.google.com/search?q=" + (textField.text ?? "") 380 +
  381 + if let text = textField.text, let url = URL(string: text), url.scheme != nil {
  382 + searchRequestURL = text
  383 + } else {
  384 + searchRequestURL = "https://www.google.com/search?q=" + (textField.text ?? "")
  385 + }
371 openSearchResult() 386 openSearchResult()
372 387
373 return true 388 return true
374 } 389 }
375 - 390 +
376 func setupSearchBarComponentsAction() { 391 func setupSearchBarComponentsAction() {
377 mainView.searchBarContainer.searchBarView.searchTextFieldView.autocorrectionType = .no 392 mainView.searchBarContainer.searchBarView.searchTextFieldView.autocorrectionType = .no
378 mainView.searchBarContainer.searchBarView.searchTextFieldView.delegate = self 393 mainView.searchBarContainer.searchBarView.searchTextFieldView.delegate = self
@@ -437,3 +452,67 @@ extension BrowserHomeViewController { @@ -437,3 +452,67 @@ extension BrowserHomeViewController {
437 openSearchResult() 452 openSearchResult()
438 } 453 }
439 } 454 }
  455 +
  456 +//MARK: Logic for subscriptions
  457 +extension BrowserHomeViewController {
  458 +
  459 + func subscriptionHandler() {
  460 + if CachingManager.shared.isSubscriptionActive {
  461 +
  462 + } else {
  463 + if storeKit.purchasedSubscriptions.isEmpty {
  464 + Task {
  465 +// try? await storeKit.restorePurchase()
  466 +
  467 + if storeKit.purchasedSubscriptions.isEmpty {
  468 + presentSubscriptionHandler()
  469 + } else {
  470 + if let restoreDate = CachingManager.shared.expirationDate {
  471 + if Date().timeIntervalSince1970 < restoreDate {
  472 + } else {
  473 + presentSubscriptionHandler()
  474 + }
  475 + } else {
  476 + DateManager.shared.getSubscriptionExpirationDate()
  477 + let restoreDate = CachingManager.shared.expirationDate
  478 + if Date().timeIntervalSince1970 < restoreDate ?? 0 {
  479 + } else {
  480 + presentSubscriptionHandler()
  481 + }
  482 + }
  483 + }
  484 + }
  485 + } else {
  486 + if let restoreDate = CachingManager.shared.expirationDate {
  487 + if Date().timeIntervalSince1970 < restoreDate {
  488 + } else {
  489 + presentSubscriptionHandler()
  490 + }
  491 + } else {
  492 + DateManager.shared.getSubscriptionExpirationDate()
  493 + let restoreDate = CachingManager.shared.expirationDate
  494 + if Date().timeIntervalSince1970 < restoreDate ?? 0 {
  495 + } else {
  496 + presentSubscriptionHandler()
  497 + }
  498 + }
  499 + }
  500 + }
  501 + }
  502 +
  503 + private func presentSubscriptionHandler() {
  504 + let subcriptionViewController = NewPaywallViewController(storeKit: storeKit, completion: testHandler)
  505 + subcriptionViewController.modalPresentationStyle = .fullScreen
  506 + subcriptionViewController.modalTransitionStyle = .crossDissolve
  507 + subcriptionViewController.mainView.infoLabel.text = "\(storeKit.storeProducts.first?.price ?? 0)$"
  508 + present(subcriptionViewController, animated: true)
  509 + }
  510 +
  511 + private func testHandler() {
  512 + let alert = UIAlertController(title: "Congradulations!", message: "Success by subscription", preferredStyle: .alert)
  513 + let okAction = UIAlertAction(title: "OK", style: .default)
  514 + alert.addAction(okAction)
  515 + present(alert, animated: true)
  516 +
  517 + }
  518 +}
@@ -20,6 +20,7 @@ final class SearchBarView: UIView { @@ -20,6 +20,7 @@ final class SearchBarView: UIView {
20 let obj = UITextField() 20 let obj = UITextField()
21 obj.text = "Search" 21 obj.text = "Search"
22 obj.textColor = ColorConstants.SearchbarTintBlue 22 obj.textColor = ColorConstants.SearchbarTintBlue
  23 + obj.autocapitalizationType = .none
23 24
24 return obj 25 return obj
25 }() 26 }()
@@ -34,6 +34,10 @@ final class RemoveAdvertViewController: UIViewController { @@ -34,6 +34,10 @@ final class RemoveAdvertViewController: UIViewController {
34 super.viewDidLoad() 34 super.viewDidLoad()
35 35
36 initViewController() 36 initViewController()
  37 +
  38 + if !CachingManager.shared.isSubscriptionActive {
  39 + subscriptionHandler()
  40 + }
37 } 41 }
38 42
39 private func initViewController() { 43 private func initViewController() {
@@ -46,6 +50,8 @@ final class RemoveAdvertViewController: UIViewController { @@ -46,6 +50,8 @@ final class RemoveAdvertViewController: UIViewController {
46 extension RemoveAdvertViewController { 50 extension RemoveAdvertViewController {
47 @objc 51 @objc
48 private func adBlockerButtonPressed(_ sender: UIButton) { 52 private func adBlockerButtonPressed(_ sender: UIButton) {
  53 + ProgressHelper.show()
  54 + mainView.adBlockButton.isEnabled = false
49 if CachingManager.shared.adBlockerState { 55 if CachingManager.shared.adBlockerState {
50 turnOffAdBlocker() 56 turnOffAdBlocker()
51 } else { 57 } else {
@@ -67,7 +73,7 @@ extension RemoveAdvertViewController { @@ -67,7 +73,7 @@ extension RemoveAdvertViewController {
67 private func subscriptionHandler() { 73 private func subscriptionHandler() {
68 if storeKit.purchasedSubscriptions.isEmpty { 74 if storeKit.purchasedSubscriptions.isEmpty {
69 Task { 75 Task {
70 - try? await storeKit.restorePurchase() 76 + // try? await storeKit.restorePurchase()
71 77
72 if storeKit.purchasedSubscriptions.isEmpty { 78 if storeKit.purchasedSubscriptions.isEmpty {
73 presentSubscriptionHandler() 79 presentSubscriptionHandler()
@@ -115,7 +121,9 @@ extension RemoveAdvertViewController { @@ -115,7 +121,9 @@ extension RemoveAdvertViewController {
115 } 121 }
116 122
117 private func presentSubscriptionHandler() { 123 private func presentSubscriptionHandler() {
118 - let subcriptionViewController = SubscriptionViewController(storeKit: storeKit, complition: testHandler) 124 + ProgressHelper.hide()
  125 + mainView.adBlockButton.isEnabled = true
  126 + let subcriptionViewController = NewPaywallViewController(storeKit: storeKit, completion: testHandler)
119 subcriptionViewController.modalPresentationStyle = .fullScreen 127 subcriptionViewController.modalPresentationStyle = .fullScreen
120 subcriptionViewController.modalTransitionStyle = .crossDissolve 128 subcriptionViewController.modalTransitionStyle = .crossDissolve
121 129
@@ -138,19 +146,23 @@ extension RemoveAdvertViewController { @@ -138,19 +146,23 @@ extension RemoveAdvertViewController {
138 } 146 }
139 147
140 private func turnOnAdBlocker() { 148 private func turnOnAdBlocker() {
  149 + ProgressHelper.hide()
141 mainView.adBlockButton.setImage(.adBlockOnState, for: .normal) 150 mainView.adBlockButton.setImage(.adBlockOnState, for: .normal)
142 mainView.tapActionLabel.textColor = ColorConstants.SearchbarTintBlue 151 mainView.tapActionLabel.textColor = ColorConstants.SearchbarTintBlue
143 mainView.tapActionLabel.text = StringConstants.turnOff 152 mainView.tapActionLabel.text = StringConstants.turnOff
144 153
145 CachingManager.shared.adBlockerState = true 154 CachingManager.shared.adBlockerState = true
  155 + mainView.adBlockButton.isEnabled = true
146 } 156 }
147 157
148 private func turnOffAdBlocker() { 158 private func turnOffAdBlocker() {
  159 + ProgressHelper.hide()
149 mainView.adBlockButton.setImage(.adBlockOffState, for: .normal) 160 mainView.adBlockButton.setImage(.adBlockOffState, for: .normal)
150 mainView.tapActionLabel.textColor = ColorConstants.customPink 161 mainView.tapActionLabel.textColor = ColorConstants.customPink
151 mainView.tapActionLabel.text = StringConstants.turnOn 162 mainView.tapActionLabel.text = StringConstants.turnOn
152 163
153 CachingManager.shared.adBlockerState = false 164 CachingManager.shared.adBlockerState = false
  165 + mainView.adBlockButton.isEnabled = true
154 } 166 }
155 } 167 }
156 168
@@ -25,7 +25,7 @@ final class SettingViewController: UIViewController { @@ -25,7 +25,7 @@ final class SettingViewController: UIViewController {
25 override func loadView() { 25 override func loadView() {
26 view = mainView 26 view = mainView
27 } 27 }
28 - 28 +
29 override func viewDidLoad() { 29 override func viewDidLoad() {
30 super.viewDidLoad() 30 super.viewDidLoad()
31 31
@@ -63,7 +63,7 @@ extension SettingViewController: UITableViewDelegate, UITableViewDataSource { @@ -63,7 +63,7 @@ extension SettingViewController: UITableViewDelegate, UITableViewDataSource {
63 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 63 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
64 return 60.0 64 return 60.0
65 } 65 }
66 - 66 +
67 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 67 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
68 let index = indexPath.row 68 let index = indexPath.row
69 cellPresshandler(index) 69 cellPresshandler(index)
@@ -101,7 +101,11 @@ extension SettingViewController { @@ -101,7 +101,11 @@ extension SettingViewController {
101 case 2: 101 case 2:
102 shareButtonPressed() 102 shareButtonPressed()
103 case 3: 103 case 3:
104 - break 104 + if let appStoreURL = URL(string: StringConstants.appStoreUrl) {
  105 + if UIApplication.shared.canOpenURL(appStoreURL) {
  106 + UIApplication.shared.open(appStoreURL, options: [:], completionHandler: nil)
  107 + }
  108 + }
105 case 4: 109 case 4:
106 setupMessage() 110 setupMessage()
107 case 5: 111 case 5:
@@ -118,7 +122,7 @@ extension SettingViewController { @@ -118,7 +122,7 @@ extension SettingViewController {
118 } 122 }
119 123
120 private func shareButtonPressed() { 124 private func shareButtonPressed() {
121 - let items = [URL(string: URLConstants.shareAppLink)] 125 + let items = [URL(string: StringConstants.appURL)]
122 let shareView = UIActivityViewController(activityItems: items as [Any], applicationActivities: nil) 126 let shareView = UIActivityViewController(activityItems: items as [Any], applicationActivities: nil)
123 127
124 present(shareView, animated: true) 128 present(shareView, animated: true)
@@ -8,19 +8,24 @@ @@ -8,19 +8,24 @@
8 import UIKit 8 import UIKit
9 import StoreKit 9 import StoreKit
10 10
11 -  
12 final class SubscriptionViewController: UIViewController { 11 final class SubscriptionViewController: UIViewController {
13 12
14 - private let mainView = SubscriptionView() 13 + let mainView = SubscriptionView()
15 14
16 private let tableViewData: [String] 15 private let tableViewData: [String]
17 private let storeKitManager: SubscriptionManager 16 private let storeKitManager: SubscriptionManager
18 private let successCompletion: () -> Void 17 private let successCompletion: () -> Void
19 18
20 - init(storeKit: SubscriptionManager, complition: @escaping() -> Void) { 19 + private var subscriptionInfo: SKProduct? {
  20 + didSet {
  21 + updateSubscriptionLabels()
  22 + }
  23 + }
  24 +
  25 + init(storeKit: SubscriptionManager, completion: @escaping() -> Void) {
21 tableViewData = StringConstants.removeAdvertTableViewData 26 tableViewData = StringConstants.removeAdvertTableViewData
22 storeKitManager = storeKit 27 storeKitManager = storeKit
23 - successCompletion = complition 28 + successCompletion = completion
24 29
25 super.init(nibName: nil, bundle: nil) 30 super.init(nibName: nil, bundle: nil)
26 } 31 }
@@ -33,6 +38,7 @@ final class SubscriptionViewController: UIViewController { @@ -33,6 +38,7 @@ final class SubscriptionViewController: UIViewController {
33 super.viewDidLoad() 38 super.viewDidLoad()
34 39
35 initViewController() 40 initViewController()
  41 + updateSubscriptionLabels()
36 } 42 }
37 43
38 override func loadView() { 44 override func loadView() {
@@ -42,6 +48,20 @@ final class SubscriptionViewController: UIViewController { @@ -42,6 +48,20 @@ final class SubscriptionViewController: UIViewController {
42 private func initViewController() { 48 private func initViewController() {
43 addTargets() 49 addTargets()
44 setupTableView() 50 setupTableView()
  51 +
  52 + mainView.privacyButton.addTarget(self, action: #selector(policyTapped), for: .touchUpInside)
  53 + mainView.termsButton.addTarget(self, action: #selector(termsTapped), for: .touchUpInside)
  54 + mainView.restoreButton.addTarget(self, action: #selector(restoreTapped), for: .touchUpInside)
  55 + }
  56 +
  57 + private func updateSubscriptionLabels() {
  58 + mainView.priceLabel.text = storeKitManager.storeProducts.first?.displayPrice
  59 + }
  60 +
  61 + private func presentViewController(_ viewController: UIViewController) {
  62 + viewController.modalPresentationStyle = .fullScreen
  63 +
  64 + present(viewController, animated: true)
45 } 65 }
46 } 66 }
47 67
@@ -75,15 +95,37 @@ extension SubscriptionViewController { @@ -75,15 +95,37 @@ extension SubscriptionViewController {
75 mainView.advantagesTableView.register(SubscriptionTableViewCell.self, forCellReuseIdentifier: SubscriptionTableViewCell.cellID) 95 mainView.advantagesTableView.register(SubscriptionTableViewCell.self, forCellReuseIdentifier: SubscriptionTableViewCell.cellID)
76 } 96 }
77 97
  98 + private func isSubscriptionValid() -> Bool {
  99 + guard let expirationDate = CachingManager.shared.expirationDate else {
  100 + return false
  101 + }
  102 +
  103 + let currentDate = Date().timeIntervalSince1970
  104 + return expirationDate > currentDate
  105 + }
  106 +
78 @MainActor 107 @MainActor
79 private func buySubscription() async throws { 108 private func buySubscription() async throws {
  109 + if CachingManager.shared.isSubscriptionActive {
  110 + dismiss(animated: true)
  111 + successCompletion()
  112 + return
  113 + }
  114 +
80 if let adblockerProduct = storeKitManager.storeProducts.first(where: { $0.id == SubscriptionsModel.subscriptionInfo["adBlocker"]}) { 115 if let adblockerProduct = storeKitManager.storeProducts.first(where: { $0.id == SubscriptionsModel.subscriptionInfo["adBlocker"]}) {
81 - if let transaction = try await storeKitManager.purchase(adblockerProduct) {  
82 - CachingManager.shared.expirationDate = transaction.expirationDate?.timeIntervalSince1970 ?? 0  
83 - dismiss(animated: true)  
84 - successCompletion() 116 + do {
  117 + if let transaction = try await storeKitManager.purchase(adblockerProduct) {
  118 + CachingManager.shared.expirationDate = transaction.expirationDate?.timeIntervalSince1970 ?? 0
  119 + dismiss(animated: true)
  120 + successCompletion()
  121 +
  122 + VPNAnalytics.logEvent(eventType: .startTrial, params: ["subscription_id": "\(transaction.originalID)"])
  123 + }
  124 + } catch {
  125 + print("Error purchasing product: \(error)")
85 } 126 }
86 } 127 }
  128 +
87 } 129 }
88 } 130 }
89 131
@@ -97,9 +139,18 @@ extension SubscriptionViewController { @@ -97,9 +139,18 @@ extension SubscriptionViewController {
97 139
98 @objc 140 @objc
99 private func buyAdblocker(_ sender: UIButton) { 141 private func buyAdblocker(_ sender: UIButton) {
  142 + ProgressHelper.show()
  143 + sender.isEnabled = false
  144 +
100 Task { 145 Task {
  146 + defer {
  147 + ProgressHelper.hide()
  148 +
  149 + sender.isEnabled = true
  150 + }
  151 +
101 do { 152 do {
102 - try await buySubscription() 153 + try await buySubscription()
103 } catch { 154 } catch {
104 let alert = UIAlertController(title: "Fail!", message: "Error with subscription", preferredStyle: .alert) 155 let alert = UIAlertController(title: "Fail!", message: "Error with subscription", preferredStyle: .alert)
105 let okAction = UIAlertAction(title: "OK", style: .default) 156 let okAction = UIAlertAction(title: "OK", style: .default)
@@ -108,4 +159,25 @@ extension SubscriptionViewController { @@ -108,4 +159,25 @@ extension SubscriptionViewController {
108 } 159 }
109 } 160 }
110 } 161 }
  162 +
  163 +
  164 +
  165 + @objc
  166 + private func termsTapped() {
  167 + let termsViewController = TermsViewController()
  168 + presentViewController(termsViewController)
  169 + }
  170 +
  171 + @objc
  172 + private func policyTapped() {
  173 + let privacyViewController = PrivacyViewController()
  174 + presentViewController(privacyViewController)
  175 + }
  176 +
  177 + @objc
  178 + private func restoreTapped() {
  179 + Task {
  180 + try? await SubscriptionManager.shared.restorePurchase()
  181 + }
  182 + }
111 } 183 }
@@ -52,7 +52,7 @@ final class SubscriptionView: GradientView { @@ -52,7 +52,7 @@ final class SubscriptionView: GradientView {
52 return obj 52 return obj
53 }() 53 }()
54 54
55 - private let priceLabel: UILabel = { 55 + let priceLabel: UILabel = {
56 let obj = UILabel() 56 let obj = UILabel()
57 obj.text = StringConstants.price 57 obj.text = StringConstants.price
58 obj.font = FontConstants.regularFont_18 58 obj.font = FontConstants.regularFont_18
@@ -72,7 +72,7 @@ final class SubscriptionView: GradientView { @@ -72,7 +72,7 @@ final class SubscriptionView: GradientView {
72 return obj 72 return obj
73 }() 73 }()
74 74
75 - private let freeTrialLabel: UILabel = { 75 + let freeTrialLabel: UILabel = {
76 let obj = UILabel() 76 let obj = UILabel()
77 obj.textAlignment = .center 77 obj.textAlignment = .center
78 obj.font = FontConstants.semiboldFont_12 78 obj.font = FontConstants.semiboldFont_12
@@ -81,15 +81,47 @@ final class SubscriptionView: GradientView { @@ -81,15 +81,47 @@ final class SubscriptionView: GradientView {
81 return obj 81 return obj
82 }() 82 }()
83 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 - 84 + private let buttonsStackView: UIStackView = {
  85 + let obj = UIStackView()
  86 + obj.axis = .horizontal
  87 + obj.alignment = .center
  88 + obj.distribution = .fillEqually
  89 + obj.spacing = 6.sizeW
  90 + return obj
  91 + }()
  92 +
  93 + let restoreButton: UIButton = {
  94 + let obj = UIButton()
  95 + obj.setTitle("Restore", for: .normal)
  96 + obj.setTitleColor(.white, for: .normal)
  97 + obj.setTitleColor(.white, for: .highlighted)
  98 + obj.titleLabel?.font = UIFont.systemFont(ofSize: 12.sizeW, weight: .regular)
  99 + obj.titleLabel?.lineBreakMode = .byWordWrapping
  100 + return obj
  101 + }()
  102 +
  103 + let privacyButton: UIButton = {
  104 + let obj = UIButton()
  105 + obj.setTitle("Privacy", for: .normal)
  106 + obj.setTitleColor(.white, for: .normal)
  107 + obj.setTitleColor(.white, for: .highlighted)
  108 + obj.titleLabel?.font = UIFont.systemFont(ofSize: 12.sizeW, weight: .regular)
  109 + obj.titleLabel?.lineBreakMode = .byWordWrapping
  110 + return obj
  111 + }()
  112 +
  113 +
  114 + let termsButton: UIButton = {
  115 + let obj = UIButton()
  116 + obj.setTitle("Terms", for: .normal)
  117 + obj.setTitleColor(.white, for: .normal)
  118 + obj.setTitleColor(.white, for: .highlighted)
  119 + obj.titleLabel?.font = UIFont.systemFont(ofSize: 12.sizeW, weight: .regular)
  120 + obj.titleLabel?.lineBreakMode = .byWordWrapping
90 return obj 121 return obj
91 }() 122 }()
92 123
  124 +
93 override init (frame: CGRect) { 125 override init (frame: CGRect) {
94 super.init(frame: frame) 126 super.init(frame: frame)
95 127
@@ -105,7 +137,7 @@ final class SubscriptionView: GradientView { @@ -105,7 +137,7 @@ final class SubscriptionView: GradientView {
105 137
106 gradientLayer.frame = subscribeButton.bounds 138 gradientLayer.frame = subscribeButton.bounds
107 } 139 }
108 - 140 +
109 141
110 private func setup() { 142 private func setup() {
111 addSubview(closeButton) 143 addSubview(closeButton)
@@ -116,7 +148,11 @@ final class SubscriptionView: GradientView { @@ -116,7 +148,11 @@ final class SubscriptionView: GradientView {
116 addSubview(priceLabel) 148 addSubview(priceLabel)
117 addSubview(subscribeButton) 149 addSubview(subscribeButton)
118 addSubview(freeTrialLabel) 150 addSubview(freeTrialLabel)
119 - addSubview(discountLabel) 151 + addSubview(buttonsStackView)
  152 +
  153 + buttonsStackView.addArrangedSubview(restoreButton)
  154 + buttonsStackView.addArrangedSubview(termsButton)
  155 + buttonsStackView.addArrangedSubview(privacyButton)
120 156
121 setupConstraints() 157 setupConstraints()
122 gradientSetup() 158 gradientSetup()
@@ -164,11 +200,11 @@ final class SubscriptionView: GradientView { @@ -164,11 +200,11 @@ final class SubscriptionView: GradientView {
164 } 200 }
165 201
166 freeTrialLabel.snp.makeConstraints { make in 202 freeTrialLabel.snp.makeConstraints { make in
167 - make.bottom.equalTo(discountLabel.snp.top).offset(-8.sizeH) 203 + make.bottom.equalTo(termsButton.snp.top).offset(-8.sizeH)
168 make.centerX.equalToSuperview() 204 make.centerX.equalToSuperview()
169 } 205 }
170 -  
171 - discountLabel.snp.makeConstraints { make in 206 +
  207 + buttonsStackView.snp.makeConstraints { make in
172 make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom).offset(-24.sizeH) 208 make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom).offset(-24.sizeH)
173 make.centerX.equalToSuperview() 209 make.centerX.equalToSuperview()
174 } 210 }
  1 +//
  2 +// NewPaywallViewController.swift
  3 +// Pro-Seecurity-VPN
  4 +//
  5 +// Created by Volodymyr Kolomyltsev on 12/22/23.
  6 +//
  7 +
  8 +import UIKit
  9 +import StoreKit
  10 +
  11 +class NewPaywallViewController: UIViewController {
  12 +
  13 + var mainView: OnboardingView
  14 + private var currentSelectedIndex: Int = 0
  15 +
  16 + private let storeKitManager: SubscriptionManager
  17 + private let successCompletion: () -> Void
  18 +
  19 + var subscriptionInfo: SKProduct? {
  20 + didSet {
  21 + updateSubscriptionLabels()
  22 + }
  23 + }
  24 +
  25 + init(storeKit: SubscriptionManager, completion: @escaping () -> Void) {
  26 + self.storeKitManager = storeKit
  27 + self.successCompletion = completion
  28 + self.mainView = OnboardingView()
  29 + super.init(nibName: nil, bundle: nil)
  30 + }
  31 +
  32 + required init?(coder: NSCoder) {
  33 + fatalError("init(coder:) has not been implemented")
  34 + }
  35 +
  36 + override func loadView() {
  37 + view = mainView
  38 + }
  39 +
  40 + override func viewDidLoad() {
  41 + super.viewDidLoad()
  42 + setupUI()
  43 +
  44 + updateSubscriptionLabels()
  45 + }
  46 +
  47 + private func setupUI() {
  48 + mainView.scrollView.delegate = self
  49 +
  50 + mainView.privacyButton.addTarget(self, action: #selector(termsTapped), for: .touchUpInside)
  51 + mainView.termsButton.addTarget(self, action: #selector(policyTapped), for: .touchUpInside)
  52 + mainView.restoreButton.addTarget(self, action: #selector(restoreTapped), for: .touchUpInside)
  53 +
  54 + mainView.closeButton.addTarget(self, action: #selector(closeViewController(_:)), for: .touchUpInside)
  55 + mainView.activateButton.addTarget(self, action: #selector(buyAdblocker), for: .touchUpInside)
  56 + }
  57 +
  58 + private func updateSubscriptionLabels() {
  59 + if let price = storeKitManager.storeProducts.first?.displayPrice {
  60 + mainView.infoLabel
  61 + .text = "3-day free trial, then \(price) per week."
  62 + }
  63 +
  64 + }
  65 +
  66 + private func presentViewController(_ viewController: UIViewController) {
  67 + viewController.modalPresentationStyle = .fullScreen
  68 + present(viewController, animated: true)
  69 + }
  70 +}
  71 +
  72 +// MARK: - UIScrollViewDelegate
  73 +extension NewPaywallViewController: UIScrollViewDelegate {
  74 + func scrollViewDidScroll(_ scrollView: UIScrollView) {
  75 + let pageIndex = round(scrollView.contentOffset.x / view.frame.width)
  76 + mainView.pageControl.currentPage = Int(pageIndex)
  77 + currentSelectedIndex = Int(pageIndex)
  78 + }
  79 +}
  80 +
  81 +// MARK: - Targets
  82 +extension NewPaywallViewController {
  83 + @objc private func termsTapped() {
  84 + let termsViewController = TermsViewController()
  85 + presentViewController(termsViewController)
  86 + }
  87 +
  88 + @objc private func policyTapped() {
  89 + let privacyViewController = PrivacyViewController()
  90 + presentViewController(privacyViewController)
  91 + }
  92 +
  93 + @objc private func restoreTapped() {
  94 + Task {
  95 + try? await SubscriptionManager.shared.restorePurchase()
  96 + }
  97 + }
  98 +
  99 + @objc private func closeViewController(_ sender: UIButton) {
  100 + dismiss(animated: true, completion: nil)
  101 + }
  102 +
  103 + private func isSubscriptionValid() -> Bool {
  104 + guard let expirationDate = CachingManager.shared.expirationDate else {
  105 + return false
  106 + }
  107 +
  108 + let currentDate = Date().timeIntervalSince1970
  109 + return expirationDate > currentDate
  110 + }
  111 +
  112 + @objc
  113 + private func buyAdblocker(_ sender: UIButton) {
  114 + ProgressHelper.show()
  115 + sender.isEnabled = false
  116 +
  117 + Task {
  118 + defer {
  119 + ProgressHelper.hide()
  120 +
  121 + sender.isEnabled = true
  122 + }
  123 +
  124 + do {
  125 + try await buySubscription()
  126 + } catch {
  127 + let alert = UIAlertController(title: "Fail!", message: "Error with subscription", preferredStyle: .alert)
  128 + let okAction = UIAlertAction(title: "OK", style: .default)
  129 + alert.addAction(okAction)
  130 + present(alert, animated: true)
  131 + }
  132 + }
  133 + }
  134 +
  135 + @MainActor
  136 + private func buySubscription() async throws {
  137 + if CachingManager.shared.isSubscriptionActive {
  138 + dismiss(animated: true)
  139 + successCompletion()
  140 + return
  141 + }
  142 +
  143 + if let adblockerProduct = storeKitManager.storeProducts.first(where: { $0.id == SubscriptionsModel.subscriptionInfo["adBlocker"]}) {
  144 + do {
  145 + if let transaction = try await storeKitManager.purchase(adblockerProduct) {
  146 + CachingManager.shared.expirationDate = transaction.expirationDate?.timeIntervalSince1970 ?? 0
  147 + dismiss(animated: true)
  148 + successCompletion()
  149 +
  150 + VPNAnalytics.logEvent(eventType: .startTrial, params: ["subscription_id": "\(transaction.originalID)"])
  151 + }
  152 + } catch {
  153 + print("Error purchasing product: \(error)")
  154 + }
  155 + }
  156 + }
  157 +
  158 +}
  159 +
  160 +// MARK: - Helpers
  161 +extension NewPaywallViewController {
  162 + private func moveScrollViewTo(page: Int) {
  163 + var currentContentOffset = mainView.scrollView.contentOffset
  164 + let width = mainView.scrollView.frame.width
  165 + currentContentOffset.x = width * CGFloat(page)
  166 + currentSelectedIndex = page
  167 + mainView.scrollView.setContentOffset(currentContentOffset, animated: true)
  168 + }
  169 +
  170 + private func showErrorAlert(message: String) {
  171 + let alert = UIAlertController(title: "Fail!", message: message, preferredStyle: .alert)
  172 + let okAction = UIAlertAction(title: "OK", style: .default)
  173 + alert.addAction(okAction)
  174 + present(alert, animated: true)
  175 + }
  176 +}
  1 +//
  2 +// PaywallType.swift
  3 +// Pro-Seecurity-VPN
  4 +//
  5 +// Created by Volodymyr Kolomyltsev on 12/22/23.
  6 +//
  7 +
  8 +import Foundation
  9 +import UIKit
  10 +
  11 +enum OnboardingType: CaseIterable {
  12 + case snapPhotoSlide
  13 + case submitPhotoSlide
  14 + case getRewardsSlide
  15 +
  16 + var imgString: String {
  17 + switch self {
  18 + case .snapPhotoSlide:
  19 + return "tv_paywall_image"
  20 + case .submitPhotoSlide:
  21 + return "scan_paywall_image"
  22 + case .getRewardsSlide:
  23 + return "card_paywall_image"
  24 + }
  25 + }
  26 +
  27 + var title: String {
  28 + switch self {
  29 + case .snapPhotoSlide:
  30 + return "Web Surfing Protection"
  31 + case .submitPhotoSlide:
  32 + return "Ad Blocking"
  33 + case .getRewardsSlide:
  34 + return "Warning Scanning"
  35 + }
  36 + }
  37 +
  38 + var subTitle: String {
  39 + switch self {
  40 + case .snapPhotoSlide:
  41 + return "This application makes your web surfing safe and private. Forget about the leakage of your personal data."
  42 + case .submitPhotoSlide:
  43 + return "GotoWeb blocks 95% of all internet ads and makes page loading 30% faster."
  44 + case .getRewardsSlide:
  45 + return "Be protected from visiting potentially dangerous phishing and fraudulent websites."
  46 + }
  47 + }
  48 +}
  1 +//
  2 +// PageView.swift
  3 +// Pro-Seecurity-VPN
  4 +//
  5 +// Created by Volodymyr Kolomyltsev on 12/22/23.
  6 +//
  7 +
  8 +import Foundation
  9 +import UIKit
  10 +import SnapKit
  11 +
  12 +class PageView: UIView {
  13 +
  14 + var model: OnboardingType? {
  15 + didSet {
  16 + handleUI(model: model!)
  17 + }
  18 + }
  19 +
  20 + private let containerView: UIView = {
  21 + let obj = UIView()
  22 +
  23 +
  24 + return obj
  25 + }()
  26 +
  27 + private let imgView: UIImageView = {
  28 + let obj = UIImageView()
  29 + obj.contentMode = .scaleAspectFill
  30 + return obj
  31 + }()
  32 +
  33 + private let titleLbl: UILabel = {
  34 + let obj = UILabel()
  35 + obj.lineBreakMode = .byWordWrapping
  36 + obj.font = .systemFont(ofSize: 26, weight: .bold)
  37 + obj.numberOfLines = 2
  38 + obj.textAlignment = .center
  39 + return obj
  40 + }()
  41 +
  42 + private let subTitleLbl: UILabel = {
  43 + let obj = UILabel()
  44 + obj.font = .systemFont(ofSize: 15, weight: .regular)
  45 + obj.lineBreakMode = .byWordWrapping
  46 + obj.numberOfLines = 3
  47 + obj.textAlignment = .center
  48 + return obj
  49 + }()
  50 +
  51 + override init(frame: CGRect) {
  52 + super.init(frame: frame)
  53 + setup()
  54 + }
  55 +
  56 + required init?(coder: NSCoder) {
  57 + fatalError("init(coder:) has not been implemented")
  58 + }
  59 +
  60 + private func setup() {
  61 + backgroundColor = .clear
  62 + addSubview(containerView)
  63 + containerView.addSubview(imgView)
  64 + addSubview(titleLbl)
  65 + addSubview(subTitleLbl)
  66 +
  67 + containerView.snp.makeConstraints { make in
  68 + make.leading.trailing.equalToSuperview()
  69 + make.height.equalTo(220.sizeH)
  70 + make.top.equalToSuperview()
  71 + make.bottom.equalTo(titleLbl.snp.top).offset(-48.sizeH)
  72 + }
  73 +
  74 + imgView.snp.makeConstraints { make in
  75 + make.edges.equalToSuperview()
  76 + }
  77 +
  78 + titleLbl.snp.makeConstraints { make in
  79 + make.bottom.equalTo(subTitleLbl.snp.top).offset(-8.sizeH)
  80 + make.centerX.equalTo(containerView)
  81 + make.width.equalTo(300.sizeW)
  82 + }
  83 +
  84 + subTitleLbl.snp.makeConstraints { make in
  85 +// make.top.equalTo(titleLbl.snp.bottom).offset(8.sizeH)
  86 + make.width.equalTo(300.sizeW)
  87 + make.centerX.equalTo(titleLbl)
  88 + make.bottom.equalToSuperview()
  89 + }
  90 + }
  91 +
  92 +}
  93 +
  94 +//MARK: Helpers
  95 +extension PageView {
  96 +
  97 + private func handleUI(model: OnboardingType) {
  98 + imgView.image = UIImage(named: model.imgString)
  99 + titleLbl.text = model.title
  100 + subTitleLbl.text = model.subTitle
  101 + }
  102 +
  103 +}
  1 +//
  2 +// NewPaywallView.swift
  3 +// Pro-Seecurity-VPN
  4 +//
  5 +// Created by Volodymyr Kolomyltsev on 12/22/23.
  6 +//
  7 +
  8 +import Foundation
  9 +import UIKit
  10 +import SnapKit
  11 +
  12 +class OnboardingView: UIView {
  13 +
  14 + private let stackView: UIStackView = {
  15 + let obj = UIStackView()
  16 + obj.axis = .horizontal
  17 + obj.distribution = .fillEqually
  18 + obj.spacing = 15.sizeW
  19 + return obj
  20 + }()
  21 +
  22 + let closeButton: UIButton = {
  23 + let obj = UIButton()
  24 + obj.setImage(UIImage(systemName: "xmark"), for: .normal)
  25 + obj.contentMode = .scaleToFill
  26 + obj.tintColor = .white
  27 +
  28 + return obj
  29 + }()
  30 +
  31 + let backgroundImageView: UIImageView = {
  32 + let obj = UIImageView()
  33 + let imageBackground = UIImage(named: "newPaywalBackground")
  34 + obj.image = imageBackground
  35 + return obj
  36 + }()
  37 +
  38 + let scrollView: UIScrollView = {
  39 + let obj = UIScrollView()
  40 + obj.isScrollEnabled = true
  41 + obj.showsHorizontalScrollIndicator = false
  42 + obj.showsVerticalScrollIndicator = false
  43 + obj.contentInsetAdjustmentBehavior = .always
  44 + obj.isPagingEnabled = true
  45 + obj.contentInset = .zero
  46 + return obj
  47 + }()
  48 +
  49 + private let snapPhotoPage: PageView = {
  50 + let obj = PageView()
  51 + obj.model = .snapPhotoSlide
  52 + return obj
  53 + }()
  54 +
  55 + private let submitPhotoPage: PageView = {
  56 + let obj = PageView()
  57 + obj.model = .submitPhotoSlide
  58 + return obj
  59 + }()
  60 +
  61 + private let getRewardsPhotoPage: PageView = {
  62 + let obj = PageView()
  63 + obj.model = .getRewardsSlide
  64 + return obj
  65 + }()
  66 +
  67 + let pageControl: UIPageControl = {
  68 + let obj = UIPageControl()
  69 + obj.numberOfPages = 3
  70 + obj.currentPage = 0
  71 + obj.clipsToBounds = true
  72 + return obj
  73 + }()
  74 +
  75 + let infoLabel: UILabel = {
  76 + let obj = UILabel()
  77 + obj.text = "3 дня бесплатной пробной версии, затем $9,99 в неделю"
  78 + obj.font = .systemFont(ofSize: 12.sizeW, weight: .regular)
  79 + obj.numberOfLines = 2
  80 + obj.textAlignment = .center
  81 + return obj
  82 + }()
  83 +
  84 + private let buttonsStackView: UIStackView = {
  85 + let obj = UIStackView()
  86 + obj.axis = .horizontal
  87 + obj.alignment = .center
  88 + obj.distribution = .fillEqually
  89 + obj.spacing = 6.sizeW
  90 + return obj
  91 + }()
  92 +
  93 + let restoreButton: UIButton = {
  94 + let obj = UIButton()
  95 + obj.setTitle("Restore", for: .normal)
  96 + obj.setTitleColor(.white, for: .normal)
  97 + obj.setTitleColor(.white, for: .highlighted)
  98 + obj.titleLabel?.font = UIFont.systemFont(ofSize: 12.sizeW, weight: .regular)
  99 + obj.titleLabel?.lineBreakMode = .byWordWrapping
  100 + return obj
  101 + }()
  102 +
  103 + let privacyButton: UIButton = {
  104 + let obj = UIButton()
  105 + obj.setTitle("Privacy", for: .normal)
  106 + obj.setTitleColor(.white, for: .normal)
  107 + obj.setTitleColor(.white, for: .highlighted)
  108 + obj.titleLabel?.font = UIFont.systemFont(ofSize: 12.sizeW, weight: .regular)
  109 + obj.titleLabel?.lineBreakMode = .byWordWrapping
  110 + return obj
  111 + }()
  112 +
  113 +
  114 + let termsButton: UIButton = {
  115 + let obj = UIButton()
  116 + obj.setTitle("Terms", for: .normal)
  117 + obj.setTitleColor(.white, for: .normal)
  118 + obj.setTitleColor(.white, for: .highlighted)
  119 + obj.titleLabel?.font = UIFont.systemFont(ofSize: 12.sizeW, weight: .regular)
  120 + obj.titleLabel?.lineBreakMode = .byWordWrapping
  121 + return obj
  122 + }()
  123 +
  124 + let activateButton: UIButton = {
  125 + let obj = UIButton()
  126 + obj.backgroundColor = UIColor(red: 15/255, green: 125/255, blue: 255/255, alpha: 1)
  127 + obj.layer.cornerRadius = 6.sizeH
  128 + obj.titleLabel?.font = UIFont.systemFont(ofSize: 16.sizeW, weight: .bold)
  129 + obj.setTitle("Activate Now", for: .normal)
  130 + return obj
  131 + }()
  132 +
  133 +
  134 + override init(frame: CGRect) {
  135 + super.init(frame: frame)
  136 + setup()
  137 + }
  138 +
  139 + required init?(coder: NSCoder) {
  140 + fatalError("init(coder:) has not been implemented")
  141 + }
  142 +
  143 + override func layoutSubviews() {
  144 + super.layoutSubviews()
  145 +// scrollView.contentInset.left = 10.sizeW
  146 + scrollView.contentSize = CGSize(width: scrollView.bounds.width*3, height: scrollView.bounds.height)
  147 + }
  148 +
  149 + private func setup() {
  150 +// backgroundColor = .red
  151 + addSubview(backgroundImageView)
  152 + addSubview(scrollView)
  153 + addSubview(pageControl)
  154 +
  155 + addSubview(infoLabel)
  156 + addSubview(activateButton)
  157 + addSubview(buttonsStackView)
  158 + addSubview(closeButton)
  159 +
  160 + buttonsStackView.addArrangedSubview(privacyButton)
  161 + buttonsStackView.addArrangedSubview(termsButton)
  162 + buttonsStackView.addArrangedSubview(restoreButton)
  163 +
  164 + scrollView.addSubview(snapPhotoPage)
  165 + scrollView.addSubview(submitPhotoPage)
  166 + scrollView.addSubview(getRewardsPhotoPage)
  167 +
  168 +// scrollView.backgroundColor = .black
  169 +
  170 + pageControl.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
  171 +
  172 + closeButton.snp.makeConstraints { make in
  173 + make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(16.sizeH)
  174 + make.leading.equalToSuperview().inset(16.sizeW)
  175 + make.height.equalTo(24.sizeH)
  176 + }
  177 +
  178 + backgroundImageView.snp.makeConstraints { make in
  179 + make.edges.equalToSuperview()
  180 + }
  181 +
  182 + scrollView.snp.makeConstraints { make in
  183 + make.top.equalTo(closeButton.snp.bottom).inset(-16.sizeH)
  184 + make.trailing.leading.equalToSuperview()
  185 + make.bottom.equalTo(pageControl.snp.top).offset(-16.sizeH)
  186 + }
  187 +
  188 + pageControl.snp.makeConstraints { make in
  189 + make.centerX.equalToSuperview()
  190 + make.bottom.equalTo(activateButton.snp.top).offset(-60.sizeH)
  191 + make.height.equalTo(16.sizeH)
  192 + }
  193 +
  194 + snapPhotoPage.snp.makeConstraints { make in
  195 + make.width.equalToSuperview()
  196 + make.top.equalToSuperview()
  197 + make.bottom.equalToSuperview()
  198 + make.leading.equalToSuperview()
  199 + }
  200 +
  201 + submitPhotoPage.snp.makeConstraints { make in
  202 + make.width.equalToSuperview()
  203 + make.top.equalToSuperview()
  204 + make.bottom.equalToSuperview()
  205 + make.leading.equalTo(snapPhotoPage.snp.trailing)
  206 + }
  207 +
  208 + getRewardsPhotoPage.snp.makeConstraints { make in
  209 + make.width.equalToSuperview()
  210 + make.top.equalToSuperview()
  211 + make.bottom.equalToSuperview()
  212 + make.leading.equalTo(submitPhotoPage.snp.trailing)
  213 + make.trailing.equalToSuperview()
  214 + }
  215 +
  216 + activateButton.snp.makeConstraints { make in
  217 + make.leading.trailing.equalToSuperview().inset(16)
  218 + make.height.equalTo(51.sizeH)
  219 + make.bottom.equalTo(infoLabel.snp.top).offset(-24.sizeH)
  220 + }
  221 +
  222 + infoLabel.snp.makeConstraints { make in
  223 + make.leading.trailing.equalToSuperview().inset(16)
  224 + make.height.equalTo(16.sizeH)
  225 + make.bottom.equalTo(buttonsStackView.snp.top).offset(-43.sizeH)
  226 + }
  227 +
  228 + buttonsStackView.snp.makeConstraints { make in
  229 + make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom).offset(-51.sizeH)
  230 + make.leading.trailing.equalToSuperview().inset(16)
  231 + }
  232 + }
  233 +}
  1 +//
  2 +// Use this file to import your target's public headers that you would like to expose to Swift.
  3 +//
  4 +
  5 +#import "VPNManagerStatus.h"
  1 +//
  2 +// VpnStatus.h
  3 +// VPN-HD
  4 +#import <Foundation/Foundation.h>
  5 +//
  6 +//
  7 +//#ifndef NS_ENUM
  8 +//#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
  9 +//#endif
  10 +typedef NS_ENUM(NSInteger, VPNManagerStatus) {
  11 + VPNManagerStatusConnected = 0,
  12 + VPNManagerStatusConnecting = 1,
  13 + VPNManagerStatusDisconnected = 2,
  14 + VPNManagerStatusDisconnecting = 3,
  15 + VPNManagerStatusNoCertificate = 4,
  16 +#ifdef TARGET_OS_IOS
  17 + VPNManagerStatusNoCertificateSettings = 5,
  18 +#endif
  19 +};
Please register or login to post a comment