Fix issues on new systems
This commit is contained in:
@@ -37,7 +37,7 @@ public func FormTextItem(_ name: LocalizedStringKey, _ systemImage: String, @Vie
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func FormItem(_ title: String, @ViewBuilder content: () -> some View) -> some View {
|
public func FormItem(_ title: String, @ViewBuilder content: () -> some View) -> some View {
|
||||||
#if os(iOS) || os(tvOS)
|
#if os(iOS)
|
||||||
HStack {
|
HStack {
|
||||||
Text(title)
|
Text(title)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
@@ -46,6 +46,19 @@ public func FormItem(_ title: String, @ViewBuilder content: () -> some View) ->
|
|||||||
Spacer()
|
Spacer()
|
||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
|
#elseif os(tvOS)
|
||||||
|
HStack {
|
||||||
|
Text(title)
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.lineLimit(1)
|
||||||
|
.layoutPriority(1)
|
||||||
|
Spacer()
|
||||||
|
Spacer()
|
||||||
|
content()
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.lineLimit(1)
|
||||||
|
.layoutPriority(1)
|
||||||
|
}
|
||||||
#elseif os(macOS)
|
#elseif os(macOS)
|
||||||
content()
|
content()
|
||||||
#endif
|
#endif
|
||||||
@@ -115,6 +128,7 @@ public func FormNavigationLink(@ViewBuilder destination: () -> some View, @ViewB
|
|||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItemGroup(placement: .topBarLeading) {
|
ToolbarItemGroup(placement: .topBarLeading) {
|
||||||
BackButton()
|
BackButton()
|
||||||
|
.tint(.accentColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, label: label)
|
}, label: label)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ public struct ConnectionListView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if !os(tvOS)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem {
|
ToolbarItem {
|
||||||
Menu {
|
Menu {
|
||||||
@@ -60,6 +61,7 @@ public struct ConnectionListView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
.searchable(text: $searchText)
|
.searchable(text: $searchText)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import Libbox
|
import Libbox
|
||||||
import Library
|
import Library
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
#if canImport(UIKit)
|
||||||
|
import UIKit
|
||||||
|
#endif
|
||||||
|
|
||||||
public struct ExtensionStatusView: View {
|
public struct ExtensionStatusView: View {
|
||||||
@Environment(\.scenePhase) private var scenePhase
|
@Environment(\.scenePhase) private var scenePhase
|
||||||
@@ -115,6 +118,8 @@ public struct ExtensionStatusView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private struct StatusItem<T>: View where T: View {
|
private struct StatusItem<T>: View where T: View {
|
||||||
|
@Environment(\.colorScheme) private var colorScheme
|
||||||
|
|
||||||
private let title: String
|
private let title: String
|
||||||
@ViewBuilder private let content: () -> T
|
@ViewBuilder private let content: () -> T
|
||||||
|
|
||||||
@@ -148,7 +153,14 @@ public struct ExtensionStatusView: View {
|
|||||||
#elseif os(macOS)
|
#elseif os(macOS)
|
||||||
return Color(nsColor: .textBackgroundColor)
|
return Color(nsColor: .textBackgroundColor)
|
||||||
#elseif os(tvOS)
|
#elseif os(tvOS)
|
||||||
return Color(uiColor: .black)
|
switch colorScheme {
|
||||||
|
case .dark:
|
||||||
|
return Color(uiColor: .black)
|
||||||
|
default:
|
||||||
|
return Color(uiColor: .white)
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return Color.clear
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,6 +108,9 @@ public struct OverviewView: View {
|
|||||||
try LibboxNewStandaloneCommandClient()!.setSystemProxyEnabled(isEnabled)
|
try LibboxNewStandaloneCommandClient()!.setSystemProxyEnabled(isEnabled)
|
||||||
} else {
|
} else {
|
||||||
// Apple BUG: HTTP Proxy cannot be disabled via setTunnelNetworkSettings, so we can only restart the Network Extension
|
// Apple BUG: HTTP Proxy cannot be disabled via setTunnelNetworkSettings, so we can only restart the Network Extension
|
||||||
|
await MainActor.run {
|
||||||
|
reasserting = true
|
||||||
|
}
|
||||||
try await profile.stop()
|
try await profile.stop()
|
||||||
var waitSeconds = 0
|
var waitSeconds = 0
|
||||||
while await profile.status != .disconnected {
|
while await profile.status != .disconnected {
|
||||||
@@ -118,6 +121,9 @@ public struct OverviewView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
try await profile.start()
|
try await profile.start()
|
||||||
|
await MainActor.run {
|
||||||
|
reasserting = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
|
|||||||
@@ -34,17 +34,23 @@ public struct EditProfileView: View {
|
|||||||
FormItem(String(localized: "Path")) {
|
FormItem(String(localized: "Path")) {
|
||||||
TextField("Path", text: $profile.path, prompt: Text("Required"))
|
TextField("Path", text: $profile.path, prompt: Text("Required"))
|
||||||
.multilineTextAlignment(.trailing)
|
.multilineTextAlignment(.trailing)
|
||||||
|
#if !os(macOS)
|
||||||
|
.keyboardType(.asciiCapableNumberPad)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} else if profile.type == .remote {
|
} else if profile.type == .remote {
|
||||||
FormItem(String(localized: "URL")) {
|
FormItem(String(localized: "URL")) {
|
||||||
TextField("URL", text: $profile.remoteURL.unwrapped(""), prompt: Text("Required"))
|
TextField("URL", text: $profile.remoteURL.unwrapped(""), prompt: Text("Required"))
|
||||||
.multilineTextAlignment(.trailing)
|
.multilineTextAlignment(.trailing)
|
||||||
|
#if !os(macOS)
|
||||||
|
.keyboardType(.URL)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
Toggle("Auto Update", isOn: $profile.autoUpdate)
|
Toggle("Auto Update", isOn: $profile.autoUpdate)
|
||||||
FormItem(String(localized: "Auto Update Interval")) {
|
FormItem(String(localized: "Auto Update Interval")) {
|
||||||
TextField("Auto Update Interval", text: $profile.autoUpdateInterval.stringBinding(defaultValue: 60), prompt: Text("In Minutes"))
|
TextField("Auto Update Interval", text: $profile.autoUpdateInterval.stringBinding(defaultValue: 60), prompt: Text("In Minutes"))
|
||||||
.multilineTextAlignment(.trailing)
|
.multilineTextAlignment(.trailing)
|
||||||
#if os(iOS)
|
#if !os(macOS)
|
||||||
.keyboardType(.numberPad)
|
.keyboardType(.numberPad)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ public struct NewProfileView: View {
|
|||||||
|
|
||||||
@State private var isSaving = false
|
@State private var isSaving = false
|
||||||
@State private var profileName = ""
|
@State private var profileName = ""
|
||||||
@State private var profileType = ProfileType.local
|
#if !os(tvOS)
|
||||||
|
@State private var profileType = ProfileType.local
|
||||||
|
#else
|
||||||
|
@State private var profileType = ProfileType.remote
|
||||||
|
#endif
|
||||||
@State private var fileImport = false
|
@State private var fileImport = false
|
||||||
@State private var fileURL: URL!
|
@State private var fileURL: URL!
|
||||||
@State private var remotePath = ""
|
@State private var remotePath = ""
|
||||||
@@ -79,17 +83,23 @@ public struct NewProfileView: View {
|
|||||||
FormItem(String(localized: "Path")) {
|
FormItem(String(localized: "Path")) {
|
||||||
TextField("Path", text: $remotePath, prompt: Text("Required"))
|
TextField("Path", text: $remotePath, prompt: Text("Required"))
|
||||||
.multilineTextAlignment(.trailing)
|
.multilineTextAlignment(.trailing)
|
||||||
|
#if !os(macOS)
|
||||||
|
.keyboardType(.asciiCapableNumberPad)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} else if profileType == .remote {
|
} else if profileType == .remote {
|
||||||
FormItem(String(localized: "URL")) {
|
FormItem(String(localized: "URL")) {
|
||||||
TextField("URL", text: $remotePath, prompt: Text("Required"))
|
TextField("URL", text: $remotePath, prompt: Text("Required"))
|
||||||
.multilineTextAlignment(.trailing)
|
.multilineTextAlignment(.trailing)
|
||||||
|
#if !os(macOS)
|
||||||
|
.keyboardType(.URL)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
Toggle("Auto Update", isOn: $autoUpdate)
|
Toggle("Auto Update", isOn: $autoUpdate)
|
||||||
FormItem(String(localized: "Auto Update Interval")) {
|
FormItem(String(localized: "Auto Update Interval")) {
|
||||||
TextField("Auto Update Interval", text: $autoUpdateInterval.stringBinding(defaultValue: 60), prompt: Text("In Minutes"))
|
TextField("Auto Update Interval", text: $autoUpdateInterval.stringBinding(defaultValue: 60), prompt: Text("In Minutes"))
|
||||||
.multilineTextAlignment(.trailing)
|
.multilineTextAlignment(.trailing)
|
||||||
#if os(iOS)
|
#if !os(macOS)
|
||||||
.keyboardType(.numberPad)
|
.keyboardType(.numberPad)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,14 +137,20 @@ public struct ProfileView: View {
|
|||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .navigationBarTrailing) {
|
ToolbarItem(placement: .navigationBarTrailing) {
|
||||||
if editMode == .inactive {
|
if editMode == .inactive {
|
||||||
Button("Edit") {
|
Button(action: {
|
||||||
editMode = .active
|
editMode = .active
|
||||||
|
}) {
|
||||||
|
Image(systemName: "square.and.pencil")
|
||||||
}
|
}
|
||||||
|
.tint(.accentColor)
|
||||||
.disabled(profileList.isEmpty)
|
.disabled(profileList.isEmpty)
|
||||||
} else {
|
} else {
|
||||||
Button("Done") {
|
Button(action: {
|
||||||
editMode = .inactive
|
editMode = .inactive
|
||||||
|
}) {
|
||||||
|
Image(systemName: "checkmark.square.fill")
|
||||||
}
|
}
|
||||||
|
.tint(.accentColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ public struct ServiceLogView: View {
|
|||||||
Label("Delete", systemImage: "trash.fill")
|
Label("Delete", systemImage: "trash.fill")
|
||||||
#else
|
#else
|
||||||
Image(systemName: "trash.fill")
|
Image(systemName: "trash.fill")
|
||||||
|
.tint(.red)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user