Add back always on option

This commit is contained in:
世界
2024-04-06 23:58:59 +08:00
parent db8cbfa865
commit debd0ca1a2
8 changed files with 94 additions and 25 deletions
@@ -12,7 +12,7 @@ public extension Binding {
public extension Binding where Value == Int32 {
func stringBinding(defaultValue: Int32) -> Binding<String> {
return Binding<String> {
Binding<String> {
var intValue = wrappedValue
if intValue == 0 {
intValue = defaultValue
@@ -0,0 +1,57 @@
import Foundation
import Library
import SwiftUI
public struct OnDemandRulesView: View {
@State private var isLoading = true
@State private var alwaysOn = false
public init() {}
public var body: some View {
viewBuilder {
if isLoading {
ProgressView().onAppear {
Task.detached {
await loadSettings()
}
}
} else {
FormView {
FormSection {
Toggle("Always On", isOn: $alwaysOn)
.onChangeCompat(of: alwaysOn) { newValue in
Task {
await SharedPreferences.alwaysOn.set(newValue)
}
}
} footer: {
Text("""
Implement always-on via on-demand rules.
This should not be an intended use of the API, so you cannot disable VPN in system settings. To stop the service manually, use the in-app interface or simply delete the VPN profile.
""")
}
FormButton {
Task {
await SharedPreferences.resetOnDemandRules()
isLoading = true
}
} label: {
Label("Reset", systemImage: "eraser.fill")
}
.foregroundColor(.red)
}
}
}
.navigationTitle("On Demand Rules")
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
#endif
}
private func loadSettings() async {
alwaysOn = await SharedPreferences.alwaysOn.get()
isLoading = false
}
}
@@ -2,10 +2,6 @@ import Library
import SwiftUI
struct PacketTunnelView: View {
#if os(macOS)
public static let windowID = "packet-tunnel"
#endif
@State private var isLoading = true
@State private var ignoreMemoryLimit = false
@@ -12,7 +12,7 @@ public struct SettingView: View {
case app
#endif
case core, packetTunnel, profileOverride, sponsors
case core, packetTunnel, onDemandRules, profileOverride, sponsors
var label: some View {
Label(title, systemImage: iconImage)
@@ -28,6 +28,8 @@ public struct SettingView: View {
return NSLocalizedString("Core", comment: "")
case .packetTunnel:
return NSLocalizedString("Packet Tunnel", comment: "")
case .onDemandRules:
return NSLocalizedString("On Demand Rules", comment: "")
case .profileOverride:
return NSLocalizedString("Profile Override", comment: "")
case .sponsors:
@@ -45,6 +47,8 @@ public struct SettingView: View {
return "shippingbox.fill"
case .packetTunnel:
return "aspectratio.fill"
case .onDemandRules:
return "filemenu.and.selection"
case .profileOverride:
return "square.dashed.inset.filled"
case .sponsors:
@@ -64,6 +68,8 @@ public struct SettingView: View {
CoreView()
case .packetTunnel:
PacketTunnelView()
case .onDemandRules:
OnDemandRulesView()
case .profileOverride:
ProfileOverrideView()
case .sponsors:
@@ -95,7 +101,7 @@ public struct SettingView: View {
#if os(macOS)
Tabs.app.navigationLink
#endif
ForEach([Tabs.core, Tabs.packetTunnel, Tabs.profileOverride]) { it in
ForEach([Tabs.core, Tabs.packetTunnel, Tabs.onDemandRules, Tabs.profileOverride]) { it in
it.navigationLink
}
#if !os(tvOS)
+8 -2
View File
@@ -9,8 +9,6 @@ public enum SharedPreferences {
private static let ignoreMemoryLimitByDefault = false
#endif
public static let alwaysOn = Preference<Bool>("always_on", defaultValue: false)
public static let ignoreMemoryLimit = Preference<Bool>("ignore_memory_limit", defaultValue: ignoreMemoryLimitByDefault)
#if os(iOS)
@@ -70,6 +68,14 @@ public enum SharedPreferences {
await excludeAPNsRoute.set(nil)
}
// On Demand Rules
public static let alwaysOn = Preference<Bool>("always_on", defaultValue: false)
public static func resetOnDemandRules() async {
await alwaysOn.set(nil)
}
#if DEBUG
public static let inDebug = true
#else
+16 -12
View File
@@ -69,6 +69,7 @@
3A60CC2B2B70AD6700D2D682 /* SettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A60CC2A2B70AD6700D2D682 /* SettingView.swift */; };
3A648D2D2A4EEAA600D95A12 /* Library.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A648D2C2A4EEAA600D95A12 /* Library.swift */; };
3A648D542A4EF4C700D95A12 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF342B12A4AA520002B34AC /* NetworkExtension.framework */; };
3A6CA4542BC19FDE0012B238 /* OnDemandRulesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A6CA4532BC19FDE0012B238 /* OnDemandRulesView.swift */; };
3A6CA5A02A71317A0027933B /* MarkdownUI in Frameworks */ = {isa = PBXBuildFile; productRef = 3A6CA59F2A71317A0027933B /* MarkdownUI */; };
3A6CA5A32A713A580027933B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3AEECC0A2A6DF9CA006A0E0C /* Assets.xcassets */; };
3A6CA5A62A713AA10027933B /* AppIcon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 3A6CA5A52A713AA10027933B /* AppIcon.icns */; };
@@ -479,6 +480,7 @@
3A60CC282B70A7C400D2D682 /* Color+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Color+Extension.swift"; sourceTree = "<group>"; };
3A60CC2A2B70AD6700D2D682 /* SettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingView.swift; sourceTree = "<group>"; };
3A648D2C2A4EEAA600D95A12 /* Library.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Library.swift; sourceTree = "<group>"; };
3A6CA4532BC19FDE0012B238 /* OnDemandRulesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnDemandRulesView.swift; sourceTree = "<group>"; };
3A6CA5A52A713AA10027933B /* AppIcon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon.icns; sourceTree = "<group>"; };
3A77016D2A4E6B34008F031F /* IntentsExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.extensionkit-extension"; includeInIndex = 0; path = IntentsExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
3A77016F2A4E6B34008F031F /* IntentsExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentsExtension.swift; sourceTree = "<group>"; };
@@ -756,6 +758,7 @@
3A60CC2A2B70AD6700D2D682 /* SettingView.swift */,
3A3AB2A62B70C146001815AE /* CoreView.swift */,
3A411CEB2B734959000D9501 /* MacAppView.swift */,
3A6CA4532BC19FDE0012B238 /* OnDemandRulesView.swift */,
);
path = Setting;
sourceTree = "<group>";
@@ -1498,6 +1501,7 @@
3A1CF2F62A50EE9C000A8289 /* GroupView.swift in Sources */,
3A4EAD212A4FEB3C005435B3 /* ApplicationLibrary.swift in Sources */,
3A7904502B6E7BAC006C08D5 /* SponsorsView.swift in Sources */,
3A6CA4542BC19FDE0012B238 /* OnDemandRulesView.swift in Sources */,
3A1CF2F22A50E613000A8289 /* OutboundGroup.swift in Sources */,
3A1CF2FA2A50F0BD000A8289 /* OutboundGroupItem.swift in Sources */,
3A99B42E2A752ABB0010D4B0 /* NavigationDestinationCompat.swift in Sources */,
@@ -2006,7 +2010,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.8.9;
MARKETING_VERSION = 1.8.11;
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa;
PRODUCT_NAME = "sing-box";
SDKROOT = appletvos;
@@ -2040,7 +2044,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.8.9;
MARKETING_VERSION = 1.8.11;
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa;
PRODUCT_NAME = "sing-box";
SDKROOT = appletvos;
@@ -2278,7 +2282,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.8.9;
MARKETING_VERSION = 1.8.11;
OTHER_CODE_SIGN_FLAGS = "--deep";
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa;
PRODUCT_NAME = "sing-box";
@@ -2318,7 +2322,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.8.9;
MARKETING_VERSION = 1.8.11;
OTHER_CODE_SIGN_FLAGS = "--deep";
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa;
PRODUCT_NAME = "sing-box";
@@ -2341,7 +2345,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 210;
CURRENT_PROJECT_VERSION = 213;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = Z56Z6NYZN2;
ENABLE_HARDENED_RUNTIME = YES;
@@ -2357,7 +2361,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.8.9;
MARKETING_VERSION = 1.8.11;
OTHER_CODE_SIGN_FLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa;
PRODUCT_NAME = "sing-box";
@@ -2379,7 +2383,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 210;
CURRENT_PROJECT_VERSION = 213;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = Z56Z6NYZN2;
ENABLE_HARDENED_RUNTIME = YES;
@@ -2395,7 +2399,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.8.9;
MARKETING_VERSION = 1.8.11;
OTHER_CODE_SIGN_FLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa;
PRODUCT_NAME = "sing-box";
@@ -2537,7 +2541,7 @@
"@executable_path/../../../../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.8.9;
MARKETING_VERSION = 1.8.11;
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.system;
PRODUCT_NAME = "$(inherited)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2573,7 +2577,7 @@
"@executable_path/../../../../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.8.9;
MARKETING_VERSION = 1.8.11;
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.system;
PRODUCT_NAME = "$(inherited)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2613,7 +2617,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.8.9;
MARKETING_VERSION = 1.8.11;
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.independent;
PRODUCT_NAME = SFM;
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -2652,7 +2656,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.8.9;
MARKETING_VERSION = 1.8.11;
PRODUCT_BUNDLE_IDENTIFIER = io.nekohasekai.sfa.independent;
PRODUCT_NAME = SFM;
PROVISIONING_PROFILE_SPECIFIER = "";