Add preview support
This commit is contained in:
@@ -36,7 +36,7 @@ public struct ActiveDashboardView: View {
|
||||
} else {
|
||||
VStack {
|
||||
#if os(iOS)
|
||||
if profile.status.isConnected {
|
||||
if ApplicationLibrary.inPreview || profile.status.isConnected {
|
||||
ExtensionStatusView()
|
||||
.listStyle(.automatic)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
@@ -53,7 +53,7 @@ public struct ActiveDashboardView: View {
|
||||
}
|
||||
}
|
||||
#else
|
||||
if profile.status.isConnected {
|
||||
if ApplicationLibrary.inPreview || profile.status.isConnected {
|
||||
ExtensionStatusView()
|
||||
}
|
||||
FormView {
|
||||
@@ -74,7 +74,7 @@ public struct ActiveDashboardView: View {
|
||||
await switchProfile(selectedProfileID!)
|
||||
}
|
||||
}
|
||||
.disabled(!profile.status.isSwitchable || reasserting)
|
||||
.disabled(!ApplicationLibrary.inPreview && (!profile.status.isSwitchable || reasserting))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,24 +115,32 @@ public struct ActiveDashboardView: View {
|
||||
defer {
|
||||
isLoading = false
|
||||
}
|
||||
do {
|
||||
profileList = try ProfileManager.list()
|
||||
} catch {
|
||||
errorMessage = error.localizedDescription
|
||||
errorPresented = true
|
||||
return
|
||||
}
|
||||
if profileList.isEmpty {
|
||||
return
|
||||
}
|
||||
if ApplicationLibrary.inPreview {
|
||||
profileList = [
|
||||
Profile(id: 0, name: "profile local", type: .local, path: ""),
|
||||
Profile(id: 1, name: "profile remote", type: .remote, path: "", lastUpdated: Date(timeIntervalSince1970: 0)),
|
||||
]
|
||||
selectedProfileID = 0
|
||||
} else {
|
||||
do {
|
||||
profileList = try ProfileManager.list()
|
||||
} catch {
|
||||
errorMessage = error.localizedDescription
|
||||
errorPresented = true
|
||||
return
|
||||
}
|
||||
if profileList.isEmpty {
|
||||
return
|
||||
}
|
||||
|
||||
selectedProfileID = SharedPreferences.selectedProfileID
|
||||
if profileList.filter({ profile in
|
||||
profile.id == selectedProfileID
|
||||
})
|
||||
.isEmpty {
|
||||
selectedProfileID = profileList[0].id!
|
||||
SharedPreferences.selectedProfileID = selectedProfileID
|
||||
selectedProfileID = SharedPreferences.selectedProfileID
|
||||
if profileList.filter({ profile in
|
||||
profile.id == selectedProfileID
|
||||
})
|
||||
.isEmpty {
|
||||
selectedProfileID = profileList[0].id!
|
||||
SharedPreferences.selectedProfileID = selectedProfileID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@ public struct DashboardView: View {
|
||||
|
||||
public var body: some View {
|
||||
viewBuilder {
|
||||
if let profile = extensionProfile.wrappedValue {
|
||||
if ApplicationLibrary.inPreview {
|
||||
ActiveDashboardView()
|
||||
} else if let profile = extensionProfile.wrappedValue {
|
||||
ActiveDashboardView().environmentObject(profile)
|
||||
} else {
|
||||
FormView {
|
||||
|
||||
@@ -18,7 +18,16 @@ public struct ExtensionStatusView: View {
|
||||
viewBuilder {
|
||||
VStack {
|
||||
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: columnCount), alignment: .leading) {
|
||||
if let message {
|
||||
if ApplicationLibrary.inPreview {
|
||||
StatusItem("Memory", "6.4 MiB")
|
||||
StatusItem("Goroutines", "89")
|
||||
StatusItem("Inbound Connections", "34")
|
||||
StatusItem("Outbound Connections", "28")
|
||||
StatusItem("Uplink", "38 B/s")
|
||||
StatusItem("Downlink", "249 MiB/s")
|
||||
StatusItem("Uplink Total", "52 MiB")
|
||||
StatusItem("Downlink Total", "5.6 GiB")
|
||||
} else if let message {
|
||||
StatusItem("Memory", LibboxFormatBytes(message.memory))
|
||||
StatusItem("Goroutines", "\(message.goroutines)")
|
||||
if message.trafficAvailable {
|
||||
|
||||
@@ -9,7 +9,18 @@ public struct StartStopButton: View {
|
||||
|
||||
public var body: some View {
|
||||
viewBuilder {
|
||||
if let profile = extensionProfile.wrappedValue {
|
||||
if ApplicationLibrary.inPreview {
|
||||
#if os(iOS)
|
||||
Toggle(isOn: .constant(true)) {
|
||||
Text("Enabled")
|
||||
}
|
||||
#elseif os(macOS)
|
||||
Button(action: {}, label: {
|
||||
Label("Stop", systemImage: "stop.fill")
|
||||
})
|
||||
#endif
|
||||
|
||||
} else if let profile = extensionProfile.wrappedValue {
|
||||
Button0(profile)
|
||||
} else {
|
||||
#if os(iOS)
|
||||
@@ -17,6 +28,7 @@ public struct StartStopButton: View {
|
||||
Text("Enabled")
|
||||
}
|
||||
#elseif os(macOS)
|
||||
|
||||
Button(action: {}, label: {
|
||||
Label("Start", systemImage: "play.fill")
|
||||
})
|
||||
|
||||
@@ -43,9 +43,24 @@ public struct GroupListView: View {
|
||||
}
|
||||
|
||||
private func doReload() {
|
||||
connectTask?.cancel()
|
||||
connectTask = Task.detached {
|
||||
await connect()
|
||||
if ApplicationLibrary.inPreview {
|
||||
groups = [
|
||||
OutboundGroup(tag: "my_group", type: "selector", selected: "server", selectable: true, items: [
|
||||
OutboundGroupItem(tag: "server", type: "Shadowsocks", urlTestTime: .now, urlTestDelay: 12),
|
||||
OutboundGroupItem(tag: "server2", type: "WireGuard", urlTestTime: .now, urlTestDelay: 34),
|
||||
OutboundGroupItem(tag: "auto", type: "URLTest", urlTestTime: .now, urlTestDelay: 100),
|
||||
]),
|
||||
OutboundGroup(tag: "group2", type: "urltest", selected: "client", selectable: false, items:
|
||||
(0 ..< 234).map { index in
|
||||
OutboundGroupItem(tag: "client\(index)", type: "Shadowsocks", urlTestTime: .now, urlTestDelay: UInt16(100 + index * 10))
|
||||
}),
|
||||
]
|
||||
isLoading = false
|
||||
} else {
|
||||
connectTask?.cancel()
|
||||
connectTask = Task.detached {
|
||||
await connect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,14 +27,26 @@ public class LogClient: ObservableObject {
|
||||
}
|
||||
|
||||
public func reconnect() {
|
||||
if isConnected {
|
||||
return
|
||||
}
|
||||
if let connectTask {
|
||||
connectTask.cancel()
|
||||
}
|
||||
connectTask = Task.detached {
|
||||
await self.connect()
|
||||
if ApplicationLibrary.inPreview {
|
||||
logList = [
|
||||
"(packet-tunnel) log server started",
|
||||
"INFO[0000] router: loaded geoip database: 250 codes",
|
||||
"INFO[0000] router: loaded geosite database: 1400 codes",
|
||||
"INFO[0000] router: updated default interface en0, index 11",
|
||||
"inbound/tun[0]: started at utun3",
|
||||
"sing-box started (1.666s)",
|
||||
]
|
||||
isConnected = true
|
||||
} else {
|
||||
if isConnected {
|
||||
return
|
||||
}
|
||||
if let connectTask {
|
||||
connectTask.cancel()
|
||||
}
|
||||
connectTask = Task.detached {
|
||||
await self.connect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,11 +61,15 @@ public struct LogView: View {
|
||||
}
|
||||
|
||||
private func connectLog() {
|
||||
guard let profile = extensionProfile.wrappedValue else {
|
||||
return
|
||||
}
|
||||
if profile.status.isConnected, !logClient.isConnected {
|
||||
if ApplicationLibrary.inPreview {
|
||||
logClient.reconnect()
|
||||
} else {
|
||||
guard let profile = extensionProfile.wrappedValue else {
|
||||
return
|
||||
}
|
||||
if profile.status.isConnected, !logClient.isConnected {
|
||||
logClient.reconnect()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,15 +70,12 @@ public extension NavigationPage {
|
||||
}
|
||||
|
||||
func visible(_ profile: ExtensionProfile?) -> Bool {
|
||||
if ApplicationLibrary.inPreview {
|
||||
return true
|
||||
}
|
||||
switch self {
|
||||
case .groups:
|
||||
return profile?.status.isConnectedStrict == true
|
||||
case .profiles, .settings:
|
||||
#if os(iOS)
|
||||
return profile?.status.isConnected != true
|
||||
#else
|
||||
fallthrough
|
||||
#endif
|
||||
default:
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -165,6 +165,7 @@ public struct NewProfileView: View {
|
||||
|
||||
var savePath = ""
|
||||
var remoteURL: String? = nil
|
||||
var lastUpdated: Date? = nil
|
||||
|
||||
if profileType == .local {
|
||||
let profileConfigDirectory = FilePath.sharedDirectory.appendingPathComponent("configs", isDirectory: true)
|
||||
@@ -217,6 +218,7 @@ public struct NewProfileView: View {
|
||||
try remoteContent.write(to: profileConfig, atomically: true, encoding: .utf8)
|
||||
savePath = profileConfig.relativePath
|
||||
remoteURL = remotePath
|
||||
lastUpdated = .now
|
||||
}
|
||||
try ProfileManager.create(Profile(name: profileName, type: profileType, path: savePath, remoteURL: remoteURL))
|
||||
}
|
||||
|
||||
@@ -169,12 +169,19 @@ public struct ProfileView: View {
|
||||
defer {
|
||||
isLoading = false
|
||||
}
|
||||
do {
|
||||
profileList = try ProfileManager.list()
|
||||
} catch {
|
||||
errorMessage = error.localizedDescription
|
||||
errorPresented = true
|
||||
return
|
||||
if ApplicationLibrary.inPreview {
|
||||
profileList = [
|
||||
Profile(id: 0, name: "profile local", type: .local, path: ""),
|
||||
Profile(id: 1, name: "profile remote", type: .remote, path: "", lastUpdated: Date(timeIntervalSince1970: 0)),
|
||||
]
|
||||
} else {
|
||||
do {
|
||||
profileList = try ProfileManager.list()
|
||||
} catch {
|
||||
errorMessage = error.localizedDescription
|
||||
errorPresented = true
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -148,10 +148,16 @@ public struct SettingView: View {
|
||||
#endif
|
||||
disableMemoryLimit = SharedPreferences.disableMemoryLimit
|
||||
version = LibboxVersion()
|
||||
dataSize = "Loading..."
|
||||
isLoading = false
|
||||
dataSize = (try? FilePath.workingDirectory.formattedSize()) ?? "Unknown"
|
||||
taiwanFlagAvailable = !DeviceCensorship.isChinaDevice()
|
||||
if ApplicationLibrary.inPreview {
|
||||
dataSize = LibboxFormatBytes(1024 * 1024 * 10)
|
||||
taiwanFlagAvailable = true
|
||||
isLoading = false
|
||||
} else {
|
||||
dataSize = "Loading..."
|
||||
taiwanFlagAvailable = !DeviceCensorship.isChinaDevice()
|
||||
isLoading = false
|
||||
dataSize = (try? FilePath.workingDirectory.formattedSize()) ?? "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
private func clearWorkingDirectory() {
|
||||
|
||||
Reference in New Issue
Block a user