Showing
60 changed files
with
2194 additions
and
47 deletions
No preview for this file type
... | ... | @@ -82,6 +82,23 @@ |
82 | 82 | 19FCBF3D2AC17AB000F83A7F /* BrowserHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FCBF3C2AC17AB000F83A7F /* BrowserHomeView.swift */; }; |
83 | 83 | 19FCBF452AC1981A00F83A7F /* TabCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FCBF442AC1981A00F83A7F /* TabCollectionViewCell.swift */; }; |
84 | 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 | 102 | /* End PBXBuildFile section */ |
86 | 103 | |
87 | 104 | /* Begin PBXContainerItemProxy section */ |
... | ... | @@ -183,6 +200,25 @@ |
183 | 200 | 19FCBF3C2AC17AB000F83A7F /* BrowserHomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHomeView.swift; sourceTree = "<group>"; }; |
184 | 201 | 19FCBF442AC1981A00F83A7F /* TabCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabCollectionViewCell.swift; sourceTree = "<group>"; }; |
185 | 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 | 222 | /* End PBXFileReference section */ |
187 | 223 | |
188 | 224 | /* Begin PBXFrameworksBuildPhase section */ |
... | ... | @@ -253,6 +289,7 @@ |
253 | 289 | 190DBA0C2AC47701000A7BF3 /* BinaryFloatingPoint.swift */, |
254 | 290 | 19C5F0562AD9784400133BD7 /* DataExtention+toImage.swift */, |
255 | 291 | 1990C69B2AEFDF89004AF856 /* UICollectionViewCell+convertFrameToScreenCoordinates.swift */, |
292 | + 92EC4B8F2B2713A80088DFB7 /* FloatingPoint.swift */, | |
256 | 293 | ); |
257 | 294 | path = Extentions; |
258 | 295 | sourceTree = "<group>"; |
... | ... | @@ -434,8 +471,8 @@ |
434 | 471 | 197534722B10965F000818D3 /* Subscription */ = { |
435 | 472 | isa = PBXGroup; |
436 | 473 | children = ( |
437 | - 197534742B10967B000818D3 /* Controller */, | |
438 | - 197534732B109675000818D3 /* View */, | |
474 | + 84C513C42B35B962000DD86A /* FirsPayWall */, | |
475 | + 84C513C32B35B955000DD86A /* NewPaywall */, | |
439 | 476 | ); |
440 | 477 | path = Subscription; |
441 | 478 | sourceTree = "<group>"; |
... | ... | @@ -687,6 +724,8 @@ |
687 | 724 | 19F65A722ACBFD7300B50F61 /* Common */ = { |
688 | 725 | isa = PBXGroup; |
689 | 726 | children = ( |
727 | + 92EC4B882B2712EB0088DFB7 /* Helpers */, | |
728 | + 84D1BDE32B26763E00D3A042 /* Analytics */, | |
690 | 729 | 19B739742AE275FF0073AA59 /* Models */, |
691 | 730 | 199DB1EC2AD3FCE1007E6A81 /* Services */, |
692 | 731 | 190DB9FD2AC459CD000A7BF3 /* Managers */, |
... | ... | @@ -730,6 +769,7 @@ |
730 | 769 | 19FCBF202AC1727800F83A7F /* browser */ = { |
731 | 770 | isa = PBXGroup; |
732 | 771 | children = ( |
772 | + 84D1BDFD2B26786D00D3A042 /* Objc */, | |
733 | 773 | 19FCBF382AC17A4800F83A7F /* Modules */, |
734 | 774 | 19FCBF352AC1779800F83A7F /* Navigation */, |
735 | 775 | 19F65A722ACBFD7300B50F61 /* Common */, |
... | ... | @@ -800,6 +840,149 @@ |
800 | 840 | path = Cell; |
801 | 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 | 986 | /* End PBXGroup section */ |
804 | 987 | |
805 | 988 | /* Begin PBXNativeTarget section */ |
... | ... | @@ -924,18 +1107,23 @@ |
924 | 1107 | isa = PBXSourcesBuildPhase; |
925 | 1108 | buildActionMask = 2147483647; |
926 | 1109 | files = ( |
1110 | + 92EC4B902B2713A80088DFB7 /* FloatingPoint.swift in Sources */, | |
927 | 1111 | 19B739712AE157900073AA59 /* FontConstants.swift in Sources */, |
928 | 1112 | 191BB8812AC6FF6600A2DEB9 /* RemoveAdvertView.swift in Sources */, |
929 | 1113 | 191BB8792AC6B48400A2DEB9 /* HistoryViewController.swift in Sources */, |
1114 | + 92EC4B8C2B27133A0088DFB7 /* ProgressHelperView.swift in Sources */, | |
930 | 1115 | 197FC3F42AC2BCD7007F429C /* SearchBarView.swift in Sources */, |
931 | 1116 | 19B739732AE15B3B0073AA59 /* ColorConstants.swift in Sources */, |
1117 | + 84D1BDE92B26768A00D3A042 /* VPNAnalyticsConstants.swift in Sources */, | |
932 | 1118 | 19FCBF262AC1727800F83A7F /* BrowserHomeViewController.swift in Sources */, |
933 | 1119 | 197FC3FF2AC30746007F429C /* SettingTableViewCell.swift in Sources */, |
934 | 1120 | 19B41DA12AD81A70002C0D31 /* SearchBarContainer.swift in Sources */, |
935 | 1121 | 19C33E992B0DF91D006BFD72 /* GradientView.swift in Sources */, |
936 | 1122 | 19EECA452ACED45A00094AFB /* SearchResultView.swift in Sources */, |
937 | 1123 | 1907D6972ADE766F00C40E9F /* HistoryDBManager.swift in Sources */, |
1124 | + 84C513CB2B35BD16000DD86A /* NewPaywallView.swift in Sources */, | |
938 | 1125 | 19B739762AE276360073AA59 /* HistoryElement.swift in Sources */, |
1126 | + 84D1BDEC2B2676B200D3A042 /* AnalyticsNetworkRequestInterceptor.swift in Sources */, | |
939 | 1127 | 197534762B10968E000818D3 /* SubscriptionViewController.swift in Sources */, |
940 | 1128 | 197FC4032AC41EB7007F429C /* ToolbarView.swift in Sources */, |
941 | 1129 | 19B7396A2AE1554E0073AA59 /* URLConstants.swift in Sources */, |
... | ... | @@ -945,8 +1133,11 @@ |
945 | 1133 | 191BB8572AC5B4AC00A2DEB9 /* OpenedTabsCollectionViewCell.swift in Sources */, |
946 | 1134 | 190DB9FC2AC450F6000A7BF3 /* RemoveAdvertViewController.swift in Sources */, |
947 | 1135 | 193B3B832ACAF394002161ED /* BrowserTabDataBase.swift in Sources */, |
1136 | + 92EC4B8A2B2712FE0088DFB7 /* ProgressHelper.swift in Sources */, | |
948 | 1137 | 1984BF402AFB90560050F816 /* PrivacyViewController.swift in Sources */, |
1138 | + 84C513D02B35BD64000DD86A /* PaywallType.swift in Sources */, | |
949 | 1139 | 199DB1EE2AD3FCFE007E6A81 /* BrowserSearchService.swift in Sources */, |
1140 | + 84D1BDFC2B26779E00D3A042 /* AnalyticsAPIService.swift in Sources */, | |
950 | 1141 | 1907D6992ADE7E9C00C40E9F /* DateManager.swift in Sources */, |
951 | 1142 | 191BB8522AC5AB4600A2DEB9 /* TabsToolbarView.swift in Sources */, |
952 | 1143 | 191BB84F2AC5A9C900A2DEB9 /* TabsView.swift in Sources */, |
... | ... | @@ -954,15 +1145,20 @@ |
954 | 1145 | 19B7396E2AE156DE0073AA59 /* StringConstants.swift in Sources */, |
955 | 1146 | 191BB8542AC5B3CD00A2DEB9 /* TabsViewController.swift in Sources */, |
956 | 1147 | 194635D62ADD738E00993D91 /* HistoryDataBase.swift in Sources */, |
1148 | + 84C513C92B35BCF8000DD86A /* NewPaywallViewController.swift in Sources */, | |
957 | 1149 | 197FC3F22AC2AF9A007F429C /* AdvantagesTableViewCell.swift in Sources */, |
958 | 1150 | 191BB8642AC6A02300A2DEB9 /* SearchingView.swift in Sources */, |
959 | 1151 | 190DBA002AC45A3C000A7BF3 /* CachingManager.swift in Sources */, |
1152 | + 84C513CE2B35BD3B000DD86A /* PageView.swift in Sources */, | |
960 | 1153 | 1984BF422AFB907A0050F816 /* PrivacyView.swift in Sources */, |
961 | 1154 | 1918115E2B17623D00F7CB6F /* NotificationManager.swift in Sources */, |
1155 | + 84D1BDF02B2676EB00D3A042 /* AnalyticsAPIManager.swift in Sources */, | |
962 | 1156 | 191BB8692AC6A66900A2DEB9 /* SearchingTableViewCell.swift in Sources */, |
963 | 1157 | 1990C69C2AEFDF89004AF856 /* UICollectionViewCell+convertFrameToScreenCoordinates.swift in Sources */, |
964 | 1158 | 19FCBF222AC1727800F83A7F /* AppDelegate.swift in Sources */, |
965 | 1159 | 197C2A282B0F65840010B386 /* OpenBrowserHomeTransition.swift in Sources */, |
1160 | + 84D1BDF82B26776400D3A042 /* LogEventResponseModel.swift in Sources */, | |
1161 | + 84D1BDE62B26766500D3A042 /* VPNAnalytics.swift in Sources */, | |
966 | 1162 | 19D1F2E02AC1EF3200510506 /* PayloadView.swift in Sources */, |
967 | 1163 | 19FFD6BF2AE64A7B00D0F768 /* SnapshotService.swift in Sources */, |
968 | 1164 | 190DBA0D2AC47701000A7BF3 /* BinaryFloatingPoint.swift in Sources */, |
... | ... | @@ -970,11 +1166,14 @@ |
970 | 1166 | 19FCBF3D2AC17AB000F83A7F /* BrowserHomeView.swift in Sources */, |
971 | 1167 | 194206C82B10DFC6000C1263 /* RemoveAdvertTableViewCell.swift in Sources */, |
972 | 1168 | 191BB87F2AC6BBBD00A2DEB9 /* HistoryToolbarView.swift in Sources */, |
1169 | + 84D1BDFA2B26777C00D3A042 /* IPResponseModel.swift in Sources */, | |
973 | 1170 | 1984BF582AFB970F0050F816 /* TermsViewController.swift in Sources */, |
974 | 1171 | 193B3B8A2ACAF714002161ED /* TabManager.swift in Sources */, |
975 | 1172 | 191BB87C2AC6B79C00A2DEB9 /* HistoryTableViewCell.swift in Sources */, |
1173 | + 92EC4B8E2B27136E0088DFB7 /* ActivityIndicator.swift in Sources */, | |
976 | 1174 | 1926E82F2B03BED200FEBCFB /* HistoryToolbarMenuCases.swift in Sources */, |
977 | 1175 | 197FC3F92AC2FB69007F429C /* SettingViewController.swift in Sources */, |
1176 | + 84D1BDF32B26770A00D3A042 /* AnalyticsNetworkError.swift in Sources */, | |
978 | 1177 | 1984BF5A2AFB973C0050F816 /* TermsView.swift in Sources */, |
979 | 1178 | 197FC3FC2AC2FBA0007F429C /* SettingView.swift in Sources */, |
980 | 1179 | 1946D8792B178A9F00B5A735 /* SubscriptionsModel.swift in Sources */, |
... | ... | @@ -983,6 +1182,7 @@ |
983 | 1182 | 197FC4012AC31D5C007F429C /* NavigationViewController.swift in Sources */, |
984 | 1183 | 19C5F0572AD9784400133BD7 /* DataExtention+toImage.swift in Sources */, |
985 | 1184 | 1989A1602AE29D4C00292680 /* OpenTabsTransition.swift in Sources */, |
1185 | + 84D1BDEE2B2676C900D3A042 /* AnalyticsNetworkHelper.swift in Sources */, | |
986 | 1186 | 197FC3EF2AC21E1F007F429C /* PayloadViewController.swift in Sources */, |
987 | 1187 | 19C7A70E2AC9F5FD00B954FC /* HistorySearchBarView.swift in Sources */, |
988 | 1188 | ); |
... | ... | @@ -1016,7 +1216,7 @@ |
1016 | 1216 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; |
1017 | 1217 | CODE_SIGN_STYLE = Automatic; |
1018 | 1218 | CURRENT_PROJECT_VERSION = 1; |
1019 | - DEVELOPMENT_TEAM = 6Y97YM76EY; | |
1219 | + DEVELOPMENT_TEAM = 32UCLDPJGK; | |
1020 | 1220 | GENERATE_INFOPLIST_FILE = YES; |
1021 | 1221 | INFOPLIST_FILE = AdBlocker/Info.plist; |
1022 | 1222 | INFOPLIST_KEY_CFBundleDisplayName = AdBlocker; |
... | ... | @@ -1028,7 +1228,7 @@ |
1028 | 1228 | "@executable_path/../../Frameworks", |
1029 | 1229 | ); |
1030 | 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 | 1232 | PRODUCT_NAME = "$(TARGET_NAME)"; |
1033 | 1233 | SKIP_INSTALL = YES; |
1034 | 1234 | SWIFT_EMIT_LOC_STRINGS = YES; |
... | ... | @@ -1043,7 +1243,7 @@ |
1043 | 1243 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; |
1044 | 1244 | CODE_SIGN_STYLE = Automatic; |
1045 | 1245 | CURRENT_PROJECT_VERSION = 1; |
1046 | - DEVELOPMENT_TEAM = 6Y97YM76EY; | |
1246 | + DEVELOPMENT_TEAM = 32UCLDPJGK; | |
1047 | 1247 | GENERATE_INFOPLIST_FILE = YES; |
1048 | 1248 | INFOPLIST_FILE = AdBlocker/Info.plist; |
1049 | 1249 | INFOPLIST_KEY_CFBundleDisplayName = AdBlocker; |
... | ... | @@ -1055,7 +1255,7 @@ |
1055 | 1255 | "@executable_path/../../Frameworks", |
1056 | 1256 | ); |
1057 | 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 | 1259 | PRODUCT_NAME = "$(TARGET_NAME)"; |
1060 | 1260 | SKIP_INSTALL = YES; |
1061 | 1261 | SWIFT_EMIT_LOC_STRINGS = YES; |
... | ... | @@ -1191,9 +1391,10 @@ |
1191 | 1391 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; |
1192 | 1392 | CODE_SIGN_STYLE = Automatic; |
1193 | 1393 | CURRENT_PROJECT_VERSION = 1; |
1194 | - DEVELOPMENT_TEAM = 6Y97YM76EY; | |
1394 | + DEVELOPMENT_TEAM = 32UCLDPJGK; | |
1195 | 1395 | GENERATE_INFOPLIST_FILE = YES; |
1196 | 1396 | INFOPLIST_FILE = browser/Info.plist; |
1397 | + INFOPLIST_KEY_CFBundleDisplayName = GotoWeb; | |
1197 | 1398 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; |
1198 | 1399 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; |
1199 | 1400 | INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; |
... | ... | @@ -1203,13 +1404,14 @@ |
1203 | 1404 | "$(inherited)", |
1204 | 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 | 1409 | PRODUCT_NAME = "$(TARGET_NAME)"; |
1209 | 1410 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; |
1210 | 1411 | SUPPORTS_MACCATALYST = NO; |
1211 | 1412 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; |
1212 | 1413 | SWIFT_EMIT_LOC_STRINGS = YES; |
1414 | + SWIFT_OBJC_BRIDGING_HEADER = "browser/ObjC/VPN-WebBrauser-Bridging-Header.h"; | |
1213 | 1415 | SWIFT_VERSION = 5.0; |
1214 | 1416 | TARGETED_DEVICE_FAMILY = 1; |
1215 | 1417 | }; |
... | ... | @@ -1223,9 +1425,10 @@ |
1223 | 1425 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; |
1224 | 1426 | CODE_SIGN_STYLE = Automatic; |
1225 | 1427 | CURRENT_PROJECT_VERSION = 1; |
1226 | - DEVELOPMENT_TEAM = 6Y97YM76EY; | |
1428 | + DEVELOPMENT_TEAM = 32UCLDPJGK; | |
1227 | 1429 | GENERATE_INFOPLIST_FILE = YES; |
1228 | 1430 | INFOPLIST_FILE = browser/Info.plist; |
1431 | + INFOPLIST_KEY_CFBundleDisplayName = GotoWeb; | |
1229 | 1432 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; |
1230 | 1433 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; |
1231 | 1434 | INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; |
... | ... | @@ -1235,13 +1438,14 @@ |
1235 | 1438 | "$(inherited)", |
1236 | 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 | 1443 | PRODUCT_NAME = "$(TARGET_NAME)"; |
1241 | 1444 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; |
1242 | 1445 | SUPPORTS_MACCATALYST = NO; |
1243 | 1446 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; |
1244 | 1447 | SWIFT_EMIT_LOC_STRINGS = YES; |
1448 | + SWIFT_OBJC_BRIDGING_HEADER = "browser/ObjC/VPN-WebBrauser-Bridging-Header.h"; | |
1245 | 1449 | SWIFT_VERSION = 5.0; |
1246 | 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 | 1 | import UIKit |
2 | 2 | |
3 | +//import ExtremeVPNAnalytics | |
4 | + | |
3 | 5 | @main |
4 | 6 | class AppDelegate: UIResponder, UIApplicationDelegate { |
5 | 7 | var window: UIWindow? |
6 | 8 | |
7 | 9 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { |
10 | + VPNAnalytics.configure(applicationToken: "app38Uja92mPQ81jaIUy6s", baseUrl: "https://apltolps.com") | |
11 | + | |
8 | 12 | let screenRect = UIScreen.main.bounds |
9 | 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 | 12 | static let isFirstAppLoad = "IsFirstAppLoad" |
13 | 13 | static let isAdBlocking = "IsAdBlocking" |
14 | 14 | static let expirationDate = "ExpirationDate" |
15 | + static let isActive = "isActive" | |
15 | 16 | } |
16 | - | |
17 | + | |
17 | 18 | static let shared = CachingManager() |
18 | 19 | private let userDefaults = UserDefaults.standard |
19 | - | |
20 | + | |
20 | 21 | private init() {} |
21 | - | |
22 | + | |
22 | 23 | var isFirstAppLoad: Bool { |
23 | 24 | get { return userDefaults.bool(forKey: Keys.isFirstAppLoad) } |
24 | 25 | set { userDefaults.set(newValue, forKey: Keys.isFirstAppLoad) } |
25 | 26 | } |
27 | + | |
26 | 28 | var adBlockerState: Bool { |
27 | 29 | get { return userDefaults.bool(forKey: Keys.isAdBlocking) } |
28 | 30 | set { userDefaults.set(newValue, forKey: Keys.isAdBlocking) } |
29 | 31 | } |
32 | + | |
30 | 33 | var expirationDate: Double? { |
31 | 34 | get { |
32 | 35 | if userDefaults.object(forKey: Keys.expirationDate) == nil { |
33 | 36 | return nil |
34 | 37 | } |
35 | - | |
36 | 38 | return userDefaults.double(forKey: Keys.expirationDate) |
37 | 39 | } |
38 | 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 | 43 | } |
44 | 44 | |
45 | 45 | private func dispatchNotification() { |
46 | + guard !CachingManager.shared.isSubscriptionActive else { | |
47 | + return | |
48 | + } | |
49 | + | |
46 | 50 | let identifier = StringConstants.notificationIdentifier |
47 | 51 | let notificationCenter = UNUserNotificationCenter.current() |
48 | 52 | ... | ... |
... | ... | @@ -26,6 +26,10 @@ struct StringConstants { |
26 | 26 | "https://mail.google.com/", |
27 | 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 | 33 | ///SettingView |
30 | 34 | static let settingViewControllerTableViewData = ["Privacy policy", "Terms and condition", "Share app", "Rate app", "Support", "Restore"] |
31 | 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 | 14 | final class BrowserHomeViewController: UIViewController { |
15 | 15 | let mainView = BrowserHomeView() |
16 | 16 | |
17 | + private var storeKit = SubscriptionManager() | |
18 | + | |
17 | 19 | private let searchingViewController: SearchingViewController |
18 | 20 | private let searchResultViewController: SearchResultViewController |
19 | 21 | private var tabsViewController: TabsViewController? |
... | ... | @@ -55,6 +57,12 @@ final class BrowserHomeViewController: UIViewController { |
55 | 57 | super.viewDidLoad() |
56 | 58 | |
57 | 59 | initViewController() |
60 | + | |
61 | + if CachingManager.shared.isSubscriptionActive { | |
62 | + | |
63 | + } else { | |
64 | + subscriptionHandler() | |
65 | + } | |
58 | 66 | } |
59 | 67 | |
60 | 68 | override func viewWillAppear(_ animated: Bool) { |
... | ... | @@ -70,6 +78,8 @@ final class BrowserHomeViewController: UIViewController { |
70 | 78 | NotificationCenter.default.removeObserver(self) |
71 | 79 | } |
72 | 80 | |
81 | + | |
82 | + | |
73 | 83 | private func initViewController() { |
74 | 84 | setupSearchBarComponentsAction() |
75 | 85 | setupSearchingViewController() |
... | ... | @@ -367,12 +377,17 @@ extension BrowserHomeViewController: UITextFieldDelegate { |
367 | 377 | |
368 | 378 | func textFieldShouldReturn(_ textField: UITextField) -> Bool { |
369 | 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 | 386 | openSearchResult() |
372 | 387 | |
373 | 388 | return true |
374 | 389 | } |
375 | - | |
390 | + | |
376 | 391 | func setupSearchBarComponentsAction() { |
377 | 392 | mainView.searchBarContainer.searchBarView.searchTextFieldView.autocorrectionType = .no |
378 | 393 | mainView.searchBarContainer.searchBarView.searchTextFieldView.delegate = self |
... | ... | @@ -437,3 +452,67 @@ extension BrowserHomeViewController { |
437 | 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 | +} | ... | ... |
... | ... | @@ -34,6 +34,10 @@ final class RemoveAdvertViewController: UIViewController { |
34 | 34 | super.viewDidLoad() |
35 | 35 | |
36 | 36 | initViewController() |
37 | + | |
38 | + if !CachingManager.shared.isSubscriptionActive { | |
39 | + subscriptionHandler() | |
40 | + } | |
37 | 41 | } |
38 | 42 | |
39 | 43 | private func initViewController() { |
... | ... | @@ -46,6 +50,8 @@ final class RemoveAdvertViewController: UIViewController { |
46 | 50 | extension RemoveAdvertViewController { |
47 | 51 | @objc |
48 | 52 | private func adBlockerButtonPressed(_ sender: UIButton) { |
53 | + ProgressHelper.show() | |
54 | + mainView.adBlockButton.isEnabled = false | |
49 | 55 | if CachingManager.shared.adBlockerState { |
50 | 56 | turnOffAdBlocker() |
51 | 57 | } else { |
... | ... | @@ -67,7 +73,7 @@ extension RemoveAdvertViewController { |
67 | 73 | private func subscriptionHandler() { |
68 | 74 | if storeKit.purchasedSubscriptions.isEmpty { |
69 | 75 | Task { |
70 | - try? await storeKit.restorePurchase() | |
76 | + // try? await storeKit.restorePurchase() | |
71 | 77 | |
72 | 78 | if storeKit.purchasedSubscriptions.isEmpty { |
73 | 79 | presentSubscriptionHandler() |
... | ... | @@ -115,7 +121,9 @@ extension RemoveAdvertViewController { |
115 | 121 | } |
116 | 122 | |
117 | 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 | 127 | subcriptionViewController.modalPresentationStyle = .fullScreen |
120 | 128 | subcriptionViewController.modalTransitionStyle = .crossDissolve |
121 | 129 | |
... | ... | @@ -138,19 +146,23 @@ extension RemoveAdvertViewController { |
138 | 146 | } |
139 | 147 | |
140 | 148 | private func turnOnAdBlocker() { |
149 | + ProgressHelper.hide() | |
141 | 150 | mainView.adBlockButton.setImage(.adBlockOnState, for: .normal) |
142 | 151 | mainView.tapActionLabel.textColor = ColorConstants.SearchbarTintBlue |
143 | 152 | mainView.tapActionLabel.text = StringConstants.turnOff |
144 | 153 | |
145 | 154 | CachingManager.shared.adBlockerState = true |
155 | + mainView.adBlockButton.isEnabled = true | |
146 | 156 | } |
147 | 157 | |
148 | 158 | private func turnOffAdBlocker() { |
159 | + ProgressHelper.hide() | |
149 | 160 | mainView.adBlockButton.setImage(.adBlockOffState, for: .normal) |
150 | 161 | mainView.tapActionLabel.textColor = ColorConstants.customPink |
151 | 162 | mainView.tapActionLabel.text = StringConstants.turnOn |
152 | 163 | |
153 | 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 | 25 | override func loadView() { |
26 | 26 | view = mainView |
27 | 27 | } |
28 | - | |
28 | + | |
29 | 29 | override func viewDidLoad() { |
30 | 30 | super.viewDidLoad() |
31 | 31 | |
... | ... | @@ -63,7 +63,7 @@ extension SettingViewController: UITableViewDelegate, UITableViewDataSource { |
63 | 63 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { |
64 | 64 | return 60.0 |
65 | 65 | } |
66 | - | |
66 | + | |
67 | 67 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { |
68 | 68 | let index = indexPath.row |
69 | 69 | cellPresshandler(index) |
... | ... | @@ -101,7 +101,11 @@ extension SettingViewController { |
101 | 101 | case 2: |
102 | 102 | shareButtonPressed() |
103 | 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 | 109 | case 4: |
106 | 110 | setupMessage() |
107 | 111 | case 5: |
... | ... | @@ -118,7 +122,7 @@ extension SettingViewController { |
118 | 122 | } |
119 | 123 | |
120 | 124 | private func shareButtonPressed() { |
121 | - let items = [URL(string: URLConstants.shareAppLink)] | |
125 | + let items = [URL(string: StringConstants.appURL)] | |
122 | 126 | let shareView = UIActivityViewController(activityItems: items as [Any], applicationActivities: nil) |
123 | 127 | |
124 | 128 | present(shareView, animated: true) | ... | ... |
... | ... | @@ -8,19 +8,24 @@ |
8 | 8 | import UIKit |
9 | 9 | import StoreKit |
10 | 10 | |
11 | - | |
12 | 11 | final class SubscriptionViewController: UIViewController { |
13 | 12 | |
14 | - private let mainView = SubscriptionView() | |
13 | + let mainView = SubscriptionView() | |
15 | 14 | |
16 | 15 | private let tableViewData: [String] |
17 | 16 | private let storeKitManager: SubscriptionManager |
18 | 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 | 26 | tableViewData = StringConstants.removeAdvertTableViewData |
22 | 27 | storeKitManager = storeKit |
23 | - successCompletion = complition | |
28 | + successCompletion = completion | |
24 | 29 | |
25 | 30 | super.init(nibName: nil, bundle: nil) |
26 | 31 | } |
... | ... | @@ -33,6 +38,7 @@ final class SubscriptionViewController: UIViewController { |
33 | 38 | super.viewDidLoad() |
34 | 39 | |
35 | 40 | initViewController() |
41 | + updateSubscriptionLabels() | |
36 | 42 | } |
37 | 43 | |
38 | 44 | override func loadView() { |
... | ... | @@ -42,6 +48,20 @@ final class SubscriptionViewController: UIViewController { |
42 | 48 | private func initViewController() { |
43 | 49 | addTargets() |
44 | 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 | 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 | 107 | @MainActor |
79 | 108 | private func buySubscription() async throws { |
109 | + if CachingManager.shared.isSubscriptionActive { | |
110 | + dismiss(animated: true) | |
111 | + successCompletion() | |
112 | + return | |
113 | + } | |
114 | + | |
80 | 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 | 139 | |
98 | 140 | @objc |
99 | 141 | private func buyAdblocker(_ sender: UIButton) { |
142 | + ProgressHelper.show() | |
143 | + sender.isEnabled = false | |
144 | + | |
100 | 145 | Task { |
146 | + defer { | |
147 | + ProgressHelper.hide() | |
148 | + | |
149 | + sender.isEnabled = true | |
150 | + } | |
151 | + | |
101 | 152 | do { |
102 | - try await buySubscription() | |
153 | + try await buySubscription() | |
103 | 154 | } catch { |
104 | 155 | let alert = UIAlertController(title: "Fail!", message: "Error with subscription", preferredStyle: .alert) |
105 | 156 | let okAction = UIAlertAction(title: "OK", style: .default) |
... | ... | @@ -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 | 52 | return obj |
53 | 53 | }() |
54 | 54 | |
55 | - private let priceLabel: UILabel = { | |
55 | + let priceLabel: UILabel = { | |
56 | 56 | let obj = UILabel() |
57 | 57 | obj.text = StringConstants.price |
58 | 58 | obj.font = FontConstants.regularFont_18 |
... | ... | @@ -72,7 +72,7 @@ final class SubscriptionView: GradientView { |
72 | 72 | return obj |
73 | 73 | }() |
74 | 74 | |
75 | - private let freeTrialLabel: UILabel = { | |
75 | + let freeTrialLabel: UILabel = { | |
76 | 76 | let obj = UILabel() |
77 | 77 | obj.textAlignment = .center |
78 | 78 | obj.font = FontConstants.semiboldFont_12 |
... | ... | @@ -81,15 +81,47 @@ final class SubscriptionView: GradientView { |
81 | 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 | 121 | return obj |
91 | 122 | }() |
92 | 123 | |
124 | + | |
93 | 125 | override init (frame: CGRect) { |
94 | 126 | super.init(frame: frame) |
95 | 127 | |
... | ... | @@ -105,7 +137,7 @@ final class SubscriptionView: GradientView { |
105 | 137 | |
106 | 138 | gradientLayer.frame = subscribeButton.bounds |
107 | 139 | } |
108 | - | |
140 | + | |
109 | 141 | |
110 | 142 | private func setup() { |
111 | 143 | addSubview(closeButton) |
... | ... | @@ -116,7 +148,11 @@ final class SubscriptionView: GradientView { |
116 | 148 | addSubview(priceLabel) |
117 | 149 | addSubview(subscribeButton) |
118 | 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 | 157 | setupConstraints() |
122 | 158 | gradientSetup() |
... | ... | @@ -164,11 +200,11 @@ final class SubscriptionView: GradientView { |
164 | 200 | } |
165 | 201 | |
166 | 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 | 204 | make.centerX.equalToSuperview() |
169 | 205 | } |
170 | - | |
171 | - discountLabel.snp.makeConstraints { make in | |
206 | + | |
207 | + buttonsStackView.snp.makeConstraints { make in | |
172 | 208 | make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom).offset(-24.sizeH) |
173 | 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