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