add
This commit is contained in:
@@ -1,280 +0,0 @@
|
||||
import Libbox
|
||||
import Network
|
||||
import Library
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
public struct GroupItemView: View {
|
||||
private let _group: Binding<OutboundGroup>
|
||||
private var group: OutboundGroup {
|
||||
_group.wrappedValue
|
||||
}
|
||||
|
||||
private let item: OutboundGroupItem
|
||||
|
||||
public init(_ group: Binding<OutboundGroup>, _ item: OutboundGroupItem) {
|
||||
_group = group
|
||||
self.item = item
|
||||
}
|
||||
|
||||
@State private var alert: Alert?
|
||||
|
||||
|
||||
/* old style
|
||||
public var body: some View {
|
||||
Button {
|
||||
if group.selectable, group.selected != item.tag {
|
||||
Task {
|
||||
await selectOutbound()
|
||||
UserDefaults.standard.setValue("\(item.tag)", forKey: "selectedNode")
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
HStack {
|
||||
VStack {
|
||||
HStack {
|
||||
Text(item.tag)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.foreground)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.tail)
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
Spacer(minLength: 8)
|
||||
HStack {
|
||||
Text(item.displayType)
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
}
|
||||
Spacer(minLength: 0)
|
||||
VStack {
|
||||
if group.selected == item.tag {
|
||||
Image(systemName: "checkmark.circle.fill")
|
||||
.foregroundStyle(Color.accentColor)
|
||||
}
|
||||
Spacer(minLength: 0)
|
||||
if item.urlTestDelay > 0 {
|
||||
Text(item.delayString)
|
||||
.font(.caption)
|
||||
.foregroundColor(item.delayColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#if !os(tvOS)
|
||||
.buttonStyle(.borderless)
|
||||
.padding(EdgeInsets(top: 10, leading: 13, bottom: 10, trailing: 13))
|
||||
.background(backgroundColor)
|
||||
.cornerRadius(10)
|
||||
#endif
|
||||
.alertBinding($alert)
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
func testPing(to server: String, port: Int, completion: @escaping (TimeInterval?) -> Void) {
|
||||
let startTime = Date()
|
||||
|
||||
let connection = NWConnection(host: NWEndpoint.Host(server), port: NWEndpoint.Port(rawValue: UInt16(port))!, using: .tcp)
|
||||
|
||||
connection.stateUpdateHandler = { state in
|
||||
switch state {
|
||||
case .ready:
|
||||
// 连接成功,计算响应时间
|
||||
let pingTime = Date().timeIntervalSince(startTime)
|
||||
completion(pingTime)
|
||||
connection.cancel() // 连接完成后取消
|
||||
case .failed(_):
|
||||
completion(nil)
|
||||
connection.cancel()
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 启动连接
|
||||
connection.start(queue: .global())
|
||||
}
|
||||
|
||||
|
||||
|
||||
public var body: some View {
|
||||
Button {
|
||||
print("\(group.selectable) group.selected - item.tag: >>> "+group.selected + " " + item.tag)
|
||||
// print(item.toString)
|
||||
|
||||
if group.selectable, group.selected != item.tag {
|
||||
|
||||
|
||||
// var item = _group.wrappedValue.items[index] // Make a mutable copy of the item
|
||||
|
||||
Task {
|
||||
|
||||
|
||||
if let server = item.server ,let port = item.server_port{
|
||||
//说明是第一次查看节点列表 然后 点击列表
|
||||
|
||||
testPing(to: server, port: port) { pingTime in
|
||||
if let ping = pingTime {
|
||||
print("Ping 时间: \(ping) 秒")
|
||||
|
||||
Task{
|
||||
await pingOutbound(tag: item.tag,pingtime: UInt16((pingTime ?? 0)*1000))
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
print("连接超时")
|
||||
}
|
||||
}
|
||||
|
||||
UserDefaults.standard.setValue("\(item.tag)", forKey: "selectedNode")
|
||||
await selectOutbound()
|
||||
|
||||
}else{
|
||||
|
||||
await selectOutbound()
|
||||
|
||||
UserDefaults.standard.setValue("\(item.tag)", forKey: "selectedNode")
|
||||
|
||||
//切换节点后重启服务
|
||||
|
||||
await restartVPNServer()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} label: {
|
||||
VStack(spacing: 2) {
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
HStack {
|
||||
// Image(server.name)
|
||||
// .resizable()
|
||||
// .aspectRatio(contentMode: .fit)
|
||||
// .frame(width: 20, height: 20)
|
||||
|
||||
Text(item.tag)
|
||||
.font(.subheadline)
|
||||
.fontWeight(.semibold)
|
||||
.foregroundColor(.white)
|
||||
}
|
||||
|
||||
Label {
|
||||
Text(item.type)
|
||||
// Text(item.urlTestDelay <= 3000 ? "在线可用" : "不可用")
|
||||
} icon: {
|
||||
// Image(systemName: item.urlTestDelay <= 3000 ? "checkmark" : "xmark")
|
||||
} .foregroundColor(.gray)
|
||||
// .foregroundColor(item.urlTestDelay <= 3000 ?.green : .red)
|
||||
.font(.caption2)
|
||||
}
|
||||
|
||||
Spacer(minLength: 10)
|
||||
|
||||
// Change Server Button...
|
||||
|
||||
VStack {
|
||||
if group.selected == item.tag {
|
||||
Image(systemName: "checkmark.circle.fill")
|
||||
.foregroundStyle(Color.accentColor)
|
||||
}
|
||||
Spacer(minLength: 0)
|
||||
if item.urlTestDelay > 0 {
|
||||
Text(item.delayString)
|
||||
.font(.caption)
|
||||
.foregroundColor(item.delayColor)
|
||||
}else{
|
||||
//正在测速
|
||||
Text("...")
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(height: 50)
|
||||
.padding(.horizontal)
|
||||
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
#if !os(tvOS)
|
||||
.buttonStyle(.borderless)
|
||||
// .padding(EdgeInsets(top: 10, leading: 13, bottom: 10, trailing: 13))
|
||||
// .background(backgroundColor)
|
||||
// .cornerRadius(10)
|
||||
#endif
|
||||
.alertBinding($alert)
|
||||
}
|
||||
|
||||
|
||||
private nonisolated func pingOutbound(tag: String,pingtime: UInt16) async {
|
||||
let newGroup = await group
|
||||
|
||||
let newitems = newGroup.items.map { item in
|
||||
var mutableItem = item
|
||||
if (item.tag == tag) {
|
||||
mutableItem.urlTestDelay = pingtime
|
||||
}
|
||||
return mutableItem
|
||||
}
|
||||
|
||||
let newOut = OutboundGroup(tag: newGroup.tag, type: newGroup.type, selected:tag, selectable: newGroup.selectable, isExpand: newGroup.isExpand, items: newitems)
|
||||
|
||||
await MainActor.run { [newOut] in
|
||||
_group.wrappedValue = newOut
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private nonisolated func selectOutbound() async {
|
||||
do {
|
||||
try await LibboxNewStandaloneCommandClient()!.selectOutbound(group.tag, outboundTag: item.tag)
|
||||
var newGroup = await group
|
||||
newGroup.selected = item.tag
|
||||
await MainActor.run { [newGroup] in
|
||||
_group.wrappedValue = newGroup
|
||||
}
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
alert = Alert(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private nonisolated func setSystemProxyEnabled(_ isEnabled: Bool) async {
|
||||
do {
|
||||
try LibboxNewStandaloneCommandClient()!.setSystemProxyEnabled(isEnabled)
|
||||
await SharedPreferences.systemProxyEnabled.set(isEnabled)
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
alert = Alert(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private nonisolated func restartVPNServer() async {
|
||||
do {
|
||||
try LibboxNewStandaloneCommandClient()!.serviceReload()
|
||||
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
alert = Alert(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var backgroundColor: Color {
|
||||
#if os(iOS)
|
||||
return Color(uiColor: .secondarySystemGroupedBackground)
|
||||
#elseif os(macOS)
|
||||
return Color(nsColor: .textBackgroundColor)
|
||||
#elseif os(tvOS)
|
||||
return Color.black
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user