mirror of
https://github.com/confirmedcode/Lockdown-iOS.git
synced 2025-12-21 12:14:02 +01:00
added new curated lists, some changes in access levels
This commit is contained in:
15
Assets.xcassets/icn_configuration.imageset/Contents.json
vendored
Normal file
15
Assets.xcassets/icn_configuration.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "icn_configuration.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"preserves-vector-representation" : true
|
||||
}
|
||||
}
|
||||
172
Assets.xcassets/icn_configuration.imageset/icn_configuration.pdf
vendored
Normal file
172
Assets.xcassets/icn_configuration.imageset/icn_configuration.pdf
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< >>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<< /Length 3 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 -0.214111 cm
|
||||
0.600000 0.600000 0.600000 scn
|
||||
20.904484 17.394764 m
|
||||
21.368065 16.592863 21.722446 15.759195 21.973381 14.909565 c
|
||||
21.433344 14.598686 20.978598 14.157190 20.651653 13.624325 c
|
||||
20.290869 13.036301 20.099773 12.359935 20.099514 11.670049 c
|
||||
20.099258 10.980165 20.289845 10.303655 20.650192 9.715361 c
|
||||
20.976801 9.182152 21.431324 8.740247 21.971262 8.428954 c
|
||||
21.458757 6.686216 20.538595 5.090506 19.286978 3.773979 c
|
||||
18.747540 4.086189 18.137623 4.259148 17.512524 4.275661 c
|
||||
16.822748 4.293884 16.141378 4.120907 15.543825 3.775871 c
|
||||
14.946270 3.430836 14.455830 2.927195 14.126781 2.320692 c
|
||||
13.828584 1.771051 13.673470 1.156351 13.674195 0.533077 c
|
||||
11.908100 0.107105 10.065874 0.107859 8.300127 0.535276 c
|
||||
8.300602 1.158606 8.145217 1.773291 7.846751 2.322845 c
|
||||
7.517449 2.929176 7.026816 3.432585 6.429144 3.777355 c
|
||||
5.831472 4.122126 5.150065 4.294821 4.460328 4.276327 c
|
||||
3.835356 4.259571 3.225625 4.086439 2.686388 3.774130 c
|
||||
2.063773 4.430382 1.520800 5.158125 1.068913 5.942282 c
|
||||
0.866418 5.825590 l
|
||||
1.068737 5.942587 l
|
||||
0.615622 6.726147 0.256930 7.560382 0.000000 8.427838 c
|
||||
0.539972 8.738712 0.994669 9.180180 1.321584 9.712997 c
|
||||
1.682371 10.301023 1.873464 10.977389 1.873722 11.667274 c
|
||||
1.873980 12.357158 1.683393 13.033669 1.323046 13.621963 c
|
||||
0.996439 14.155172 0.541912 14.597075 0.001975 14.908367 c
|
||||
0.514479 16.651108 1.434644 18.246819 2.686261 19.563347 c
|
||||
3.225698 19.251135 3.835614 19.078176 4.460714 19.061663 c
|
||||
5.150490 19.043438 5.831858 19.216417 6.429413 19.561453 c
|
||||
7.026968 19.906490 7.517408 20.410130 7.846457 21.016634 c
|
||||
8.144655 21.566275 8.299768 22.180973 8.299045 22.804247 c
|
||||
10.065140 23.230219 11.907364 23.229465 13.673112 22.802046 c
|
||||
13.672637 22.178719 13.828022 21.564032 14.126487 21.014477 c
|
||||
14.455789 20.408144 14.946423 19.904739 15.544095 19.559969 c
|
||||
16.141766 19.215199 16.823172 19.042503 17.512909 19.060997 c
|
||||
18.137920 19.077755 18.747690 19.250910 19.286953 19.563255 c
|
||||
19.897404 18.920540 20.441837 18.196901 20.904369 17.394966 c
|
||||
20.904484 17.394764 l
|
||||
h
|
||||
7.363808 5.394186 m
|
||||
7.363998 5.394075 l
|
||||
8.559423 4.704582 9.458236 3.598047 9.888060 2.286676 c
|
||||
9.935762 2.141140 l
|
||||
10.088241 2.126778 l
|
||||
10.685646 2.070509 11.285800 2.069283 11.883828 2.125608 c
|
||||
12.036282 2.139971 l
|
||||
12.083998 2.285475 l
|
||||
12.514101 3.597029 13.413335 4.703590 14.609183 5.392872 c
|
||||
14.609514 5.393064 l
|
||||
15.804481 6.084450 17.212688 6.310163 18.563877 6.026884 c
|
||||
18.713669 5.995481 l
|
||||
18.802338 6.120228 l
|
||||
19.149935 6.609261 19.449434 7.130437 19.698524 7.675325 c
|
||||
19.762119 7.814435 l
|
||||
19.660093 7.928395 l
|
||||
18.739574 8.956595 18.231045 10.288438 18.232035 11.668493 c
|
||||
18.232035 11.668661 l
|
||||
18.232035 13.082383 18.759258 14.402637 19.660101 15.408935 c
|
||||
19.762426 15.523241 l
|
||||
19.698254 15.662592 l
|
||||
19.447437 16.207222 19.146814 16.727501 18.800220 17.216789 c
|
||||
18.711601 17.341892 l
|
||||
18.561550 17.310440 l
|
||||
17.211214 17.027399 15.803920 17.252693 14.609429 17.943138 c
|
||||
14.609241 17.943249 l
|
||||
13.413815 18.632742 12.515003 19.739279 12.085179 21.050650 c
|
||||
12.037477 21.196184 l
|
||||
11.884998 21.210546 l
|
||||
11.287594 21.266815 10.687437 21.268042 10.089409 21.211716 c
|
||||
9.936955 21.197355 l
|
||||
9.889239 21.051851 l
|
||||
9.459136 19.740295 8.559904 18.633734 7.364056 17.944450 c
|
||||
7.363724 17.944260 l
|
||||
6.168757 17.252874 4.760549 17.027161 3.409360 17.310438 c
|
||||
3.259362 17.341885 l
|
||||
3.170729 17.216858 l
|
||||
2.824025 16.727785 2.524039 16.207218 2.274725 15.662024 c
|
||||
2.211105 15.522903 l
|
||||
2.313144 15.408928 l
|
||||
3.233665 14.380727 3.742193 13.048885 3.741202 11.668830 c
|
||||
3.741202 11.668661 l
|
||||
3.741202 10.254938 3.213981 8.934685 2.313138 7.928389 c
|
||||
2.210811 7.814082 l
|
||||
2.274985 7.674731 l
|
||||
2.525801 7.130102 2.826425 6.609823 3.173019 6.120535 c
|
||||
3.261637 5.995432 l
|
||||
3.411688 6.026882 l
|
||||
4.762024 6.309925 6.169318 6.084631 7.363808 5.394186 c
|
||||
h
|
||||
10.986620 8.396538 m
|
||||
10.118798 8.396538 9.286520 8.741278 8.672877 9.354920 c
|
||||
8.059236 9.968562 7.714495 10.800840 7.714495 11.668661 c
|
||||
7.714495 12.536483 8.059236 13.368759 8.672877 13.982402 c
|
||||
9.286520 14.596045 10.118798 14.940784 10.986620 14.940784 c
|
||||
11.854441 14.940784 12.686719 14.596045 13.300361 13.982402 c
|
||||
13.914002 13.368759 14.258743 12.536483 14.258743 11.668661 c
|
||||
14.258743 10.800840 13.914002 9.968562 13.300361 9.354920 c
|
||||
12.686719 8.741278 11.854441 8.396538 10.986620 8.396538 c
|
||||
h
|
||||
10.986620 10.266323 m
|
||||
11.358543 10.266323 11.715232 10.414069 11.978221 10.677058 c
|
||||
12.241210 10.940047 12.388958 11.296738 12.388958 11.668661 c
|
||||
12.388958 12.040586 12.241210 12.397275 11.978221 12.660264 c
|
||||
11.715232 12.923253 11.358543 13.071000 10.986620 13.071000 c
|
||||
10.614696 13.071000 10.258004 12.923253 9.995015 12.660264 c
|
||||
9.732025 12.397274 9.584281 12.040584 9.584281 11.668661 c
|
||||
9.584281 11.296739 9.732025 10.940048 9.995015 10.677058 c
|
||||
10.258004 10.414069 10.614696 10.266323 10.986620 10.266323 c
|
||||
h
|
||||
f*
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
4844
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 21.973389 22.909058 ]
|
||||
/Resources 1 0 R
|
||||
/Contents 2 0 R
|
||||
/Parent 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /Kids [ 4 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Pages 5 0 R
|
||||
/Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000000034 00000 n
|
||||
0000004934 00000 n
|
||||
0000004957 00000 n
|
||||
0000005130 00000 n
|
||||
0000005204 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 6 0 R
|
||||
/Size 7
|
||||
>>
|
||||
startxref
|
||||
5263
|
||||
%%EOF
|
||||
@@ -89,4 +89,3 @@ public extension RawValueCodable where RawValue: Codable {
|
||||
try container.encode(rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -261,6 +261,13 @@
|
||||
40960B0D2A034054000F82EB /* LockdownStorageIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40960B0C2A034054000F82EB /* LockdownStorageIdentifier.swift */; };
|
||||
40960B0E2A034054000F82EB /* LockdownStorageIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40960B0C2A034054000F82EB /* LockdownStorageIdentifier.swift */; };
|
||||
40960B152A034400000F82EB /* Keychainable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40960B142A034400000F82EB /* Keychainable.swift */; };
|
||||
40E7A2F22A0CE8AE00E0231A /* advanced_gaming.txt in Resources */ = {isa = PBXBuildFile; fileRef = 40E7A2EC2A0CE8AE00E0231A /* advanced_gaming.txt */; };
|
||||
40E7A2F82A0CE92900E0231A /* ifunny_trackers.txt in Resources */ = {isa = PBXBuildFile; fileRef = 40E7A2F32A0CE92800E0231A /* ifunny_trackers.txt */; };
|
||||
40E7A2F92A0CE92900E0231A /* junes_journey_trackers.txt in Resources */ = {isa = PBXBuildFile; fileRef = 40E7A2F42A0CE92800E0231A /* junes_journey_trackers.txt */; };
|
||||
40E7A2FA2A0CE92900E0231A /* scams.txt in Resources */ = {isa = PBXBuildFile; fileRef = 40E7A2F52A0CE92800E0231A /* scams.txt */; };
|
||||
40E7A2FB2A0CE92900E0231A /* tiktok_trackers.txt in Resources */ = {isa = PBXBuildFile; fileRef = 40E7A2F62A0CE92800E0231A /* tiktok_trackers.txt */; };
|
||||
40E7A2FC2A0CE92900E0231A /* advanced_analytics.txt in Resources */ = {isa = PBXBuildFile; fileRef = 40E7A2F72A0CE92900E0231A /* advanced_analytics.txt */; };
|
||||
40E7A3012A0E1C7A00E0231A /* SplashscreenViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40E7A3002A0E1C7A00E0231A /* SplashscreenViewController.swift */; };
|
||||
40FC414329F74C7900BD7396 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40FC414229F74C7900BD7396 /* String+Extensions.swift */; };
|
||||
4A86219093026DE70A097E79 /* Pods-LockdownTests-metadata.plist in Resources */ = {isa = PBXBuildFile; fileRef = 8DA68459884385F76BF86234 /* Pods-LockdownTests-metadata.plist */; };
|
||||
54F0B1A0273200B0002F3630 /* FirewallController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCA4F4022F252720017740D /* FirewallController.swift */; };
|
||||
@@ -711,6 +718,13 @@
|
||||
40960B092A03400E000F82EB /* UserDefault.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefault.swift; sourceTree = "<group>"; };
|
||||
40960B0C2A034054000F82EB /* LockdownStorageIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockdownStorageIdentifier.swift; sourceTree = "<group>"; };
|
||||
40960B142A034400000F82EB /* Keychainable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keychainable.swift; sourceTree = "<group>"; };
|
||||
40E7A2EC2A0CE8AE00E0231A /* advanced_gaming.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = advanced_gaming.txt; sourceTree = "<group>"; };
|
||||
40E7A2F32A0CE92800E0231A /* ifunny_trackers.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ifunny_trackers.txt; sourceTree = "<group>"; };
|
||||
40E7A2F42A0CE92800E0231A /* junes_journey_trackers.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = junes_journey_trackers.txt; sourceTree = "<group>"; };
|
||||
40E7A2F52A0CE92800E0231A /* scams.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = scams.txt; sourceTree = "<group>"; };
|
||||
40E7A2F62A0CE92800E0231A /* tiktok_trackers.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tiktok_trackers.txt; sourceTree = "<group>"; };
|
||||
40E7A2F72A0CE92900E0231A /* advanced_analytics.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = advanced_analytics.txt; sourceTree = "<group>"; };
|
||||
40E7A3002A0E1C7A00E0231A /* SplashscreenViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashscreenViewController.swift; sourceTree = "<group>"; };
|
||||
40FC414229F74C7900BD7396 /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = "<group>"; };
|
||||
4CA426CE326B009F3E4493D1 /* Pods_Lockdown.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Lockdown.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
50F9BE503587CE4933CB7983 /* Pods-Lockdown-settings-metadata.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "Pods-Lockdown-settings-metadata.plist"; path = "Settings.bundle/Pods-Lockdown-settings-metadata.plist"; sourceTree = "<group>"; };
|
||||
@@ -977,6 +991,12 @@
|
||||
3D0971D522EBAAEE00CCD326 /* Domains */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
40E7A2F72A0CE92900E0231A /* advanced_analytics.txt */,
|
||||
40E7A2F32A0CE92800E0231A /* ifunny_trackers.txt */,
|
||||
40E7A2F42A0CE92800E0231A /* junes_journey_trackers.txt */,
|
||||
40E7A2F52A0CE92800E0231A /* scams.txt */,
|
||||
40E7A2F62A0CE92800E0231A /* tiktok_trackers.txt */,
|
||||
40E7A2EC2A0CE8AE00E0231A /* advanced_gaming.txt */,
|
||||
3DD545DA2808C2F6005E140C /* 5000_dummy_list.txt */,
|
||||
3DAA6B4E22EA76420018FC09 /* clickbait.txt */,
|
||||
3D5F5A0723107C1E004C3860 /* game_ads.txt */,
|
||||
@@ -1512,6 +1532,30 @@
|
||||
name = Protocols;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
40E7A2FD2A0E1C3200E0231A /* Presentation */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
40E7A2FE2A0E1C4500E0231A /* Splashscreen */,
|
||||
);
|
||||
name = Presentation;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
40E7A2FE2A0E1C4500E0231A /* Splashscreen */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
40E7A2FF2A0E1C5600E0231A /* ViewController */,
|
||||
);
|
||||
name = Splashscreen;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
40E7A2FF2A0E1C5600E0231A /* ViewController */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
40E7A3002A0E1C7A00E0231A /* SplashscreenViewController.swift */,
|
||||
);
|
||||
name = ViewController;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7C0D11102473EDFD00A26E04 /* Services */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1650,6 +1694,7 @@
|
||||
A1141A131F46230500F54698 /* LockdowniOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
40E7A2FD2A0E1C3200E0231A /* Presentation */,
|
||||
40960B042A033EE8000F82EB /* Core */,
|
||||
40960AF92A033E2E000F82EB /* Business Logic */,
|
||||
402D24CE29D87EF300A5AB60 /* Scenes */,
|
||||
@@ -2245,6 +2290,7 @@
|
||||
A1D85F0B207C562F00B766E0 /* adBlockListThree.json in Resources */,
|
||||
A1159FCC207C228300DA4670 /* privacyBlockList.json in Resources */,
|
||||
A1159FCD207C228300DA4670 /* socialBlockList.json in Resources */,
|
||||
40E7A2F22A0CE8AE00E0231A /* advanced_gaming.txt in Resources */,
|
||||
A1FCDA8722CDE8C000C928BC /* crypto_mining_ips.txt in Resources */,
|
||||
3D752C342357FA3B00C163E4 /* SF-Pro-Rounded-Regular.otf in Resources */,
|
||||
A1159FCE207C228300DA4670 /* adBlockList.json in Resources */,
|
||||
@@ -2254,6 +2300,7 @@
|
||||
3D44378422DFB22600908CDC /* Montserrat-SemiBold.ttf in Resources */,
|
||||
3D01D97B2480DCB3003A710C /* data_trackers.txt in Resources */,
|
||||
3D44378022DFB22600908CDC /* Montserrat-Medium.ttf in Resources */,
|
||||
40E7A2F82A0CE92900E0231A /* ifunny_trackers.txt in Resources */,
|
||||
A15F3C751F79DC8F00B07F03 /* LaunchScreen.storyboard in Resources */,
|
||||
3DD545DB2808C2F6005E140C /* 5000_dummy_list.txt in Resources */,
|
||||
A1FCDA8522CDE60800C928BC /* crypto_mining.txt in Resources */,
|
||||
@@ -2268,8 +2315,10 @@
|
||||
3D752C362357FA3B00C163E4 /* SF-Pro-Rounded-Bold.otf in Resources */,
|
||||
3D44378222DFB22600908CDC /* Montserrat-Thin.ttf in Resources */,
|
||||
A1FCDA8A22D3BA1900C928BC /* facebook_inc_ips.txt in Resources */,
|
||||
40E7A2F92A0CE92900E0231A /* junes_journey_trackers.txt in Resources */,
|
||||
3DAA6B4F22EA76420018FC09 /* clickbait.txt in Resources */,
|
||||
A1FCDA8D22D3C50A00C928BC /* email_opens.txt in Resources */,
|
||||
40E7A2FB2A0CE92900E0231A /* tiktok_trackers.txt in Resources */,
|
||||
A1141A1C1F46230500F54698 /* Assets.xcassets in Resources */,
|
||||
3D44378322DFB22600908CDC /* Montserrat-Bold.ttf in Resources */,
|
||||
A1FCDA9122D3D52C00C928BC /* facebook_inc_ipv6.txt in Resources */,
|
||||
@@ -2282,6 +2331,8 @@
|
||||
3D40826327F675F6004C146B /* dnscrypt-proxy.toml in Resources */,
|
||||
3D5464D323037CCA00AE1F73 /* Settings.bundle in Resources */,
|
||||
20816D1FD569053C0994232B /* Pods-Lockdown-metadata.plist in Resources */,
|
||||
40E7A2FC2A0CE92900E0231A /* advanced_analytics.txt in Resources */,
|
||||
40E7A2FA2A0CE92900E0231A /* scams.txt in Resources */,
|
||||
C9E66BB880A29A48D055FBFF /* Pods-Lockdown-settings-metadata.plist in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -2683,6 +2734,7 @@
|
||||
A154A07E215C78180010FFCC /* BlockListCell.swift in Sources */,
|
||||
3D47CDCE22F3C3F3003BD7F7 /* NVActivityIndicatorAnimationBallScaleRippleMultiple.swift in Sources */,
|
||||
40FC414329F74C7900BD7396 /* String+Extensions.swift in Sources */,
|
||||
40E7A3012A0E1C7A00E0231A /* SplashscreenViewController.swift in Sources */,
|
||||
3D47CDCC22F3C3F3003BD7F7 /* NVActivityIndicatorAnimationBallScaleMultiple.swift in Sources */,
|
||||
A1EBEADC2097AE6E002B9087 /* DefaultValues.swift in Sources */,
|
||||
A1EBEAD02097AE6E002B9087 /* M13CheckboxController.swift in Sources */,
|
||||
@@ -2921,7 +2973,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 14;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = V8J3Z26F6Z;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -2958,7 +3010,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 14;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = V8J3Z26F6Z;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -3051,7 +3103,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 14;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = V8J3Z26F6Z;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -3089,7 +3141,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 14;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = V8J3Z26F6Z;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -3240,7 +3292,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 14;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = V8J3Z26F6Z;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
@@ -3280,7 +3332,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 14;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = V8J3Z26F6Z;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
@@ -3326,7 +3378,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 14;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = V8J3Z26F6Z;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -3369,7 +3421,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 14;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = V8J3Z26F6Z;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -3405,7 +3457,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 14;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = V8J3Z26F6Z;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = "Lockdown Blocker/Info.plist";
|
||||
@@ -3435,7 +3487,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 14;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = V8J3Z26F6Z;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = "Lockdown Blocker/Info.plist";
|
||||
@@ -3467,7 +3519,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 14;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = V8J3Z26F6Z;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -3524,7 +3576,7 @@
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 14;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = V8J3Z26F6Z;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
||||
@@ -95,9 +95,9 @@ final class AdvancedPaywallView: UIView {
|
||||
imageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
button.addSubview(imageView)
|
||||
NSLayoutConstraint.activate([
|
||||
imageView.trailingAnchor.constraint(equalTo: button.trailingAnchor, constant: 0),
|
||||
imageView.topAnchor.constraint(equalTo: button.topAnchor, constant: 0)
|
||||
])
|
||||
imageView.trailingAnchor.constraint(equalTo: button.trailingAnchor, constant: 0),
|
||||
imageView.topAnchor.constraint(equalTo: button.topAnchor, constant: 0)
|
||||
])
|
||||
|
||||
let titleLabel = UILabel()
|
||||
titleLabel.text = NSLocalizedString("7-Day FREE TRIAL", comment: "")
|
||||
@@ -110,7 +110,7 @@ final class AdvancedPaywallView: UIView {
|
||||
|
||||
let descriptionLabel = UILabel()
|
||||
descriptionLabel.font = fontMedium11
|
||||
descriptionLabel.text = "then $35.99 per year"
|
||||
descriptionLabel.text = "then \(VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdAdvancedYearly)) per year"
|
||||
descriptionLabel.textColor = .white
|
||||
descriptionLabel.textAlignment = .left
|
||||
button.addSubview(descriptionLabel)
|
||||
@@ -118,13 +118,13 @@ final class AdvancedPaywallView: UIView {
|
||||
descriptionLabel.anchors.leading.pin(inset: 24)
|
||||
|
||||
let descriptionLabel2 = UILabel()
|
||||
descriptionLabel2.text = "only $3 per month"
|
||||
descriptionLabel2.text = "only $2.49 per month"
|
||||
descriptionLabel2.font = fontMedium11
|
||||
descriptionLabel2.textColor = .white
|
||||
button.addSubview(descriptionLabel2)
|
||||
descriptionLabel2.anchors.top.spacing(14, to: imageView.anchors.bottom)
|
||||
descriptionLabel2.anchors.trailing.pin(inset: 24)
|
||||
|
||||
|
||||
|
||||
button.anchors.height.equal(66)
|
||||
button.addTarget(self, action: #selector(buyButton1Clicked), for: .touchUpInside)
|
||||
@@ -147,7 +147,7 @@ final class AdvancedPaywallView: UIView {
|
||||
|
||||
let descriptionLabel = UILabel()
|
||||
descriptionLabel.font = fontMedium11
|
||||
descriptionLabel.text = "$4.99/month"
|
||||
descriptionLabel.text = "\(VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdAdvancedMonthly))/month"
|
||||
descriptionLabel.textColor = .white
|
||||
descriptionLabel.textAlignment = .left
|
||||
|
||||
|
||||
@@ -123,9 +123,9 @@ final class AnonymousPaywallView: UIView {
|
||||
titleLabel.anchors.top.pin(inset: 16)
|
||||
titleLabel.anchors.leading.pin(inset: 24)
|
||||
|
||||
let descriptionLabel = UILabel()
|
||||
var descriptionLabel = UILabel()
|
||||
descriptionLabel.font = fontMedium11
|
||||
descriptionLabel.text = "then $49.99 per year"
|
||||
descriptionLabel.text = "then \(VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdAnnual)) per year"
|
||||
descriptionLabel.textColor = .white
|
||||
descriptionLabel.textAlignment = .left
|
||||
descriptionLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
@@ -134,7 +134,7 @@ final class AnonymousPaywallView: UIView {
|
||||
descriptionLabel.anchors.leading.pin(inset: 24)
|
||||
|
||||
let descriptionLabel2 = UILabel()
|
||||
descriptionLabel2.text = "only $4.17 per month"
|
||||
descriptionLabel2.text = "only $4.99 per month"
|
||||
descriptionLabel2.font = fontMedium11
|
||||
descriptionLabel2.textColor = .white
|
||||
button.addSubview(descriptionLabel2)
|
||||
@@ -146,6 +146,33 @@ final class AnonymousPaywallView: UIView {
|
||||
return button
|
||||
}()
|
||||
|
||||
lazy var button1TitleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.text = NSLocalizedString("7-Day FREE TRIAL", comment: "")
|
||||
label.font = fontBold15
|
||||
label.textColor = .white
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
buyButton1.addSubview(button1TitleLabel)
|
||||
label.anchors.top.pin(inset: 16)
|
||||
label.anchors.leading.pin(inset: 24)
|
||||
return label
|
||||
}()
|
||||
|
||||
lazy var button1DescriptionLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = fontMedium11
|
||||
label.text = "then \(VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdAnnual)) per year"
|
||||
label.textColor = .white
|
||||
label.textAlignment = .left
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
buyButton1.addSubview(button1DescriptionLabel)
|
||||
label.anchors.top.spacing(4, to: button1TitleLabel.anchors.bottom)
|
||||
label.anchors.leading.pin(inset: 24)
|
||||
|
||||
return label
|
||||
}()
|
||||
|
||||
|
||||
lazy var buyButton2: UIButton = {
|
||||
let button = UIButton(type: .system)
|
||||
button.tintColor = .white
|
||||
@@ -162,7 +189,7 @@ final class AnonymousPaywallView: UIView {
|
||||
|
||||
let descriptionLabel = UILabel()
|
||||
descriptionLabel.font = fontMedium11
|
||||
descriptionLabel.text = "$4.99/month"
|
||||
descriptionLabel.text = "\(VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdMonthly))/month"
|
||||
descriptionLabel.textColor = .white
|
||||
descriptionLabel.textAlignment = .left
|
||||
|
||||
|
||||
@@ -60,7 +60,45 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
connectivityService.startObservingConnectivity()
|
||||
|
||||
// Content Blocker
|
||||
SFContentBlockerManager.reloadContentBlocker(withIdentifier: LockdownStorageIdentifier.contentBlockerId) { error in
|
||||
if error != nil {
|
||||
DDLogError("Error loading Content Blocker: \(String(describing: error))")
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare IAP
|
||||
|
||||
SwiftyStoreKit.completeTransactions(atomically: true) { purchases in
|
||||
for purchase in purchases {
|
||||
DDLogInfo("LAUNCH: Processing Purchase\n\(purchase)")
|
||||
if purchase.transaction.transactionState == .purchased || purchase.transaction.transactionState == .restored {
|
||||
if purchase.needsFinishTransaction {
|
||||
DDLogInfo("Finishing transaction for purchase: \(purchase)")
|
||||
SwiftyStoreKit.finishTransaction(purchase.transaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VPNSubscription.cacheLocalizedPrices()
|
||||
|
||||
BaseUserService.shared.updateUserSubscription{ subscription in
|
||||
if subscription?.planType == .monthly || subscription?.planType == .annual {
|
||||
UserDefaults.hasSeenAdvancedPaywall = false
|
||||
UserDefaults.hasSeenUniversalPaywall = false
|
||||
UserDefaults.hasSeenAnonymousPaywall = true
|
||||
}
|
||||
else if subscription?.planType == .proMonthly || subscription?.planType == .proAnnual {
|
||||
UserDefaults.hasSeenAnonymousPaywall = false
|
||||
UserDefaults.hasSeenAdvancedPaywall = false
|
||||
UserDefaults.hasSeenUniversalPaywall = true
|
||||
} else {
|
||||
UserDefaults.hasSeenAnonymousPaywall = false
|
||||
UserDefaults.hasSeenAdvancedPaywall = false
|
||||
UserDefaults.hasSeenUniversalPaywall = false
|
||||
}
|
||||
}
|
||||
|
||||
// Set up PopupDialog
|
||||
let dialogAppearance = PopupDialogDefaultView.appearance()
|
||||
@@ -110,12 +148,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
}
|
||||
cancelButtonAppearance.titleFont = fontSemiBold17
|
||||
cancelButtonAppearance.titleColor = UIColor.lightGray
|
||||
|
||||
// Lockdown default lists
|
||||
setupFirewallDefaultBlockLists()
|
||||
|
||||
// Whitelist default domains
|
||||
setupLockdownWhitelistedDomains()
|
||||
|
||||
// Show indicator at top when internet not reachable
|
||||
reachability?.whenReachable = { reachability in
|
||||
@@ -138,27 +170,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
DDLogError("Unable to start reachability notifier")
|
||||
}
|
||||
|
||||
// Content Blocker
|
||||
SFContentBlockerManager.reloadContentBlocker( withIdentifier: "com.confirmed.lockdown.Confirmed-Blocker") { (_ error: Error?) -> Void in
|
||||
if error != nil {
|
||||
DDLogError("Error loading Content Blocker: \(String(describing: error))")
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare IAP
|
||||
VPNSubscription.cacheLocalizedPrices()
|
||||
SwiftyStoreKit.completeTransactions(atomically: true) { purchases in
|
||||
for purchase in purchases {
|
||||
DDLogInfo("LAUNCH: Processing Purchase\n\(purchase)");
|
||||
if purchase.transaction.transactionState == .purchased || purchase.transaction.transactionState == .restored {
|
||||
if purchase.needsFinishTransaction {
|
||||
DDLogInfo("Finishing transaction for purchase: \(purchase)")
|
||||
SwiftyStoreKit.finishTransaction(purchase.transaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Periodically check if the firewall is functioning correctly - every 2.5 hours
|
||||
if #available(iOS 13.0, *) {
|
||||
DDLogInfo("BGTask: Registering BGTask id \(FirewallRepair.identifier)")
|
||||
@@ -423,14 +434,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
}
|
||||
|
||||
else if (host == "toggleFirewall") {
|
||||
if let home = self.getCurrentViewController() as? HomeViewController {
|
||||
home.toggleFirewall(self)
|
||||
if let home = self.getCurrentViewController() as? LDFirewallViewController {
|
||||
home.toggleFirewall()
|
||||
}
|
||||
}
|
||||
|
||||
else if (host == "toggleVPN") {
|
||||
if let home = self.getCurrentViewController() as? HomeViewController {
|
||||
home.toggleVPN(self)
|
||||
if let home = self.getCurrentViewController() as? LDVpnViewController {
|
||||
home.toggleVPN()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1068,7 +1068,7 @@
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" tag="2" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="A simple, powerful firewall that stops connections to trackers, malware and other bad agents.
Free and open source." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="6Qj-yK-k5A">
|
||||
<rect key="frame" x="24" y="211.5" width="327" height="128.5"/>
|
||||
<rect key="frame" x="24" y="211.5" width="327" height="161"/>
|
||||
<fontDescription key="fontDescription" name="Montserrat-Regular" family="Montserrat" pointSize="22"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
@@ -1098,7 +1098,7 @@
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="h6y-cc-pyT">
|
||||
<rect key="frame" x="107.5" y="602" width="160" height="31"/>
|
||||
<rect key="frame" x="95.5" y="602" width="184" height="32"/>
|
||||
<fontDescription key="fontDescription" name="Montserrat-SemiBold" family="Montserrat" pointSize="16"/>
|
||||
<state key="normal" title="Why Trust Lockdown?">
|
||||
<color key="titleColor" red="0.0" green="0.67843137249999996" blue="0.90588235289999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
@@ -1187,7 +1187,7 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="50"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Blocking Enabled" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Kd7-nB-tAb">
|
||||
<rect key="frame" x="20" y="6.5" width="125.5" height="30"/>
|
||||
<rect key="frame" x="20" y="6.5" width="144" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="ZgL-en-Q3V"/>
|
||||
</constraints>
|
||||
@@ -1351,7 +1351,7 @@
|
||||
<rect key="frame" x="344" y="0.0" width="31" height="73"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<label opaque="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="iOS Monthly" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xt8-uP-JgS">
|
||||
<label opaque="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Anonymous Monthly" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xt8-uP-JgS">
|
||||
<rect key="frame" x="73.5" y="7" width="293.5" height="38.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="38.5" id="9jN-wn-44u"/>
|
||||
@@ -1453,7 +1453,7 @@
|
||||
<action selector="annualTapped:" destination="uhi-Bj-03J" eventType="valueChanged" id="Lkt-A8-pnc"/>
|
||||
</connections>
|
||||
</view>
|
||||
<label opaque="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="iOS Annual (Save ~50%)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5Ce-KH-z1j">
|
||||
<label opaque="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Anonymous Annual (Save ~50%)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5Ce-KH-z1j">
|
||||
<rect key="frame" x="73.5" y="7" width="293.5" height="38.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="38.5" id="evj-cu-zx7"/>
|
||||
@@ -1490,7 +1490,7 @@
|
||||
<rect key="frame" x="344" y="0.0" width="31" height="72.5"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<label opaque="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Pro Monthly" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="c6Y-nW-xhv">
|
||||
<label opaque="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Universal Monthly" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="c6Y-nW-xhv">
|
||||
<rect key="frame" x="73.5" y="7" width="293.5" height="38.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="38.5" id="PoX-VC-lK0"/>
|
||||
@@ -1592,7 +1592,7 @@
|
||||
<action selector="annualProTapped:" destination="uhi-Bj-03J" eventType="valueChanged" id="G8D-3e-zKC"/>
|
||||
</connections>
|
||||
</view>
|
||||
<label opaque="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Pro Annual (Save ~30%)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ASZ-so-4BJ">
|
||||
<label opaque="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Universal Annual (Save ~30%)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ASZ-so-4BJ">
|
||||
<rect key="frame" x="73.5" y="7.5" width="293.5" height="38.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="38.5" id="TS3-2d-dVZ"/>
|
||||
@@ -3034,7 +3034,7 @@
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Email Address" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="wPU-g5-s3s">
|
||||
<rect key="frame" x="37.5" y="175" width="300.5" height="34"/>
|
||||
<rect key="frame" x="33" y="176" width="309" height="34"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" relation="lessThanOrEqual" constant="400" id="hHY-9d-5Uw"/>
|
||||
</constraints>
|
||||
@@ -3042,13 +3042,13 @@
|
||||
<textInputTraits key="textInputTraits" keyboardType="emailAddress" returnKeyType="next" enablesReturnKeyAutomatically="YES" textContentType="username"/>
|
||||
</textField>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Email" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jMa-F3-KUG">
|
||||
<rect key="frame" x="34" y="158" width="29.5" height="14"/>
|
||||
<rect key="frame" x="29.5" y="158" width="34.5" height="15"/>
|
||||
<fontDescription key="fontDescription" name="Montserrat-Regular" family="Montserrat" pointSize="12"/>
|
||||
<color key="textColor" systemColor="secondaryLabelColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Password" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="f3K-Kz-eVg">
|
||||
<rect key="frame" x="37.5" y="234" width="300.5" height="34"/>
|
||||
<rect key="frame" x="33" y="236" width="309" height="34"/>
|
||||
<fontDescription key="fontDescription" name="Montserrat-Regular" family="Montserrat" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" returnKeyType="go" enablesReturnKeyAutomatically="YES" secureTextEntry="YES" textContentType="password"/>
|
||||
<connections>
|
||||
@@ -3056,7 +3056,7 @@
|
||||
</connections>
|
||||
</textField>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Password" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="W3y-bX-UkA">
|
||||
<rect key="frame" x="34" y="217" width="53.5" height="14"/>
|
||||
<rect key="frame" x="29.5" y="218" width="58" height="15"/>
|
||||
<fontDescription key="fontDescription" name="Montserrat-Regular" family="Montserrat" pointSize="12"/>
|
||||
<color key="textColor" systemColor="secondaryLabelColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@@ -3071,7 +3071,7 @@
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gJW-8m-Vk5">
|
||||
<rect key="frame" x="37.5" y="274" width="300.5" height="38.5"/>
|
||||
<rect key="frame" x="33" y="276" width="309" height="40.5"/>
|
||||
<string key="text">Password must be at least 8 characters, contain at least one uppercase letter, one lowercase letter, one number, and one symbol.</string>
|
||||
<fontDescription key="fontDescription" name="Montserrat-Regular" family="Montserrat" pointSize="11"/>
|
||||
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
@@ -3209,7 +3209,7 @@
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Email Address" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="KMj-n0-VnV">
|
||||
<rect key="frame" x="24" y="147" width="327" height="34"/>
|
||||
<rect key="frame" x="24" y="148" width="327" height="34"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" priority="750" constant="400" id="Y17-UK-EsH"/>
|
||||
</constraints>
|
||||
@@ -3217,18 +3217,18 @@
|
||||
<textInputTraits key="textInputTraits" keyboardType="emailAddress" returnKeyType="done" enablesReturnKeyAutomatically="YES" textContentType="username"/>
|
||||
</textField>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Email" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="asx-fS-ufQ">
|
||||
<rect key="frame" x="24" y="130" width="29.5" height="14"/>
|
||||
<rect key="frame" x="24" y="130" width="34.5" height="15"/>
|
||||
<fontDescription key="fontDescription" name="Montserrat-Regular" family="Montserrat" pointSize="12"/>
|
||||
<color key="textColor" systemColor="secondaryLabelColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Password" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="0XQ-Qd-SAy">
|
||||
<rect key="frame" x="24" y="206" width="327" height="34"/>
|
||||
<rect key="frame" x="24" y="208" width="327" height="34"/>
|
||||
<fontDescription key="fontDescription" name="Montserrat-Regular" family="Montserrat" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" returnKeyType="done" enablesReturnKeyAutomatically="YES" secureTextEntry="YES" textContentType="password"/>
|
||||
</textField>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Password" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rCb-D1-AbS">
|
||||
<rect key="frame" x="24" y="189" width="53.5" height="14"/>
|
||||
<rect key="frame" x="24" y="190" width="58" height="15"/>
|
||||
<fontDescription key="fontDescription" name="Montserrat-Regular" family="Montserrat" pointSize="12"/>
|
||||
<color key="textColor" systemColor="secondaryLabelColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@@ -3361,7 +3361,7 @@
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Email Address" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="pXd-nf-bzR">
|
||||
<rect key="frame" x="24" y="155" width="327" height="34"/>
|
||||
<rect key="frame" x="24" y="156" width="327" height="34"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" priority="750" constant="400" id="aqM-gh-6bG"/>
|
||||
</constraints>
|
||||
@@ -3369,7 +3369,7 @@
|
||||
<textInputTraits key="textInputTraits" keyboardType="emailAddress" returnKeyType="done" enablesReturnKeyAutomatically="YES" textContentType="email"/>
|
||||
</textField>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Email" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="syJ-Jd-iUo">
|
||||
<rect key="frame" x="24" y="138" width="29.5" height="14"/>
|
||||
<rect key="frame" x="24" y="138" width="34.5" height="15"/>
|
||||
<fontDescription key="fontDescription" name="Montserrat-Regular" family="Montserrat" pointSize="12"/>
|
||||
<color key="textColor" systemColor="secondaryLabelColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@@ -3471,7 +3471,7 @@
|
||||
<!--Main Tab Bar Controller-->
|
||||
<scene sceneID="Lob-gK-5lR">
|
||||
<objects>
|
||||
<tabBarController automaticallyAdjustsScrollViewInsets="NO" id="yjd-Jn-wK5" customClass="MainTabBarController" customModule="Lockdown" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tabBarController storyboardIdentifier="MainTabBarController" automaticallyAdjustsScrollViewInsets="NO" id="yjd-Jn-wK5" customClass="MainTabBarController" customModule="Lockdown" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<toolbarItems/>
|
||||
<tabBar key="tabBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="ZaO-Uc-o9X">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1000" height="1000"/>
|
||||
@@ -3558,7 +3558,7 @@
|
||||
<scene sceneID="Ukn-8j-czd">
|
||||
<objects>
|
||||
<navigationController id="iEl-zS-nFt" sceneMemberID="viewController">
|
||||
<tabBarItem key="tabBarItem" title="Configuration" image="gearshape" catalog="system" id="zu3-Y2-tf2"/>
|
||||
<tabBarItem key="tabBarItem" title="Configuration" image="icn_configuration" id="zu3-Y2-tf2"/>
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="yvf-h3-UiG">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
@@ -3679,8 +3679,8 @@
|
||||
<resources>
|
||||
<image name="blue_circle" width="156" height="156"/>
|
||||
<image name="book" catalog="system" width="128" height="99"/>
|
||||
<image name="gearshape" catalog="system" width="128" height="123"/>
|
||||
<image name="globe" width="120" height="120"/>
|
||||
<image name="icn_configuration" width="22" height="23"/>
|
||||
<image name="icn_firewall" width="19" height="22"/>
|
||||
<image name="icn_vpn" width="22" height="22"/>
|
||||
<image name="lock.shield.fill" catalog="system" width="128" height="119"/>
|
||||
|
||||
@@ -81,7 +81,6 @@ final class BlockListViewController: BaseViewController {
|
||||
button.tintColor = .tunnelsBlue
|
||||
button.setImage(UIImage(systemName: "plus", withConfiguration: symbolConfig), for: .normal)
|
||||
button.addTarget(self, action: #selector(showSubmenu), for: .touchUpInside)
|
||||
button.isEnabled = UserDefaults.hasSeenAdvancedPaywall ? true : false
|
||||
return button
|
||||
}()
|
||||
|
||||
@@ -129,7 +128,6 @@ final class BlockListViewController: BaseViewController {
|
||||
button.tintColor = .tunnelsBlue
|
||||
button.setImage(UIImage(named: "icn_edit"), for: .normal)
|
||||
button.addTarget(self, action: #selector(editDomains), for: .touchUpInside)
|
||||
button.isHidden = true
|
||||
return button
|
||||
}()
|
||||
|
||||
@@ -150,6 +148,12 @@ final class BlockListViewController: BaseViewController {
|
||||
tap.cancelsTouchesInView = false
|
||||
view.addGestureRecognizer(tap)
|
||||
|
||||
if UserDefaults.hasSeenAdvancedPaywall || UserDefaults.hasSeenAnonymousPaywall || UserDefaults.hasSeenUniversalPaywall {
|
||||
editDomainButton.isEnabled = true
|
||||
} else {
|
||||
editDomainButton.isEnabled = false
|
||||
}
|
||||
|
||||
configure()
|
||||
configureCuratedBlockedDomainsTableView()
|
||||
configureCustomBlockedListsTableView()
|
||||
@@ -372,7 +376,8 @@ extension BlockListViewController {
|
||||
let emptyList = emptyListsView
|
||||
let lockedList = lockedListsView
|
||||
|
||||
if UserDefaults.hasSeenAdvancedPaywall {
|
||||
if UserDefaults.hasSeenAdvancedPaywall || UserDefaults.hasSeenAnonymousPaywall || UserDefaults.hasSeenUniversalPaywall {
|
||||
addNewListButton.isEnabled = true
|
||||
if customBlockedLists.count == 0 {
|
||||
tableView.addRow { (contentView) in
|
||||
contentView.addSubview(emptyList)
|
||||
|
||||
@@ -11,15 +11,6 @@ class BlockLogViewController: BaseViewController, UITableViewDelegate, UITableVi
|
||||
|
||||
@IBOutlet var blockDayCounterLabel: UILabel!
|
||||
|
||||
// lazy var blockDayCounterLabel: UILabel = {
|
||||
// let label = UILabel()
|
||||
// label.text = "233"
|
||||
// label.textColor = .label
|
||||
// label.font = fontRegular14
|
||||
// label.textAlignment = .center
|
||||
// return label
|
||||
// }()
|
||||
|
||||
// -- SUPPORTING LIVE UPDATES
|
||||
var timer: Timer?
|
||||
var kvoObservationToken: Any?
|
||||
@@ -43,7 +34,9 @@ class BlockLogViewController: BaseViewController, UITableViewDelegate, UITableVi
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "blockLogCell", for: indexPath) as! BlockLogCell
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: "blockLogCell", for: indexPath) as? BlockLogCell else {
|
||||
return UITableViewCell()
|
||||
}
|
||||
|
||||
cell.time.text = dayLogTime[indexPath.row];
|
||||
cell.logHost?.text = dayLogHost[indexPath.row];
|
||||
@@ -138,30 +131,40 @@ class BlockLogViewController: BaseViewController, UITableViewDelegate, UITableVi
|
||||
@IBAction func showMenu() {
|
||||
let isBlockEnabled = BlockDayLog.shared.isEnabled
|
||||
|
||||
showPopupDialog(title: NSLocalizedString("Settings", comment: ""), message: NSLocalizedString("The block log can be manually cleared or disabled. Disabling the Block Log only disables the log of connections - the number of tracking attempts will still be displayed.", comment: ""), buttons: [
|
||||
.custom(title: isBlockEnabled ? NSLocalizedString("Disable Block Log" , comment: "") : NSLocalizedString("Enable Block Log", comment: ""), completion: {
|
||||
if isBlockEnabled {
|
||||
self.showDisableBlockLog()
|
||||
} else {
|
||||
self.enableBlockLog()
|
||||
}
|
||||
}),
|
||||
.custom(title: NSLocalizedString("Clear Block Log", comment: ""), completion: {
|
||||
BlockDayLog.shared.clear()
|
||||
defaults.set(0, forKey: kDayMetrics)
|
||||
self.refreshData(self)
|
||||
}),
|
||||
.cancel()
|
||||
let message = """
|
||||
The block log can be manually cleared or disabled. Disabling the Block Log only disables the log of connections - \
|
||||
the number of tracking attempts will still be displayed.
|
||||
"""
|
||||
showPopupDialog(
|
||||
title: .localized("Settings"),
|
||||
message: .localized(message),
|
||||
buttons: [
|
||||
.custom(title: isBlockEnabled ? .localized("Disable Block Log") : .localized("Enable Block Log")) {
|
||||
if isBlockEnabled {
|
||||
self.showDisableBlockLog()
|
||||
} else {
|
||||
self.enableBlockLog()
|
||||
}
|
||||
},
|
||||
.custom(title: .localized("Clear Block Log")) {
|
||||
BlockDayLog.shared.clear()
|
||||
defaults.set(0, forKey: kDayMetrics)
|
||||
self.refreshData(self)
|
||||
},
|
||||
.cancel()
|
||||
])
|
||||
}
|
||||
|
||||
func showDisableBlockLog() {
|
||||
showPopupDialog(title: NSLocalizedString("Disable Block Log?", comment: ""), message: NSLocalizedString("You'll have to reenable it later here to start seeing blocked entries again.", comment: ""), buttons: [
|
||||
.destructive(title: NSLocalizedString("Disable", comment: ""), completion: {
|
||||
BlockDayLog.shared.disable(shouldClear: true)
|
||||
self.refreshData(self)
|
||||
}),
|
||||
.preferredCancel()
|
||||
showPopupDialog(
|
||||
title: .localized("Disable Block Log?"),
|
||||
message: .localized("You'll have to reenable it later here to start seeing blocked entries again."),
|
||||
buttons: [
|
||||
.destructive(title: .localized("Disable")) {
|
||||
BlockDayLog.shared.disable(shouldClear: true)
|
||||
self.refreshData(self)
|
||||
},
|
||||
.preferredCancel()
|
||||
])
|
||||
}
|
||||
|
||||
|
||||
@@ -48,8 +48,8 @@ final class FirewallPaywallViewController: BaseViewController, Loadable {
|
||||
private lazy var annualPlan: AdvancedPlansViews = {
|
||||
let view = AdvancedPlansViews()
|
||||
view.title.text = "Annual"
|
||||
view.detailTitle.text = "$35.99/year"
|
||||
view.detailTitle2.text = "$3/month"
|
||||
view.detailTitle.text = "\(VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdAdvancedYearly))/year"
|
||||
view.detailTitle2.text = "$2.99/month"
|
||||
view.discountImageView.image = UIImage(named: "saveDiscount")
|
||||
view.iconImageView.image = UIImage(named: "fill-1")
|
||||
view.backgroundView.layer.borderColor = UIColor.white.cgColor
|
||||
@@ -68,7 +68,7 @@ final class FirewallPaywallViewController: BaseViewController, Loadable {
|
||||
monthlyPlan.iconImageView.image = UIImage(named: "grey-ellipse-1")
|
||||
monthlyPlan.backgroundView.layer.borderColor = UIColor.borderGray.cgColor
|
||||
|
||||
ftPriceLabel.text = "7-day free trial, then $29.99 yearly. Cancel anytime."
|
||||
ftPriceLabel.text = "7-day free trial, then \(VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdAdvancedYearly)) yearly. Cancel anytime."
|
||||
}
|
||||
return view
|
||||
}()
|
||||
@@ -76,7 +76,7 @@ final class FirewallPaywallViewController: BaseViewController, Loadable {
|
||||
private lazy var monthlyPlan: AdvancedPlansViews = {
|
||||
let view = AdvancedPlansViews()
|
||||
view.title.text = "Monthly"
|
||||
view.detailTitle.text = "$4.99/month"
|
||||
view.detailTitle.text = "\(VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdAdvancedMonthly))/month"
|
||||
view.detailTitle2.text = " "
|
||||
view.isUserInteractionEnabled = true
|
||||
|
||||
@@ -93,7 +93,7 @@ final class FirewallPaywallViewController: BaseViewController, Loadable {
|
||||
annualPlan.iconImageView.image = UIImage(named: "grey-ellipse-1")
|
||||
annualPlan.backgroundView.layer.borderColor = UIColor.borderGray.cgColor
|
||||
|
||||
ftPriceLabel.text = "7-day free trial, then $4.99 monthly. Cancel anytime."
|
||||
ftPriceLabel.text = "7-day free trial, then \(VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdAdvancedMonthly)) monthly. Cancel anytime."
|
||||
}
|
||||
return view
|
||||
}()
|
||||
@@ -111,7 +111,7 @@ final class FirewallPaywallViewController: BaseViewController, Loadable {
|
||||
|
||||
lazy var ftPriceLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.text = NSLocalizedString("7-day free trial, then $35.99 yearly. Cancel anytime.", comment: "")
|
||||
label.text = NSLocalizedString("7-day free trial, then \(VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdAdvancedYearly)) yearly. Cancel anytime.", comment: "")
|
||||
label.textColor = .smallGrey
|
||||
label.font = fontMedium11
|
||||
label.textAlignment = .center
|
||||
@@ -401,13 +401,7 @@ extension FirewallPaywallViewController: ProductPurchasable {
|
||||
|
||||
// TODO: change view of LDFirewallViewController
|
||||
}
|
||||
|
||||
advancedPlanUpdated?()
|
||||
UserDefaults.hasSeenAdvancedPaywall = true
|
||||
// if let vc = firewallVC {
|
||||
// vc.advancedPlanUpdated = true
|
||||
// UserDefaults.hasSeenAdvancedPaywall = true
|
||||
// }
|
||||
|
||||
// force refresh receipt, and sync with email if it exists, activate VPNte
|
||||
if let apiCredentials = getAPICredentials(), getAPICredentialsConfirmed() == true {
|
||||
|
||||
@@ -67,8 +67,13 @@ final class LDConfigurationViewController: UIViewController {
|
||||
view.isUserInteractionEnabled = true
|
||||
view.setOnClickListener { [weak self] in
|
||||
guard let self else { return }
|
||||
let vc = ImportBlockListViewController()
|
||||
self.present(vc, animated: true)
|
||||
if UserDefaults.hasSeenAdvancedPaywall || UserDefaults.hasSeenAnonymousPaywall || UserDefaults.hasSeenUniversalPaywall {
|
||||
let vc = ImportBlockListViewController()
|
||||
self.present(vc, animated: true)
|
||||
} else {
|
||||
let vc = VPNPaywallViewController()
|
||||
self.present(vc, animated: true)
|
||||
}
|
||||
}
|
||||
return view
|
||||
}()
|
||||
|
||||
@@ -48,6 +48,36 @@ final class LDFirewallViewController: BaseViewController {
|
||||
return view
|
||||
}()
|
||||
|
||||
lazy var yourCurrentPlanLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.text = NSLocalizedString("Your current plan is", comment: "")
|
||||
label.font = fontRegular14
|
||||
label.numberOfLines = 0
|
||||
label.textColor = .label
|
||||
return label
|
||||
}()
|
||||
|
||||
lazy var upgradeLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.text = NSLocalizedString("Upgrade?", comment: "")
|
||||
label.font = fontBold13
|
||||
label.textColor = .tunnelsBlue
|
||||
label.isUserInteractionEnabled = true
|
||||
label.setOnClickListener {
|
||||
let vc = VPNPaywallViewController()
|
||||
self.present(vc, animated: true)
|
||||
}
|
||||
return label
|
||||
}()
|
||||
|
||||
lazy var protectionPlanLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.text = NSLocalizedString("Basic Protection", comment: "")
|
||||
label.font = fontBold22
|
||||
label.textColor = .label
|
||||
return label
|
||||
}()
|
||||
|
||||
lazy var firewallTitle: UILabel = {
|
||||
let label = UILabel()
|
||||
label.text = NSLocalizedString("Get complete protection", comment: "")
|
||||
@@ -226,8 +256,6 @@ final class LDFirewallViewController: BaseViewController {
|
||||
super.viewDidLoad()
|
||||
VPNSubscription.cacheLocalizedPrices()
|
||||
|
||||
|
||||
|
||||
updateFirewallButtonWithStatus(status: FirewallController.shared.status())
|
||||
updateMetrics()
|
||||
if metricsTimer == nil {
|
||||
@@ -243,8 +271,20 @@ final class LDFirewallViewController: BaseViewController {
|
||||
firewallSwitchControl.anchors.trailing.marginsPin()
|
||||
firewallSwitchControl.anchors.height.equal(56)
|
||||
|
||||
view.addSubview(yourCurrentPlanLabel)
|
||||
yourCurrentPlanLabel.anchors.leading.marginsPin()
|
||||
yourCurrentPlanLabel.anchors.top.safeAreaPin()
|
||||
|
||||
view.addSubview(upgradeLabel)
|
||||
upgradeLabel.anchors.trailing.marginsPin()
|
||||
upgradeLabel.anchors.centerY.equal(yourCurrentPlanLabel.anchors.centerY)
|
||||
|
||||
view.addSubview(protectionPlanLabel)
|
||||
protectionPlanLabel.anchors.top.spacing(8, to: yourCurrentPlanLabel.anchors.bottom)
|
||||
protectionPlanLabel.anchors.leading.marginsPin()
|
||||
|
||||
view.addSubview(scrollView)
|
||||
scrollView.anchors.top.safeAreaPin()
|
||||
scrollView.anchors.top.spacing(12, to: protectionPlanLabel.anchors.bottom)
|
||||
scrollView.anchors.leading.pin()
|
||||
scrollView.anchors.trailing.pin()
|
||||
scrollView.anchors.bottom.spacing(8, to: firewallSwitchControl.anchors.top)
|
||||
@@ -260,13 +300,8 @@ final class LDFirewallViewController: BaseViewController {
|
||||
stackView.anchors.leading.marginsPin()
|
||||
stackView.anchors.trailing.marginsPin()
|
||||
|
||||
contentView.addSubview(cpStackView)
|
||||
cpStackView.anchors.top.spacing(18, to: stackView.anchors.bottom)
|
||||
cpStackView.anchors.leading.marginsPin()
|
||||
cpStackView.anchors.trailing.marginsPin()
|
||||
|
||||
contentView.addSubview(upgradeButton)
|
||||
upgradeButton.anchors.top.spacing(18, to: cpStackView.anchors.bottom)
|
||||
upgradeButton.anchors.top.spacing(18, to: stackView.anchors.bottom)
|
||||
upgradeButton.anchors.leading.marginsPin()
|
||||
upgradeButton.anchors.trailing.marginsPin()
|
||||
|
||||
@@ -280,9 +315,11 @@ final class LDFirewallViewController: BaseViewController {
|
||||
statisitcsView.anchors.leading.marginsPin()
|
||||
statisitcsView.anchors.trailing.marginsPin()
|
||||
|
||||
accountStateDidChange()
|
||||
updateProtectionPlanUI()
|
||||
|
||||
// accountStateDidChange()
|
||||
|
||||
// NotificationCenter.default.addObserver(self, selector: #selector(accountStateDidChange), name: Notification.Name("AdvancedPlanActive"), object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(tunnelStatusDidChange(_:)), name: .NEVPNStatusDidChange, object: nil)
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
@@ -297,6 +334,21 @@ extension LDFirewallViewController: Loadable {
|
||||
updateActiveSubscription()
|
||||
}
|
||||
|
||||
func updateProtectionPlanUI() {
|
||||
if UserDefaults.hasSeenUniversalPaywall {
|
||||
updateUI()
|
||||
protectionPlanLabel.text = "Universal protection"
|
||||
} else if UserDefaults.hasSeenAnonymousPaywall {
|
||||
updateUI()
|
||||
protectionPlanLabel.text = "Anonymous protection"
|
||||
} else if UserDefaults.hasSeenAdvancedPaywall {
|
||||
updateUI()
|
||||
protectionPlanLabel.text = "Advanced protection"
|
||||
} else {
|
||||
protectionPlanLabel.text = "Basic protection"
|
||||
}
|
||||
}
|
||||
|
||||
func updateUI() {
|
||||
firewallTitle.isHidden = true
|
||||
firewallDescriptionLabel1.isHidden = true
|
||||
@@ -310,7 +362,6 @@ extension LDFirewallViewController: Loadable {
|
||||
cpTrackersGroupView2.number.isHidden = false
|
||||
cpTrackersGroupView3.lockImage.isHidden = true
|
||||
cpTrackersGroupView3.number.isHidden = false
|
||||
cpTitle.text = "Most active not blocked"
|
||||
}
|
||||
|
||||
func updateActiveSubscription() {
|
||||
@@ -325,9 +376,15 @@ extension LDFirewallViewController: Loadable {
|
||||
}.done { [self] subscriptions in
|
||||
self.activePlans = subscriptions.map({ $0.planType })
|
||||
if let active = subscriptions.first {
|
||||
if active.planType == .proAnnual || active.planType == .proMonthly || active.planType == .advancedMonthly || active.planType == .advancedYearly || active.planType == .monthly || active.planType == .annual {
|
||||
if active.planType == .proAnnual || active.planType == .proMonthly {
|
||||
protectionPlanLabel.text = "Universal protection"
|
||||
updateUI()
|
||||
UserDefaults.hasSeenAdvancedPaywall = true
|
||||
} else if active.planType == .monthly || active.planType == .annual {
|
||||
updateUI()
|
||||
protectionPlanLabel.text = "Anonymous protection"
|
||||
} else if active.planType == .advancedMonthly || active.planType == .advancedYearly {
|
||||
updateUI()
|
||||
protectionPlanLabel.text = "Advanced protection"
|
||||
} else {
|
||||
firewallTitle.textColor = .red
|
||||
}
|
||||
@@ -383,13 +440,10 @@ extension LDFirewallViewController: Loadable {
|
||||
DispatchQueue.main.async { [unowned self] in
|
||||
self.statisitcsView.enabledBoxView.numberLabel.text = String(getTotalEnabled().count)
|
||||
self.statisitcsView.disabledBoxView.numberLabel.text = String(getTotalDisabled().count)
|
||||
self.statisitcsView.requestsBoxView.numberLabel.text = String(Int.random(in: 1..<144))
|
||||
self.statisitcsView.blockedBoxView.numberLabel.text = String(getAllBlockedDomains().count)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func toggleFirewall() {
|
||||
if (defaults.bool(forKey: kHasAgreedToFirewallPrivacyPolicy) == false) {
|
||||
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
||||
|
||||
@@ -32,6 +32,36 @@ final class LDVpnViewController: BaseViewController {
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var yourCurrentPlanLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.text = NSLocalizedString("Your current plan is", comment: "")
|
||||
label.font = fontRegular14
|
||||
label.numberOfLines = 0
|
||||
label.textColor = .label
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var upgradeLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.text = NSLocalizedString("Upgrade?", comment: "")
|
||||
label.font = fontBold13
|
||||
label.textColor = .tunnelsBlue
|
||||
label.isUserInteractionEnabled = true
|
||||
label.setOnClickListener {
|
||||
let vc = VPNPaywallViewController()
|
||||
self.present(vc, animated: true)
|
||||
}
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var protectionPlanLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.text = NSLocalizedString("Basic Protection", comment: "")
|
||||
label.font = fontBold22
|
||||
label.textColor = .label
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var mainTitle: UILabel = {
|
||||
let label = UILabel()
|
||||
label.text = NSLocalizedString("Get Anonymous protection", comment: "")
|
||||
@@ -162,8 +192,20 @@ final class LDVpnViewController: BaseViewController {
|
||||
vpnSwitchControl.anchors.trailing.marginsPin()
|
||||
vpnSwitchControl.anchors.height.equal(56)
|
||||
|
||||
view.addSubview(yourCurrentPlanLabel)
|
||||
yourCurrentPlanLabel.anchors.leading.marginsPin()
|
||||
yourCurrentPlanLabel.anchors.top.safeAreaPin()
|
||||
|
||||
view.addSubview(upgradeLabel)
|
||||
upgradeLabel.anchors.trailing.marginsPin()
|
||||
upgradeLabel.anchors.centerY.equal(yourCurrentPlanLabel.anchors.centerY)
|
||||
|
||||
view.addSubview(protectionPlanLabel)
|
||||
protectionPlanLabel.anchors.top.spacing(8, to: yourCurrentPlanLabel.anchors.bottom)
|
||||
protectionPlanLabel.anchors.leading.marginsPin()
|
||||
|
||||
view.addSubview(scrollView)
|
||||
scrollView.anchors.top.safeAreaPin()
|
||||
scrollView.anchors.top.spacing(12, to: protectionPlanLabel.anchors.bottom)
|
||||
scrollView.anchors.leading.pin()
|
||||
scrollView.anchors.trailing.pin()
|
||||
scrollView.anchors.bottom.spacing(8, to: vpnSwitchControl.anchors.top)
|
||||
@@ -216,7 +258,8 @@ final class LDVpnViewController: BaseViewController {
|
||||
// self.performSegue(withIdentifier: "showSignup", sender: self)
|
||||
})
|
||||
default:
|
||||
_ = self.popupErrorAsApiError(error)
|
||||
// _ = self.popupErrorAsApiError(error)
|
||||
break
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -227,7 +270,34 @@ final class LDVpnViewController: BaseViewController {
|
||||
}
|
||||
}
|
||||
|
||||
accountStateDidChange()
|
||||
if UserDefaults.hasSeenAnonymousPaywall {
|
||||
mainTitle.text = "Get Universal protection"
|
||||
descriptionLabel1.lockImage.image = UIImage(named: "icn_checkmark")
|
||||
descriptionLabel2.lockImage.image = UIImage(named: "icn_checkmark")
|
||||
descriptionLabel3.lockImage.image = UIImage(named: "icn_checkmark")
|
||||
descriptionLabel4.lockImage.image = UIImage(named: "icn_checkmark")
|
||||
protectionPlanLabel.text = "Anonymous protection"
|
||||
} else if UserDefaults.hasSeenUniversalPaywall {
|
||||
mainTitle.text = "You're fully protected"
|
||||
descriptionLabel1.lockImage.image = UIImage(named: "icn_checkmark")
|
||||
descriptionLabel2.lockImage.image = UIImage(named: "icn_checkmark")
|
||||
descriptionLabel3.lockImage.image = UIImage(named: "icn_checkmark")
|
||||
descriptionLabel4.lockImage.image = UIImage(named: "icn_checkmark")
|
||||
descriptionLabel5.lockImage.image = UIImage(named: "icn_checkmark")
|
||||
descriptionLabel6.lockImage.image = UIImage(named: "icn_checkmark")
|
||||
upgradeButton.isHidden = true
|
||||
upgradeButton.anchors.height.equal(0)
|
||||
protectionPlanLabel.text = "Universal protection"
|
||||
} else if UserDefaults.hasSeenAdvancedPaywall {
|
||||
descriptionLabel1.lockImage.image = UIImage(named: "icn_checkmark")
|
||||
descriptionLabel2.lockImage.image = UIImage(named: "icn_checkmark")
|
||||
descriptionLabel3.lockImage.image = UIImage(named: "icn_checkmark")
|
||||
protectionPlanLabel.text = "Advanced protection"
|
||||
} else {
|
||||
protectionPlanLabel.text = "Basic protection"
|
||||
}
|
||||
|
||||
// accountStateDidChange()
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(tunnelStatusDidChange(_:)), name: .NEVPNStatusDidChange, object: nil)
|
||||
}
|
||||
@@ -428,7 +498,9 @@ extension LDVpnViewController: Loadable {
|
||||
}
|
||||
}
|
||||
else {
|
||||
_ = self.popupErrorAsApiError(error)
|
||||
// _ = self.popupErrorAsApiError(error)
|
||||
self.updateVPNButtonWithStatus(status: .connecting)
|
||||
VPNController.shared.setEnabled(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,9 +309,6 @@ extension ListSettingsViewController {
|
||||
}
|
||||
|
||||
func setBlockingEnabled(_ isEnabled: Bool) {
|
||||
if let vc = self.blockListVC {
|
||||
vc.didMakeChange = true
|
||||
}
|
||||
|
||||
let domains = getBlockedLists().userBlockListsDefaults
|
||||
var userList = domains[listName]
|
||||
@@ -322,6 +319,10 @@ extension ListSettingsViewController {
|
||||
data.userBlockListsDefaults[listName] = userList
|
||||
let encodedData = try? JSONEncoder().encode(data)
|
||||
defaults.set(encodedData, forKey: kUserBlockedLists)
|
||||
|
||||
if let vc = self.blockListVC {
|
||||
vc.didMakeChange = true
|
||||
}
|
||||
}
|
||||
|
||||
@objc func exportList(_ sender: UIButton) {
|
||||
|
||||
@@ -24,7 +24,7 @@ final class BoxLabelView: UIView {
|
||||
view.layer.cornerRadius = 4
|
||||
view.layer.borderColor = UIColor.lightGray.cgColor
|
||||
view.layer.borderWidth = 1
|
||||
view.anchors.height.equal(65)
|
||||
view.anchors.height.equal(85)
|
||||
return view
|
||||
}()
|
||||
|
||||
@@ -96,13 +96,6 @@ final class OverallStatiscticView: UIView {
|
||||
return box
|
||||
}()
|
||||
|
||||
lazy var requestsBoxView: BoxLabelView = {
|
||||
let box = BoxLabelView()
|
||||
box.numberLabel.text = "0.9K"
|
||||
box.boxTitle.text = "Requests"
|
||||
return box
|
||||
}()
|
||||
|
||||
lazy var blockedBoxView: BoxLabelView = {
|
||||
let box = BoxLabelView()
|
||||
box.numberLabel.text = "0.2K"
|
||||
@@ -114,7 +107,6 @@ final class OverallStatiscticView: UIView {
|
||||
let stackView = UIStackView()
|
||||
stackView.addArrangedSubview(enabledBoxView)
|
||||
stackView.addArrangedSubview(disabledBoxView)
|
||||
stackView.addArrangedSubview(requestsBoxView)
|
||||
stackView.addArrangedSubview(blockedBoxView)
|
||||
stackView.axis = .horizontal
|
||||
stackView.distribution = .fillEqually
|
||||
|
||||
53
LockdowniOS/SplashscreenViewController.swift
Normal file
53
LockdowniOS/SplashscreenViewController.swift
Normal file
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// SplashscreenViewController.swift
|
||||
// Lockdown
|
||||
//
|
||||
// Created by Aliaksandr Dvoineu on 12.05.23.
|
||||
// Copyright © 2023 Confirmed Inc. All rights reserved.
|
||||
//
|
||||
|
||||
import AppTrackingTransparency
|
||||
import UIKit
|
||||
|
||||
final class SplashscreenViewController: BaseViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
BaseUserService.shared.updateUserSubscription { [weak self] _ in
|
||||
DispatchQueue.main.async {
|
||||
self?.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func dismiss() {
|
||||
dismiss(animated: false) {
|
||||
let keyWindow = UIApplication.shared.windows.first(where: { $0.isKeyWindow })
|
||||
keyWindow?.rootViewController = UIStoryboard.main.instantiateViewController(withIdentifier: "MainTabBarController")
|
||||
|
||||
|
||||
// Do not show onboarding if user has seen the previous onboarding or has already seen this new one
|
||||
// if OneTimeActions.hasSeen(.welcomeScreen) == false,
|
||||
// OneTimeActions.hasSeen(.newFancyOnboarding) == false {
|
||||
// let onboardingViewController = OnboardingViewController()
|
||||
// let navigation = UINavigationController(rootViewController: onboardingViewController)
|
||||
// keyWindow?.rootViewController = navigation
|
||||
// } else {
|
||||
// keyWindow?.rootViewController = UIStoryboard.main.instantiateViewController(withIdentifier: "MainTabBarController")
|
||||
// }
|
||||
keyWindow?.makeKeyAndVisible()
|
||||
}
|
||||
}
|
||||
|
||||
private func askForPermissionToTrack(completion: @escaping () -> Void) {
|
||||
guard #available(iOS 14, *) else {
|
||||
completion()
|
||||
return
|
||||
}
|
||||
|
||||
ATTrackingManager.requestTrackingAuthorization(completionHandler: { _ in
|
||||
completion()
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -117,7 +117,7 @@ final class UniversalPaywallView: UIView {
|
||||
|
||||
let descriptionLabel = UILabel()
|
||||
descriptionLabel.font = fontMedium11
|
||||
descriptionLabel.text = "then $74.99 per year"
|
||||
descriptionLabel.text = "then \(VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdAnnualPro)) per year"
|
||||
descriptionLabel.textColor = .white
|
||||
descriptionLabel.textAlignment = .left
|
||||
descriptionLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
@@ -126,7 +126,7 @@ final class UniversalPaywallView: UIView {
|
||||
descriptionLabel.anchors.leading.pin(inset: 24)
|
||||
|
||||
let descriptionLabel2 = UILabel()
|
||||
descriptionLabel2.text = "only $6.25 per month"
|
||||
descriptionLabel2.text = "only $8.33 per month"
|
||||
descriptionLabel2.font = fontMedium11
|
||||
descriptionLabel2.textColor = .white
|
||||
button.addSubview(descriptionLabel2)
|
||||
@@ -154,7 +154,7 @@ final class UniversalPaywallView: UIView {
|
||||
|
||||
let descriptionLabel = UILabel()
|
||||
descriptionLabel.font = fontMedium11
|
||||
descriptionLabel.text = "$11.99/month"
|
||||
descriptionLabel.text = "\(VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdMonthlyPro))/month"
|
||||
descriptionLabel.textColor = .white
|
||||
descriptionLabel.textAlignment = .left
|
||||
|
||||
|
||||
@@ -58,7 +58,6 @@ final class BaseUserService: UserService {
|
||||
}.done { subscriptions in
|
||||
DDLogInfo("active-subs: \(subscriptions)")
|
||||
NotificationCenter.default.post(name: AccountUI.accountStateDidChange, object: self)
|
||||
|
||||
self.user.updateSubscription(to: subscriptions.first)
|
||||
completion(subscriptions.first)
|
||||
}.catch { error in
|
||||
@@ -69,6 +68,7 @@ final class BaseUserService: UserService {
|
||||
DDLogError("Error loading plan: Non-API Error - \(error.localizedDescription)")
|
||||
}
|
||||
self.user.updateSubscription(to: nil)
|
||||
// TODO: to change later when there will be data on the server
|
||||
completion(nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +125,10 @@ final class VPNPaywallViewController: BaseViewController, Loadable {
|
||||
|
||||
lazy var advancedView: AdvancedPaywallView = {
|
||||
let view = AdvancedPaywallView()
|
||||
if UserDefaults.hasSeenAdvancedPaywall || UserDefaults.hasSeenAnonymousPaywall || UserDefaults.hasSeenUniversalPaywall {
|
||||
view.buyButton1.isEnabled = false
|
||||
view.buyButton2.isEnabled = false
|
||||
}
|
||||
view.buyButton1.setOnClickListener { [unowned self] in
|
||||
selectAdvancedYearly()
|
||||
startTrial()
|
||||
@@ -139,6 +143,10 @@ final class VPNPaywallViewController: BaseViewController, Loadable {
|
||||
lazy var anonymousView: AnonymousPaywallView = {
|
||||
let view = AnonymousPaywallView()
|
||||
view.isHidden = true
|
||||
if UserDefaults.hasSeenAnonymousPaywall || UserDefaults.hasSeenUniversalPaywall {
|
||||
view.buyButton1.isEnabled = false
|
||||
view.buyButton2.isEnabled = false
|
||||
}
|
||||
view.buyButton1.setOnClickListener { [unowned self] in
|
||||
selectAnonymousYearly()
|
||||
startTrial()
|
||||
@@ -153,6 +161,10 @@ final class VPNPaywallViewController: BaseViewController, Loadable {
|
||||
lazy var universalView: UniversalPaywallView = {
|
||||
let view = UniversalPaywallView()
|
||||
view.isHidden = true
|
||||
if UserDefaults.hasSeenUniversalPaywall {
|
||||
view.buyButton1.isEnabled = false
|
||||
view.buyButton2.isEnabled = false
|
||||
}
|
||||
view.buyButton1.setOnClickListener { [unowned self] in
|
||||
selectUniversalYearly()
|
||||
startTrial()
|
||||
@@ -191,7 +203,6 @@ final class VPNPaywallViewController: BaseViewController, Loadable {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
view.backgroundColor = .paywallNew
|
||||
|
||||
configureUI()
|
||||
}
|
||||
|
||||
@@ -245,8 +256,6 @@ final class VPNPaywallViewController: BaseViewController, Loadable {
|
||||
dismiss(animated: true)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@objc private func labelTapped(sender: UITapGestureRecognizer) {
|
||||
let termsRange = NSRange(location: privacyLabel.attributedText!.length - NSLocalizedString("Terms of Service", comment: "").count - 18, length: NSLocalizedString("Terms of Service", comment: "").count)
|
||||
let privacyRange = NSRange(location: privacyLabel.attributedText!.length - NSLocalizedString("Privacy Policy", comment: "").count, length: NSLocalizedString("Privacy Policy", comment: "").count)
|
||||
@@ -310,11 +319,9 @@ extension VPNPaywallViewController: ProductPurchasable {
|
||||
if advancedView.isSelected {
|
||||
let monthlyPlanLabel = VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdAdvancedMonthly, for: context)
|
||||
let annualPlanLabel = VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdAdvancedMonthly, for: context)
|
||||
// ftPriceLabel.text = "7-day free trial, then \(priceLabel). Cancel anytime."
|
||||
} else if anonymousView.isSelected {
|
||||
let monthlyPlanLabel = VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdMonthly, for: context)
|
||||
let annualPlanLabel = VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdAnnual, for: context)
|
||||
// ftPriceLabel.text = "7-day free trial, then \(priceLabel). Cancel anytime."
|
||||
} else if universalView.isSelected {
|
||||
let monthlyPlanLabel = VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdMonthlyPro, for: context)
|
||||
let annualPlanLabel = VPNSubscription.getProductIdPrice(productId: VPNSubscription.productIdAnnualPro, for: context)
|
||||
@@ -328,7 +335,23 @@ extension VPNPaywallViewController: ProductPurchasable {
|
||||
self.dismiss(animated: true, completion: {
|
||||
if let presentingViewController = self.parentVC as? LDVpnViewController {
|
||||
// TODO: change view of LDFirewallViewController
|
||||
|
||||
}
|
||||
if self.anonymousView.isSelected {
|
||||
UserDefaults.hasSeenAnonymousPaywall = true
|
||||
UserDefaults.hasSeenUniversalPaywall = false
|
||||
UserDefaults.hasSeenAdvancedPaywall = false
|
||||
} else if self.universalView.isSelected {
|
||||
UserDefaults.hasSeenAnonymousPaywall = false
|
||||
UserDefaults.hasSeenUniversalPaywall = true
|
||||
UserDefaults.hasSeenAdvancedPaywall = false
|
||||
} else if self.advancedView.isSelected {
|
||||
UserDefaults.hasSeenAnonymousPaywall = false
|
||||
UserDefaults.hasSeenUniversalPaywall = false
|
||||
UserDefaults.hasSeenAdvancedPaywall = true
|
||||
} else {
|
||||
UserDefaults.hasSeenAnonymousPaywall = false
|
||||
UserDefaults.hasSeenUniversalPaywall = false
|
||||
UserDefaults.hasSeenAdvancedPaywall = false
|
||||
}
|
||||
// force refresh receipt, and sync with email if it exists, activate VPNte
|
||||
if let apiCredentials = getAPICredentials(), getAPICredentialsConfirmed() == true {
|
||||
@@ -419,7 +442,8 @@ Please allow them in Settings App -> Screen Time -> Restrictions -> App Store ->
|
||||
self.showPopupDialog(title: .localized("Error Starting Trial"), message: errorText, acceptButton: .localizedOkay)
|
||||
} else if self.popupErrorAsNSURLError(error) {
|
||||
return
|
||||
} else if self.popupErrorAsApiError(error) {
|
||||
}
|
||||
else if self.popupErrorAsApiError(error) {
|
||||
return
|
||||
} else {
|
||||
self.showPopupDialog(
|
||||
|
||||
@@ -9,6 +9,7 @@ import UIKit
|
||||
import SwiftyStoreKit
|
||||
import PromiseKit
|
||||
import CocoaLumberjackSwift
|
||||
import StoreKit
|
||||
|
||||
enum SubscriptionState: Int {
|
||||
case Uninitialized = 1, Subscribed, NotSubscribed
|
||||
@@ -23,11 +24,11 @@ class VPNSubscription: NSObject {
|
||||
static let productIdMonthlyPro = "LockdowniOSVpnMonthlyPro"
|
||||
static let productIdAnnualPro = "LockdowniOSVpnAnnualPro"
|
||||
static let productIds: Set = [productIdAdvancedMonthly, productIdAdvancedYearly, productIdMonthly, productIdAnnual, productIdMonthlyPro, productIdAnnualPro]
|
||||
static var selectedProductId = productIdMonthly
|
||||
static var selectedProductId = productIdAdvancedMonthly
|
||||
|
||||
// Advanced Level
|
||||
static var defaultPriceStringAdvancedMonthly = "$4.99/month"
|
||||
static var defaultPriceStringAdvancedYearly = "then $35.99/year"
|
||||
static var defaultPriceStringAdvancedYearly = "then $29.99/year"
|
||||
static var defaultPriceSubStringAdvancedYearly = "only $2.49/month"
|
||||
|
||||
// Anonymous Level
|
||||
@@ -44,7 +45,7 @@ class VPNSubscription: NSObject {
|
||||
static var defaultUpgradePriceStringAdvancedYearly = "$29.99/year"
|
||||
static var defaultUpgradePriceStringMonthly = "$8.99 per month"
|
||||
static var defaultUpgradePriceStringMonthlyPro = "$11.99 per month"
|
||||
static var defaultUpgradePriceStringAnnual = "$59.99/year (~$4.17/month)"
|
||||
static var defaultUpgradePriceStringAnnual = "$59.99/year (~$4.99/month)"
|
||||
static var defaultUpgradePriceStringAnnualPro = "$99.99/year (~$8.33/month)"
|
||||
|
||||
static func purchase(succeeded: @escaping () -> Void, errored: @escaping (Error) -> Void) {
|
||||
@@ -167,8 +168,8 @@ class VPNSubscription: NSObject {
|
||||
if product.productIdentifier == productIdAdvancedMonthly {
|
||||
if product.localizedPrice != nil {
|
||||
DDLogInfo("setting monthly display price = " + product.localizedPrice!)
|
||||
setProductIdPrice(productId: productIdAdvancedMonthly, price: "\(product.localizedPrice!)/month")
|
||||
setProductIdUpgradePrice(productId: productIdAdvancedMonthly, upgradePrice: "\(product.localizedPrice!)/month")
|
||||
setProductIdPrice(productId: productIdAdvancedMonthly, price: "\(product.localizedPrice!)")
|
||||
setProductIdUpgradePrice(productId: productIdAdvancedMonthly, upgradePrice: "\(product.localizedPrice!)")
|
||||
}
|
||||
else {
|
||||
DDLogError("monthly nil localizedPrice, setting default")
|
||||
@@ -179,8 +180,8 @@ class VPNSubscription: NSObject {
|
||||
else if product.productIdentifier == productIdAdvancedYearly {
|
||||
if product.localizedPrice != nil {
|
||||
DDLogInfo("setting monthly display price = " + product.localizedPrice!)
|
||||
setProductIdPrice(productId: productIdAdvancedYearly, price: "then \(product.localizedPrice!) per year")
|
||||
setProductIdUpgradePrice(productId: productIdAdvancedYearly, upgradePrice: "\(product.localizedPrice!)/year")
|
||||
setProductIdPrice(productId: productIdAdvancedYearly, price: "\(product.localizedPrice!)")
|
||||
setProductIdUpgradePrice(productId: productIdAdvancedYearly, upgradePrice: "\(product.localizedPrice!)")
|
||||
}
|
||||
else {
|
||||
DDLogError("monthly nil localizedPrice, setting default")
|
||||
@@ -191,8 +192,8 @@ class VPNSubscription: NSObject {
|
||||
else if product.productIdentifier == productIdMonthly {
|
||||
if product.localizedPrice != nil {
|
||||
DDLogInfo("setting monthly display price = " + product.localizedPrice!)
|
||||
setProductIdPrice(productId: productIdMonthly, price: "\(product.localizedPrice!) per month after")
|
||||
setProductIdUpgradePrice(productId: productIdMonthly, upgradePrice: "\(product.localizedPrice!) per month")
|
||||
setProductIdPrice(productId: productIdMonthly, price: "\(product.localizedPrice!)")
|
||||
setProductIdUpgradePrice(productId: productIdMonthly, upgradePrice: "\(product.localizedPrice!)")
|
||||
}
|
||||
else {
|
||||
DDLogError("monthly nil localizedPrice, setting default")
|
||||
@@ -203,8 +204,8 @@ class VPNSubscription: NSObject {
|
||||
else if product.productIdentifier == productIdMonthlyPro {
|
||||
if product.localizedPrice != nil {
|
||||
DDLogInfo("setting monthlyPro display price = " + product.localizedPrice!)
|
||||
setProductIdPrice(productId: productIdMonthlyPro, price: "\(product.localizedPrice!) per month after")
|
||||
setProductIdUpgradePrice(productId: productIdMonthlyPro, upgradePrice: "\(product.localizedPrice!) per month")
|
||||
setProductIdPrice(productId: productIdMonthlyPro, price: "\(product.localizedPrice!)")
|
||||
setProductIdUpgradePrice(productId: productIdMonthlyPro, upgradePrice: "\(product.localizedPrice!)")
|
||||
}
|
||||
else {
|
||||
DDLogError("monthlyPro nil localizedPrice, setting default")
|
||||
@@ -216,10 +217,10 @@ class VPNSubscription: NSObject {
|
||||
currencyFormatter.locale = product.priceLocale
|
||||
let priceMonthly = product.price.dividing(by: 12)
|
||||
DDLogInfo("annual price = \(product.price)")
|
||||
if let priceString = currencyFormatter.string(from: product.price), let priceStringMonthly = currencyFormatter.string(from: priceMonthly) {
|
||||
if let priceString = currencyFormatter.string(from: product.price) {
|
||||
DDLogInfo("setting annual display price = annual product price / 12 = " + priceString)
|
||||
setProductIdPrice(productId: productIdAnnual, price: "\(priceString)/year after (~\(priceStringMonthly)/month)")
|
||||
setProductIdUpgradePrice(productId: productIdAnnual, upgradePrice: "\(priceString)/year (~\(priceStringMonthly)/month)")
|
||||
setProductIdPrice(productId: productIdAnnual, price: "\(priceString)")
|
||||
setProductIdUpgradePrice(productId: productIdAnnual, upgradePrice: "\(priceString)")
|
||||
}
|
||||
else {
|
||||
DDLogError("unable to format price with currencyformatter: " + product.price.stringValue)
|
||||
@@ -231,10 +232,10 @@ class VPNSubscription: NSObject {
|
||||
currencyFormatter.locale = product.priceLocale
|
||||
let priceMonthly = product.price.dividing(by: 12)
|
||||
DDLogInfo("annualPro price = \(product.price)")
|
||||
if let priceString = currencyFormatter.string(from: product.price), let priceStringMonthly = currencyFormatter.string(from: priceMonthly) {
|
||||
if let priceString = currencyFormatter.string(from: product.price) {
|
||||
DDLogInfo("setting annualPro display price = annualPro product price / 12 = " + priceString)
|
||||
setProductIdPrice(productId: productIdAnnualPro, price: "\(priceString)/year after (~\(priceStringMonthly)/month)")
|
||||
setProductIdUpgradePrice(productId: productIdAnnualPro, upgradePrice: "\(priceString)/year (~\(priceStringMonthly)/month)")
|
||||
setProductIdPrice(productId: productIdAnnualPro, price: "\(priceString)")
|
||||
setProductIdUpgradePrice(productId: productIdAnnualPro, upgradePrice: "\(priceString)")
|
||||
}
|
||||
else {
|
||||
DDLogError("unable to format price with currencyformatter: " + product.price.stringValue)
|
||||
|
||||
Reference in New Issue
Block a user