Version 1.0.0
1.0.0
|
Before Width: | Height: | Size: 773 B After Width: | Height: | Size: 773 B |
3
AppIcon.icon/Assets/StosPlug 3.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="674" height="674" viewBox="0 0 674 674" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M605 0C643.108 3.92999e-06 674 30.8924 674 69V605C674 643.108 643.108 674 605 674H414V593H439L520 376.5C521.833 372.333 526.4 363 530 359C534.5 354 537 346.5 537 341C537 335.529 532.547 311.258 470 294.27V149C470 140.714 467.198 133.084 462.494 127H382.506C377.802 133.084 375 140.714 375 149V275.253C350.381 273.121 325.624 273.092 301 275.167V149C301 140.714 298.198 133.084 293.494 127H213.506C208.802 133.084 206 140.714 206 149V294L204.522 294.399C142.43 311.381 138 335.543 138 341C138 346.5 140.5 354 145 359C148.6 363 153.167 372.333 155 376.5L237 593H262V674H69C30.8924 674 0 643.108 0 605V69C3.9305e-06 30.8924 30.8924 0 69 0H605Z" fill="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 773 B |
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"fill" : {
|
"fill" : {
|
||||||
"linear-gradient" : [
|
"linear-gradient" : [
|
||||||
"display-p3:0.72718,1.00000,0.56150,1.00000",
|
"display-p3:0.72549,1.00000,0.56078,1.00000",
|
||||||
"display-p3:0.23889,0.54053,0.96826,1.00000"
|
"display-p3:0.23922,0.54118,0.96863,1.00000"
|
||||||
],
|
],
|
||||||
"orientation" : {
|
"orientation" : {
|
||||||
"start" : {
|
"start" : {
|
||||||
@@ -17,20 +17,19 @@
|
|||||||
},
|
},
|
||||||
"groups" : [
|
"groups" : [
|
||||||
{
|
{
|
||||||
|
"hidden-specializations" : [
|
||||||
|
{
|
||||||
|
"value" : true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearance" : "tinted",
|
||||||
|
"value" : false
|
||||||
|
}
|
||||||
|
],
|
||||||
"layers" : [
|
"layers" : [
|
||||||
{
|
{
|
||||||
"blend-mode" : "normal",
|
"image-name" : "StosPlug 3.svg",
|
||||||
"hidden" : false,
|
"name" : "StosPlug 3"
|
||||||
"image-name" : "StosPlug.svg",
|
|
||||||
"name" : "StosPlug",
|
|
||||||
"opacity" : 0.5,
|
|
||||||
"position" : {
|
|
||||||
"scale" : 1,
|
|
||||||
"translation-in-points" : [
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"shadow" : {
|
"shadow" : {
|
||||||
@@ -46,6 +45,45 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"hidden-specializations" : [
|
||||||
|
{
|
||||||
|
"value" : false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearance" : "tinted",
|
||||||
|
"value" : true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"layers" : [
|
||||||
|
{
|
||||||
|
"fill-specializations" : [
|
||||||
|
{
|
||||||
|
"value" : {
|
||||||
|
"solid" : "display-p3:0.94916,0.94916,0.94916,0.50000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearance" : "tinted",
|
||||||
|
"value" : {
|
||||||
|
"solid" : "display-p3:1.00000,1.00000,1.00000,0.50000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hidden" : false,
|
||||||
|
"image-name" : "StosPlug 2.svg",
|
||||||
|
"name" : "StosPlug"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"shadow" : {
|
||||||
|
"kind" : "neutral",
|
||||||
|
"opacity" : 0.5
|
||||||
|
},
|
||||||
|
"translucency" : {
|
||||||
|
"enabled" : true,
|
||||||
|
"value" : 0.5
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"supported-platforms" : {
|
"supported-platforms" : {
|
||||||
|
|||||||
@@ -420,7 +420,7 @@
|
|||||||
DEVELOPMENT_TEAM = 42Q7QX86GV;
|
DEVELOPMENT_TEAM = 42Q7QX86GV;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = LocalDevVPN;
|
INFOPLIST_KEY_CFBundleDisplayName = LocalDevVPN;
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = Stossy11;
|
INFOPLIST_KEY_NSHumanReadableCopyright = "Coxson Engineering";
|
||||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
@@ -430,14 +430,15 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
|
MARKETING_VERSION = 1.0.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.jkcoxson.LocalDevVPN;
|
PRODUCT_BUNDLE_IDENTIFIER = com.jkcoxson.LocalDevVPN;
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
SUPPORTS_MACCATALYST = NO;
|
SUPPORTS_MACCATALYST = NO;
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "LocalDevVPN/LocalDevVPN-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "LocalDevVPN/LocalDevVPN-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2,3";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
TVOS_DEPLOYMENT_TARGET = 17.0;
|
TVOS_DEPLOYMENT_TARGET = 17.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
@@ -455,7 +456,7 @@
|
|||||||
DEVELOPMENT_TEAM = 42Q7QX86GV;
|
DEVELOPMENT_TEAM = 42Q7QX86GV;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = LocalDevVPN;
|
INFOPLIST_KEY_CFBundleDisplayName = LocalDevVPN;
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = Stossy11;
|
INFOPLIST_KEY_NSHumanReadableCopyright = "Coxson Engineering";
|
||||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
@@ -465,13 +466,14 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
|
MARKETING_VERSION = 1.0.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.jkcoxson.LocalDevVPN;
|
PRODUCT_BUNDLE_IDENTIFIER = com.jkcoxson.LocalDevVPN;
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SUPPORTED_PLATFORMS = "appletvos appletvsimulator iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
SUPPORTS_MACCATALYST = NO;
|
SUPPORTS_MACCATALYST = NO;
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "LocalDevVPN/LocalDevVPN-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "LocalDevVPN/LocalDevVPN-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2,3";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
TVOS_DEPLOYMENT_TARGET = 17.0;
|
TVOS_DEPLOYMENT_TARGET = 17.0;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
BlueprintIdentifier = "4EB3C76D2D96715400C1B22C"
|
BlueprintIdentifier = "4EB3C76D2D96715400C1B22C"
|
||||||
BuildableName = "TunnelProv.appex"
|
BuildableName = "TunnelProv.appex"
|
||||||
BlueprintName = "TunnelProv"
|
BlueprintName = "TunnelProv"
|
||||||
ReferencedContainer = "container:StosVPN.xcodeproj">
|
ReferencedContainer = "container:LocalDevVPN.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildActionEntry>
|
</BuildActionEntry>
|
||||||
<BuildActionEntry
|
<BuildActionEntry
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
BlueprintIdentifier = "4EB3C7572D96631A00C1B22C"
|
BlueprintIdentifier = "4EB3C7572D96631A00C1B22C"
|
||||||
BuildableName = "LocalDevVPN.app"
|
BuildableName = "LocalDevVPN.app"
|
||||||
BlueprintName = "LocalDevVPN"
|
BlueprintName = "LocalDevVPN"
|
||||||
ReferencedContainer = "container:StosVPN.xcodeproj">
|
ReferencedContainer = "container:LocalDevVPN.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildActionEntry>
|
</BuildActionEntry>
|
||||||
</BuildActionEntries>
|
</BuildActionEntries>
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
BlueprintIdentifier = "4EB3C7572D96631A00C1B22C"
|
BlueprintIdentifier = "4EB3C7572D96631A00C1B22C"
|
||||||
BuildableName = "LocalDevVPN.app"
|
BuildableName = "LocalDevVPN.app"
|
||||||
BlueprintName = "LocalDevVPN"
|
BlueprintName = "LocalDevVPN"
|
||||||
ReferencedContainer = "container:StosVPN.xcodeproj">
|
ReferencedContainer = "container:LocalDevVPN.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
@@ -74,7 +74,6 @@
|
|||||||
savedToolIdentifier = ""
|
savedToolIdentifier = ""
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
debugDocumentVersioning = "YES"
|
debugDocumentVersioning = "YES"
|
||||||
askForAppToLaunch = "Yes"
|
|
||||||
launchAutomaticallySubstyle = "2">
|
launchAutomaticallySubstyle = "2">
|
||||||
<BuildableProductRunnable
|
<BuildableProductRunnable
|
||||||
runnableDebuggingMode = "0">
|
runnableDebuggingMode = "0">
|
||||||
@@ -83,7 +82,7 @@
|
|||||||
BlueprintIdentifier = "4EB3C7572D96631A00C1B22C"
|
BlueprintIdentifier = "4EB3C7572D96631A00C1B22C"
|
||||||
BuildableName = "LocalDevVPN.app"
|
BuildableName = "LocalDevVPN.app"
|
||||||
BlueprintName = "LocalDevVPN"
|
BlueprintName = "LocalDevVPN"
|
||||||
ReferencedContainer = "container:StosVPN.xcodeproj">
|
ReferencedContainer = "container:LocalDevVPN.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
</ProfileAction>
|
</ProfileAction>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>SchemeUserState</key>
|
<key>SchemeUserState</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>StosVPN.xcscheme_^#shared#^_</key>
|
<key>LocalDevVPN.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "StosVPN-icon.jpg",
|
"filename" : "image-5.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"platform" : "ios",
|
"platform" : "ios",
|
||||||
"size" : "1024x1024"
|
"size" : "1024x1024"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 42 KiB |
BIN
LocalDevVPN/Assets.xcassets/AppIcon.appiconset/image-5.png
Normal file
|
After Width: | Height: | Size: 175 KiB |
|
Before Width: | Height: | Size: 20 KiB |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "1280x768 copy 3.jpeg",
|
"filename" : "image-2.png",
|
||||||
"idiom" : "tv"
|
"idiom" : "tv"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
|
After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 156 KiB |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "1280x768.png",
|
"filename" : "image.png",
|
||||||
"idiom" : "tv"
|
"idiom" : "tv"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
|
After Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 20 KiB |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "1280x768 copy 3.jpeg",
|
"filename" : "image-2.png",
|
||||||
"idiom" : "tv"
|
"idiom" : "tv"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
|
After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "Content.png",
|
"filename" : "image-2 1.png",
|
||||||
"idiom" : "tv",
|
"idiom" : "tv",
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "Content@2x.png",
|
"filename" : "image-2.png",
|
||||||
"idiom" : "tv",
|
"idiom" : "tv",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
}
|
}
|
||||||
|
|||||||
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 34 KiB |
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "cool.png",
|
"filename" : "image.png",
|
||||||
"idiom" : "tv",
|
"idiom" : "tv",
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "cool 1.png",
|
"filename" : "image 1.png",
|
||||||
"idiom" : "tv",
|
"idiom" : "tv",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
}
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 6.1 KiB |
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "Content.png",
|
"filename" : "image-2.png",
|
||||||
"idiom" : "tv",
|
"idiom" : "tv",
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "Content@2x.png",
|
"filename" : "image-2 1.png",
|
||||||
"idiom" : "tv",
|
"idiom" : "tv",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
}
|
}
|
||||||
|
|||||||
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 198 KiB |
|
Before Width: | Height: | Size: 73 KiB |
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "1280x768 copy 4.jpeg",
|
"filename" : "image-3.png",
|
||||||
"idiom" : "tv",
|
"idiom" : "tv",
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "1280x768 copy 4 2.jpeg",
|
"filename" : "image-3 1.png",
|
||||||
"idiom" : "tv",
|
"idiom" : "tv",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
LocalDevVPN/Assets.xcassets/AppIcon.brandassets/Top Shelf Image Wide.imageset/image-3 1.png
vendored
Normal file
|
After Width: | Height: | Size: 645 KiB |
BIN
LocalDevVPN/Assets.xcassets/AppIcon.brandassets/Top Shelf Image Wide.imageset/image-3.png
vendored
Normal file
|
After Width: | Height: | Size: 183 KiB |
|
Before Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 160 KiB |
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "1280x768 copy 4.jpeg",
|
"filename" : "image-4.png",
|
||||||
"idiom" : "tv",
|
"idiom" : "tv",
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "1280x768 copy 5.jpeg",
|
"filename" : "image-4 1.png",
|
||||||
"idiom" : "tv",
|
"idiom" : "tv",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
LocalDevVPN/Assets.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/image-4 1.png
vendored
Normal file
|
After Width: | Height: | Size: 639 KiB |
BIN
LocalDevVPN/Assets.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/image-4.png
vendored
Normal file
|
After Width: | Height: | Size: 277 KiB |
@@ -655,8 +655,9 @@ struct ContentView: View {
|
|||||||
Button {
|
Button {
|
||||||
showSettings = true
|
showSettings = true
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: "gear")
|
Image(systemName: "gearshape.fill")
|
||||||
.foregroundColor(.primary)
|
.font(.system(size: 20, weight: .medium))
|
||||||
|
.foregroundColor(.secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -727,6 +728,7 @@ struct StatusIndicatorView: View {
|
|||||||
.font(.subheadline)
|
.font(.subheadline)
|
||||||
.foregroundColor(tunnelManager.tunnelStatus == .connected ? .green : .secondary)
|
.foregroundColor(tunnelManager.tunnelStatus == .connected ? .green : .secondary)
|
||||||
}
|
}
|
||||||
|
.padding(.horizontal)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateAnimation() {
|
private func updateAnimation() {
|
||||||
@@ -757,16 +759,39 @@ struct ConnectionButton: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Button(action: action) {
|
Button(action: action) {
|
||||||
HStack {
|
if #available(iOS 19.0, *) {
|
||||||
Text(buttonText)
|
HStack(spacing: 8) {
|
||||||
.font(.headline)
|
if tunnelManager.tunnelStatus == .connecting || tunnelManager.tunnelStatus == .disconnecting {
|
||||||
.fontWeight(.semibold)
|
ProgressView()
|
||||||
|
.progressViewStyle(CircularProgressViewStyle(tint: .white))
|
||||||
if tunnelManager.tunnelStatus == .connecting || tunnelManager.tunnelStatus == .disconnecting {
|
}
|
||||||
ProgressView()
|
|
||||||
.progressViewStyle(CircularProgressViewStyle())
|
Text(buttonText)
|
||||||
.padding(.leading, 5)
|
.font(.system(size: 17, weight: .semibold))
|
||||||
}
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.frame(height: 56)
|
||||||
|
.glassEffect(.regular.interactive().tint(tunnelManager.tunnelStatus != .connected ? .red : .green), in: RoundedRectangle(cornerRadius: 14, style: .continuous))
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.shadow(color: tunnelManager.tunnelStatus.color.opacity(0.3), radius: 12, x: 0, y: 6)
|
||||||
|
} else {
|
||||||
|
HStack(spacing: 8) {
|
||||||
|
if tunnelManager.tunnelStatus == .connecting || tunnelManager.tunnelStatus == .disconnecting {
|
||||||
|
ProgressView()
|
||||||
|
.progressViewStyle(CircularProgressViewStyle(tint: .white))
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(buttonText)
|
||||||
|
.font(.system(size: 17, weight: .semibold))
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.frame(height: 56)
|
||||||
|
.background(
|
||||||
|
RoundedRectangle(cornerRadius: 14, style: .continuous)
|
||||||
|
.fill(buttonBackground)
|
||||||
|
)
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.shadow(color: tunnelManager.tunnelStatus.color.opacity(0.3), radius: 12, x: 0, y: 6)
|
||||||
}
|
}
|
||||||
.frame(width: 200, height: 50)
|
.frame(width: 200, height: 50)
|
||||||
.background(buttonBackground)
|
.background(buttonBackground)
|
||||||
@@ -775,6 +800,7 @@ struct ConnectionButton: View {
|
|||||||
.shadow(color: Color.black.opacity(0.15), radius: 10, x: 0, y: 5)
|
.shadow(color: Color.black.opacity(0.15), radius: 10, x: 0, y: 5)
|
||||||
}
|
}
|
||||||
.disabled(tunnelManager.tunnelStatus == .connecting || tunnelManager.tunnelStatus == .disconnecting)
|
.disabled(tunnelManager.tunnelStatus == .connecting || tunnelManager.tunnelStatus == .disconnecting)
|
||||||
|
.padding(.horizontal, 20)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var buttonText: String {
|
private var buttonText: String {
|
||||||
@@ -862,16 +888,21 @@ struct ConnectionStatsView: View {
|
|||||||
if hours > 0 {
|
if hours > 0 {
|
||||||
return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
|
return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
|
||||||
} else {
|
} else {
|
||||||
return String(format: "%02d:%02d", minutes, seconds)
|
return LinearGradient(
|
||||||
|
colors: [Color.blue, Color.blue.opacity(0.8)],
|
||||||
|
startPoint: .topLeading,
|
||||||
|
endPoint: .bottomTrailing
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StatItemView: View {
|
struct InfoCard: View {
|
||||||
let title: LocalizedStringKey
|
|
||||||
let value: String
|
|
||||||
let icon: String
|
let icon: String
|
||||||
|
let title: String
|
||||||
|
let subtitle: String
|
||||||
|
let accentColor: Color
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading, spacing: 10) {
|
VStack(alignment: .leading, spacing: 10) {
|
||||||
HStack {
|
HStack {
|
||||||
@@ -879,15 +910,24 @@ struct StatItemView: View {
|
|||||||
.foregroundColor(.blue)
|
.foregroundColor(.blue)
|
||||||
|
|
||||||
Text(title)
|
Text(title)
|
||||||
.font(.caption)
|
.font(.system(size: 15, weight: .semibold))
|
||||||
|
.foregroundColor(.primary)
|
||||||
|
|
||||||
|
Text(subtitle)
|
||||||
|
.font(.system(size: 13, weight: .regular))
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
|
.lineLimit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(value)
|
Text(value)
|
||||||
.font(.system(size: 16, weight: .semibold))
|
.font(.system(size: 16, weight: .semibold))
|
||||||
.foregroundColor(.primary)
|
.foregroundColor(.primary)
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.padding(16)
|
||||||
|
.background(
|
||||||
|
RoundedRectangle(cornerRadius: 14, style: .continuous)
|
||||||
|
.fill(Color(UIColor.secondarySystemGroupedBackground))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1151,10 +1191,18 @@ struct HelpView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Section(header: Text("app_info_header")) {
|
Section(header: Text("app_info_header")) {
|
||||||
HStack {
|
if let minVersion = Bundle.main.infoDictionary?["MinimumOSVersion"] as? String {
|
||||||
Image(systemName: "exclamationmark.shield")
|
let message = String(
|
||||||
Text("requires_ios")
|
format: NSLocalizedString("requires_ios", comment: ""),
|
||||||
|
minVersion
|
||||||
|
)
|
||||||
|
HStack {
|
||||||
|
Image(systemName: "exclamationmark.shield")
|
||||||
|
Text(message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
Image(systemName: "lock.shield")
|
Image(systemName: "lock.shield")
|
||||||
Text("uses_network_extension")
|
Text("uses_network_extension")
|
||||||
|
|||||||