Restart service when settings change
This commit is contained in:
@@ -243,7 +243,7 @@ import SwiftUI
|
||||
|
||||
@ToolbarContentBuilder private var toolbar: some ToolbarContent {
|
||||
#if os(tvOS)
|
||||
ToolbarItemGroup(placement: .topBarLeading) {
|
||||
ToolbarItemGroup(placement: .topBarLeading) {
|
||||
navigationButtons
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -143,7 +143,7 @@ import SwiftUI
|
||||
}
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
TVToolbarButton(title: String(localized: "Reset")) {
|
||||
TVToolbarButton(title: String(localized: "Reset")) {
|
||||
Task {
|
||||
await configuration.resetToDefault()
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ struct ProfilePickerSheet: View {
|
||||
.environment(\.editMode, $editMode)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .confirmationAction) {
|
||||
TVToolbarButton(title: editMode.isEditing ? String(localized: "Done"): String(localized: "Edit")) {
|
||||
TVToolbarButton(title: editMode.isEditing ? String(localized: "Done") : String(localized: "Edit")) {
|
||||
withAnimation {
|
||||
if editMode.isEditing {
|
||||
movingProfileID = nil
|
||||
|
||||
@@ -32,17 +32,7 @@ public final class OverviewViewModel: BaseViewModel {
|
||||
try LibboxNewStandaloneCommandClient()!.setSystemProxyEnabled(enabled)
|
||||
} else {
|
||||
await MainActor.run { reasserting = true }
|
||||
try await profile.stop()
|
||||
|
||||
var waitSeconds = 0
|
||||
while await profile.status != .disconnected {
|
||||
try await Task.sleep(nanoseconds: NSEC_PER_SEC)
|
||||
waitSeconds += 1
|
||||
if waitSeconds >= 5 {
|
||||
throw NSError(domain: "Restart service timeout", code: 0)
|
||||
}
|
||||
}
|
||||
try await profile.start()
|
||||
try await profile.restart()
|
||||
await MainActor.run { reasserting = false }
|
||||
}
|
||||
} catch {
|
||||
|
||||
@@ -3,7 +3,9 @@ import Library
|
||||
import SwiftUI
|
||||
|
||||
public struct OnDemandRulesView: View {
|
||||
@EnvironmentObject private var environments: ExtensionEnvironments
|
||||
@State private var isLoading = true
|
||||
@State private var alert: AlertState?
|
||||
@State private var alwaysOn = false
|
||||
|
||||
public init() {}
|
||||
@@ -23,11 +25,13 @@ public struct OnDemandRulesView: View {
|
||||
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.
|
||||
""", $alwaysOn) { newValue in
|
||||
await SharedPreferences.alwaysOn.set(newValue)
|
||||
await restartService()
|
||||
}
|
||||
|
||||
FormButton {
|
||||
Task {
|
||||
await SharedPreferences.resetOnDemandRules()
|
||||
await restartService()
|
||||
isLoading = true
|
||||
}
|
||||
} label: {
|
||||
@@ -38,11 +42,23 @@ public struct OnDemandRulesView: View {
|
||||
}
|
||||
}
|
||||
.navigationTitle("On Demand Rules")
|
||||
.alert($alert)
|
||||
#if os(iOS)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
#endif
|
||||
}
|
||||
|
||||
private func restartService() async {
|
||||
guard let profile = environments.extensionProfile, profile.status.isConnected else {
|
||||
return
|
||||
}
|
||||
do {
|
||||
try await profile.restart()
|
||||
} catch {
|
||||
alert = AlertState(error: error)
|
||||
}
|
||||
}
|
||||
|
||||
private func loadSettings() async {
|
||||
alwaysOn = await SharedPreferences.alwaysOn.get()
|
||||
isLoading = false
|
||||
|
||||
@@ -2,7 +2,9 @@ import Library
|
||||
import SwiftUI
|
||||
|
||||
struct PacketTunnelView: View {
|
||||
@EnvironmentObject private var environments: ExtensionEnvironments
|
||||
@State private var isLoading = true
|
||||
@State private var alert: AlertState?
|
||||
|
||||
@State private var ignoreMemoryLimit = false
|
||||
|
||||
@@ -27,6 +29,7 @@ struct PacketTunnelView: View {
|
||||
Do not enforce memory limits on sing-box. Will cause OOM on non-jailbroken iOS and tvOS devices.
|
||||
""", $ignoreMemoryLimit) { newValue in
|
||||
await SharedPreferences.ignoreMemoryLimit.set(newValue)
|
||||
await restartService()
|
||||
}
|
||||
|
||||
#if !os(tvOS)
|
||||
@@ -38,6 +41,7 @@ struct PacketTunnelView: View {
|
||||
[Apple Documentation](https://developer.apple.com/documentation/networkextension/nevpnprotocol/3131931-includeallnetworks)
|
||||
""", $includeAllNetworks) { newValue in
|
||||
await SharedPreferences.includeAllNetworks.set(newValue)
|
||||
await restartService()
|
||||
}
|
||||
|
||||
FormToggle("excludeAPNs", """
|
||||
@@ -46,14 +50,16 @@ struct PacketTunnelView: View {
|
||||
[Apple Documentation](https://developer.apple.com/documentation/networkextension/nevpnprotocol/4140516-excludeapns)
|
||||
""", $excludeAPNs) { newValue in
|
||||
await SharedPreferences.excludeAPNs.set(newValue)
|
||||
await restartService()
|
||||
}
|
||||
|
||||
FormToggle("excludeCellularServices", """
|
||||
If this property is true, the system excludes cellular services — such as Wi-Fi Calling, MMS, SMS, and Visual Voicemail — but only when the **includeAllNetworks** property is also true. This property doesn’t impact services that use the cellular network only — such as VoLTE — which the system automatically excludes.
|
||||
If this property is true, the system excludes cellular services — such as Wi-Fi Calling, MMS, SMS, and Visual Voicemail — but only when the **includeAllNetworks** property is also true. This property doesn't impact services that use the cellular network only — such as VoLTE — which the system automatically excludes.
|
||||
|
||||
[Apple Documentation](https://developer.apple.com/documentation/networkextension/nevpnprotocol/4140517-excludecellularservices)
|
||||
""", $excludeCellularServices) { newValue in
|
||||
await SharedPreferences.excludeCellularServices.set(newValue)
|
||||
await restartService()
|
||||
}
|
||||
|
||||
FormToggle("excludeLocalNetworks", """
|
||||
@@ -62,6 +68,7 @@ struct PacketTunnelView: View {
|
||||
[Apple Documentation](https://developer.apple.com/documentation/networkextension/nevpnprotocol/3143658-excludelocalnetworks)
|
||||
""", $excludeLocalNetworks) { newValue in
|
||||
await SharedPreferences.excludeLocalNetworks.set(newValue)
|
||||
await restartService()
|
||||
}
|
||||
|
||||
FormToggle("enforceRoutes", """
|
||||
@@ -72,6 +79,7 @@ struct PacketTunnelView: View {
|
||||
[Apple Documentation](https://developer.apple.com/documentation/networkextension/nevpnprotocol/3689459-enforceroutes)
|
||||
""", $enforceRoutes) { newValue in
|
||||
await SharedPreferences.enforceRoutes.set(newValue)
|
||||
await restartService()
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -79,6 +87,7 @@ struct PacketTunnelView: View {
|
||||
FormButton {
|
||||
Task {
|
||||
await SharedPreferences.resetPacketTunnel()
|
||||
await restartService()
|
||||
isLoading = true
|
||||
}
|
||||
} label: {
|
||||
@@ -89,11 +98,23 @@ struct PacketTunnelView: View {
|
||||
}
|
||||
}
|
||||
.navigationTitle("Packet Tunnel")
|
||||
.alert($alert)
|
||||
#if os(iOS)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
#endif
|
||||
}
|
||||
|
||||
private func restartService() async {
|
||||
guard let profile = environments.extensionProfile, profile.status.isConnected else {
|
||||
return
|
||||
}
|
||||
do {
|
||||
try await profile.restart()
|
||||
} catch {
|
||||
alert = AlertState(error: error)
|
||||
}
|
||||
}
|
||||
|
||||
private func loadSettings() async {
|
||||
ignoreMemoryLimit = await SharedPreferences.ignoreMemoryLimit.get()
|
||||
#if !os(tvOS)
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import Libbox
|
||||
import Library
|
||||
import SwiftUI
|
||||
|
||||
public struct ProfileOverrideView: View {
|
||||
@EnvironmentObject private var environments: ExtensionEnvironments
|
||||
@State private var isLoading = true
|
||||
@State private var alert: AlertState?
|
||||
@State private var excludeDefaultRoute = false
|
||||
@State private var autoRouteUseSubRangesByDefault = false
|
||||
@State private var excludeAPNsRoute = false
|
||||
@@ -20,6 +23,7 @@ public struct ProfileOverrideView: View {
|
||||
FormView {
|
||||
FormToggle("Hide VPN Icon", "Append `0.0.0.0/31` and `::/127` to `route_exclude_address` if not exists.", $excludeDefaultRoute) { newValue in
|
||||
await SharedPreferences.excludeDefaultRoute.set(newValue)
|
||||
await reloadService()
|
||||
}
|
||||
|
||||
FormToggle("No Default Route", """
|
||||
@@ -27,15 +31,18 @@ public struct ProfileOverrideView: View {
|
||||
If `<route_address/route_exclude_address>` exists in the configuration, this item will not take effect on the corresponding network (commonly used to resolve HomeKit compatibility issues).
|
||||
""", $autoRouteUseSubRangesByDefault) { newValue in
|
||||
await SharedPreferences.autoRouteUseSubRangesByDefault.set(newValue)
|
||||
await reloadService()
|
||||
}
|
||||
|
||||
FormToggle("Exclude APNs Route", "Append `push.apple.com` to `bypass_domain`, and `17.0.0.0/8` to `route_exclude_address`.", $excludeAPNsRoute) { newValue in
|
||||
await SharedPreferences.excludeAPNsRoute.set(newValue)
|
||||
await reloadService()
|
||||
}
|
||||
|
||||
FormButton {
|
||||
Task {
|
||||
await SharedPreferences.resetProfileOverride()
|
||||
await reloadService()
|
||||
isLoading = true
|
||||
}
|
||||
} label: {
|
||||
@@ -46,11 +53,23 @@ public struct ProfileOverrideView: View {
|
||||
}
|
||||
}
|
||||
.navigationTitle("Profile Override")
|
||||
.alert($alert)
|
||||
#if os(iOS)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
#endif
|
||||
}
|
||||
|
||||
private func reloadService() async {
|
||||
guard let profile = environments.extensionProfile, profile.status.isConnected else {
|
||||
return
|
||||
}
|
||||
do {
|
||||
try LibboxNewStandaloneCommandClient()?.serviceReload()
|
||||
} catch {
|
||||
alert = AlertState(error: error)
|
||||
}
|
||||
}
|
||||
|
||||
private func loadSettings() async {
|
||||
excludeDefaultRoute = await SharedPreferences.excludeDefaultRoute.get()
|
||||
autoRouteUseSubRangesByDefault = await SharedPreferences.autoRouteUseSubRangesByDefault.get()
|
||||
|
||||
@@ -38,9 +38,7 @@ struct StartServiceIntent: AppIntent {
|
||||
}
|
||||
try LibboxNewStandaloneCommandClient()!.serviceReload()
|
||||
} else if extensionProfile.status.isConnected {
|
||||
try await extensionProfile.stop()
|
||||
try await Task.sleep(nanoseconds: UInt64(100 * Double(NSEC_PER_MSEC)))
|
||||
try await extensionProfile.start()
|
||||
try await extensionProfile.restart()
|
||||
} else {
|
||||
try await extensionProfile.start()
|
||||
}
|
||||
@@ -65,9 +63,7 @@ struct RestartServiceIntent: AppIntent {
|
||||
if extensionProfile.status == .connected {
|
||||
try LibboxNewStandaloneCommandClient()!.serviceReload()
|
||||
} else if extensionProfile.status.isConnected {
|
||||
try await extensionProfile.stop()
|
||||
try await Task.sleep(nanoseconds: UInt64(100 * Double(NSEC_PER_MSEC)))
|
||||
try await extensionProfile.start()
|
||||
try await extensionProfile.restart()
|
||||
} else {
|
||||
try await extensionProfile.start()
|
||||
}
|
||||
|
||||
@@ -108,6 +108,19 @@ public class ExtensionProfile: ObservableObject {
|
||||
manager.connection.stopVPNTunnel()
|
||||
}
|
||||
|
||||
public func restart() async throws {
|
||||
try await stop()
|
||||
var waitSeconds = 0
|
||||
while await MainActor.run(body: { status }) != .disconnected {
|
||||
try await Task.sleep(nanoseconds: NSEC_PER_SEC)
|
||||
waitSeconds += 1
|
||||
if waitSeconds >= 5 {
|
||||
throw NSError(domain: "Restart service timeout", code: 0)
|
||||
}
|
||||
}
|
||||
try await start()
|
||||
}
|
||||
|
||||
public static func load() async throws -> ExtensionProfile? {
|
||||
let managers = try await NETunnelProviderManager.loadAllFromPreferences()
|
||||
if managers.isEmpty {
|
||||
|
||||
@@ -923,7 +923,7 @@
|
||||
"If this property is true, the system excludes Apple Push Notification services (APNs) traffic, but only when the **includeAllNetworks** property is also true.\n\n[Apple Documentation](https://developer.apple.com/documentation/networkextension/nevpnprotocol/4140516-excludeapns)" : {
|
||||
"shouldTranslate" : false
|
||||
},
|
||||
"If this property is true, the system excludes cellular services — such as Wi-Fi Calling, MMS, SMS, and Visual Voicemail — but only when the **includeAllNetworks** property is also true. This property doesn’t impact services that use the cellular network only — such as VoLTE — which the system automatically excludes.\n\n[Apple Documentation](https://developer.apple.com/documentation/networkextension/nevpnprotocol/4140517-excludecellularservices)" : {
|
||||
"If this property is true, the system excludes cellular services — such as Wi-Fi Calling, MMS, SMS, and Visual Voicemail — but only when the **includeAllNetworks** property is also true. This property doesn't impact services that use the cellular network only — such as VoLTE — which the system automatically excludes.\n\n[Apple Documentation](https://developer.apple.com/documentation/networkextension/nevpnprotocol/4140517-excludecellularservices)" : {
|
||||
"shouldTranslate" : false
|
||||
},
|
||||
"If this property is true, the system excludes network connections to hosts on the local network — such as AirPlay, AirDrop, and CarPlay — but only when the **includeAllNetworks** or **enforceRoutes** property is also true.\n\n[Apple Documentation](https://developer.apple.com/documentation/networkextension/nevpnprotocol/3143658-excludelocalnetworks)" : {
|
||||
|
||||
Reference in New Issue
Block a user