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 | }; |
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
Pro-Seecurity-VPN.xcodeproj/xcuserdata/admin.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
0 → 100644
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() -> ()" | ||
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() -> ()" | ||
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() -> ()" | ||
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() -> ()" | ||
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() -> ()" | ||
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() -> ()" | ||
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> |
Pro-Seecurity-VPN.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/xcschememanagement.plist
0 → 100644
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> |
Pro-Seecurity-VPN.xcodeproj/xcuserdata/eugeney.xcuserdatad/xcschemes/xcschememanagement.plist
0 → 100644
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> |
Pro-Seecurity-VPN.xcodeproj/xcuserdata/user247686.xcuserdatad/xcschemes/xcschememanagement.plist
0 → 100644
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 | +// 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 | +} |
browser/Common/Helpers/ProgressHelper.swift
0 → 100644
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"] |
browser/Common/Resources/Images/Assets.xcassets/NewPaywall/card_paywall_image.imageset/Contents.json
0 → 100644
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 | +} |
7.67 KB
12 KB
12 KB
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 | +} |
browser/Common/Resources/Images/Assets.xcassets/NewPaywall/newPaywalBackground.imageset/Group 14.png
0 → 100644
109 KB
292 KB
521 KB
browser/Common/Resources/Images/Assets.xcassets/NewPaywall/scan_paywall_image.imageset/Contents.json
0 → 100644
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 | +} |
4.8 KB
9.49 KB
14.9 KB
browser/Common/Resources/Images/Assets.xcassets/NewPaywall/tv_paywall_image.imageset/Contents.json
0 → 100644
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 | +} |
browser/Common/Resources/Images/Assets.xcassets/NewPaywall/tv_paywall_image.imageset/Group 14.png
0 → 100644
3.79 KB
browser/Common/Resources/Images/Assets.xcassets/NewPaywall/tv_paywall_image.imageset/Group 14@2x.png
0 → 100644
7.74 KB
browser/Common/Resources/Images/Assets.xcassets/NewPaywall/tv_paywall_image.imageset/Group 14@3x.png
0 → 100644
12.5 KB
@@ -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 | +} |
browser/Objc/VPNManagerStatus.h
0 → 100644
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