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
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
import Libbox
|
||||
import Library
|
||||
import SwiftUI
|
||||
|
||||
|
||||
|
||||
public struct GroupListView: View {
|
||||
@Environment(\.scenePhase) private var scenePhase
|
||||
@State private var isLoading = true
|
||||
@StateObject private var commandClient = CommandClient(.groups)
|
||||
@State private var groups: [OutboundGroup] = []
|
||||
|
||||
public init() {
|
||||
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
VStack {
|
||||
if isLoading {
|
||||
Spacer().frame(height: 20)
|
||||
Text("请开启VPN后查看节点数据").foregroundColor(.red)
|
||||
} else if !groups.isEmpty {
|
||||
ScrollView {
|
||||
VStack {
|
||||
|
||||
ForEach(groups, id: \.hashValue) { it in
|
||||
GroupView(it)
|
||||
}
|
||||
}.padding() //.background(Color.gray.opacity(0.1))
|
||||
}
|
||||
} else {
|
||||
Spacer().frame(height: 20)
|
||||
ProgressView()
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
connect()
|
||||
}
|
||||
.onDisappear {
|
||||
commandClient.disconnect()
|
||||
}
|
||||
.onChangeCompat(of: scenePhase) { newValue in
|
||||
if newValue == .active {
|
||||
commandClient.connect()
|
||||
} else {
|
||||
commandClient.disconnect()
|
||||
}
|
||||
}
|
||||
.onReceive(commandClient.$groups, perform: { groups in
|
||||
if let groups {
|
||||
setGroups(groups)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private func connect() {
|
||||
if ApplicationLibrary.inPreview {
|
||||
groups = [
|
||||
OutboundGroup(tag: "my_group", type: "selector", selected: "server", selectable: true, isExpand: 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: true, isExpand: false, items:
|
||||
(0 ..< 234).map { index in
|
||||
OutboundGroupItem(tag: "client\(index)", type: "Shadowsocks", urlTestTime: .now, urlTestDelay: UInt16(100 + index * 10))
|
||||
}),
|
||||
]
|
||||
isLoading = false
|
||||
} else {
|
||||
|
||||
#if targetEnvironment(simulator)
|
||||
groups = [
|
||||
OutboundGroup(tag: "my_group", type: "selector", selected: "server", selectable: true, isExpand: true, items: [
|
||||
OutboundGroupItem(tag: "🇭🇰🇭🇰Hong Kong 01", type: "Shadowsocks", urlTestTime: .now, urlTestDelay: 12),
|
||||
OutboundGroupItem(tag: "🇭🇰🇭🇰Hong Kong 03", type: "WireGuard", urlTestTime: .now, urlTestDelay: 34),
|
||||
OutboundGroupItem(tag: "🇭🇰🇭🇰Hong Kong 04", type: "URLTest", urlTestTime: .now, urlTestDelay: 100),
|
||||
OutboundGroupItem(tag: "🇯🇵🇯🇵🇯🇵Japan 01", type: "Shadowsocks", urlTestTime: .now, urlTestDelay: 12),
|
||||
OutboundGroupItem(tag: "🇯🇵🇯🇵Japan Kong 01", type: "Shadowsocks", urlTestTime: .now, urlTestDelay: 112),
|
||||
OutboundGroupItem(tag: "🇯🇵🇯🇵Japan Kong 02", type: "Shadowsocks", urlTestTime: .now, urlTestDelay: 1222),
|
||||
OutboundGroupItem(tag: "🇯🇵🇯🇵Japan Kong 03", type: "Shadowsocks", urlTestTime: .now, urlTestDelay: 4412),
|
||||
OutboundGroupItem(tag: "🇯🇵🇯🇵Japan Kong 04", type: "Shadowsocks", urlTestTime: .now, urlTestDelay: 512),
|
||||
]),
|
||||
]
|
||||
isLoading = false
|
||||
#endif
|
||||
commandClient.connect()
|
||||
}
|
||||
}
|
||||
|
||||
private func setGroups(_ goGroups: [LibboxOutboundGroup]) {
|
||||
|
||||
var groups = [OutboundGroup]()
|
||||
if let goGroup = goGroups.first {
|
||||
goGroup.isExpand = true
|
||||
var items = [OutboundGroupItem]()
|
||||
let itemIterator = goGroup.getItems()!
|
||||
while itemIterator.hasNext() {
|
||||
let goItem = itemIterator.next()!
|
||||
items.append(OutboundGroupItem(tag: goItem.tag, type: goItem.type, urlTestTime: Date(timeIntervalSince1970: Double(goItem.urlTestTime)), urlTestDelay: UInt16(goItem.urlTestDelay)))
|
||||
}
|
||||
groups.append(OutboundGroup(tag: goGroup.tag, type: goGroup.type, selected: goGroup.selected, selectable: goGroup.selectable, isExpand: goGroup.isExpand, items: items))
|
||||
UserDefaults.standard.setValue("\(goGroup.tag)", forKey: "goGrouptag")
|
||||
}
|
||||
|
||||
/* 原有的全部显示逻辑
|
||||
var groups = [OutboundGroup]()
|
||||
for goGroup in goGroups {
|
||||
print(goGroup.tag)
|
||||
//默认设置为开启
|
||||
goGroup.isExpand = true
|
||||
var items = [OutboundGroupItem]()
|
||||
let itemIterator = goGroup.getItems()!
|
||||
while itemIterator.hasNext() {
|
||||
let goItem = itemIterator.next()!
|
||||
items.append(OutboundGroupItem(tag: goItem.tag, type: goItem.type, urlTestTime: Date(timeIntervalSince1970: Double(goItem.urlTestTime)), urlTestDelay: UInt16(goItem.urlTestDelay)))
|
||||
}
|
||||
groups.append(OutboundGroup(tag: goGroup.tag, type: goGroup.type, selected: goGroup.selected, selectable: goGroup.selectable, isExpand: goGroup.isExpand, items: items))
|
||||
}*/
|
||||
self.groups = groups
|
||||
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
import Libbox
|
||||
import Library
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
public struct GroupView: View {
|
||||
@State private var group: OutboundGroup
|
||||
@State private var geometryWidth: CGFloat = 300
|
||||
@State private var alert: Alert?
|
||||
|
||||
|
||||
public init(_ group: OutboundGroup) {
|
||||
_group = State(initialValue: group)
|
||||
}
|
||||
|
||||
private var title: some View {
|
||||
HStack {
|
||||
// Text(group.tag)
|
||||
// .font(.headline)
|
||||
//Text()
|
||||
Text(group.tag)
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
Text("\(group.items.count)")
|
||||
.font(.subheadline)
|
||||
.padding(EdgeInsets(top: 2, leading: 4, bottom: 2, trailing: 4))
|
||||
.background(Color.gray.opacity(0.5))
|
||||
.cornerRadius(4)
|
||||
Button {
|
||||
group.isExpand = !group.isExpand
|
||||
Task {
|
||||
await setGroupExpand()
|
||||
}
|
||||
} label: {
|
||||
HStack{
|
||||
|
||||
if group.isExpand {
|
||||
Image(systemName: "arrow.down.to.line")
|
||||
Text("收起").font(.subheadline)
|
||||
} else {
|
||||
Image(systemName: "arrow.up.to.line")
|
||||
Text("展开").font(.subheadline)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#if os(macOS) || os(tvOS)
|
||||
.buttonStyle(.plain)
|
||||
#endif
|
||||
Button {
|
||||
Task {
|
||||
await doURLTest()
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "bolt.fill")
|
||||
Text("测速").font(.subheadline)
|
||||
}
|
||||
#if os(macOS) || os(tvOS)
|
||||
.buttonStyle(.plain)
|
||||
#endif
|
||||
}
|
||||
.alertBinding($alert)
|
||||
.padding([.top, .bottom], 10)
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
Section {
|
||||
if group.isExpand {
|
||||
LazyVGrid(columns: Array(repeating: GridItem(.flexible()),
|
||||
count: explandColumnCount()))
|
||||
{
|
||||
ForEach(group.items, id: \.tag) { it in
|
||||
GroupItemView($group, it)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
VStack(spacing: 5) {
|
||||
ForEach(Array(itemGroups.enumerated()), id: \.offset) { items in
|
||||
HStack(spacing: 5) {
|
||||
ForEach(items.element, id: \.tag) { it in
|
||||
ZStack {
|
||||
Rectangle()
|
||||
.fill(it.delayColor)
|
||||
if it.tag == group.selected {
|
||||
Rectangle()
|
||||
.fill(Color.white)
|
||||
#if !os(tvOS)
|
||||
.frame(width: 5, height: 5)
|
||||
#else
|
||||
.frame(width: 15, height: 15)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if !os(tvOS)
|
||||
.frame(width: 10, height: 10)
|
||||
#else
|
||||
.frame(width: 30, height: 30)
|
||||
#endif
|
||||
}
|
||||
}.frame(maxWidth: .infinity, alignment: .topLeading)
|
||||
}
|
||||
}
|
||||
}
|
||||
} header: {
|
||||
//title .frame(maxWidth: .infinity, alignment: .topLeading)
|
||||
}
|
||||
.background {
|
||||
/* GeometryReader { geometry in
|
||||
Rectangle()
|
||||
.fill(.clear)
|
||||
.frame(height: 1)
|
||||
.onChangeCompat(of: geometry.size.width) { newValue in
|
||||
geometryWidth = newValue
|
||||
}
|
||||
.onAppear {
|
||||
geometryWidth = geometry.size.width
|
||||
}
|
||||
}.padding() */
|
||||
}.padding(.leading,-18.0)
|
||||
}
|
||||
|
||||
private var itemGroups: [[OutboundGroupItem]] {
|
||||
let count: Int
|
||||
#if os(tvOS)
|
||||
count = Int(Int(geometryWidth) / 40)
|
||||
#else
|
||||
count = Int(Int(geometryWidth) / 20)
|
||||
#endif
|
||||
if count == 0 {
|
||||
return [group.items]
|
||||
} else {
|
||||
return group.items.chunked(
|
||||
into: count
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private func explandColumnCount() -> Int {
|
||||
let standardCount = Int(Int(geometryWidth) / 180)
|
||||
#if os(iOS)
|
||||
return standardCount < 2 ? 1 : standardCount
|
||||
#elseif os(tvOS)
|
||||
return 4
|
||||
#else
|
||||
return standardCount < 1 ? 1 : standardCount
|
||||
#endif
|
||||
}
|
||||
|
||||
private nonisolated func doURLTest() async {
|
||||
do {
|
||||
try await LibboxNewStandaloneCommandClient()!.urlTest(group.tag)
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
alert = Alert(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private nonisolated func setGroupExpand() async {
|
||||
do {
|
||||
try await LibboxNewStandaloneCommandClient()!.setGroupExpand(group.tag, isExpand: group.isExpand)
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
alert = Alert(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension Array {
|
||||
func chunked(into size: Int) -> [[Element]] {
|
||||
stride(from: 0, to: count, by: size).map {
|
||||
Array(self[$0 ..< Swift.min($0 + size, count)])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
//
|
||||
// NodesListView.swift
|
||||
// ApplicationLibrary
|
||||
//
|
||||
// Created by Mac on 2024/10/26.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
//NodesListView
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
import Foundation
|
||||
import Libbox
|
||||
import SwiftUI
|
||||
|
||||
public struct OutboundGroup: Codable {
|
||||
let tag: String
|
||||
let type: String
|
||||
var selected: String
|
||||
let selectable: Bool
|
||||
var isExpand: Bool
|
||||
let items: [OutboundGroupItem]
|
||||
|
||||
|
||||
|
||||
|
||||
var hashValue: Int {
|
||||
var value = tag.hashValue
|
||||
(value, _) = value.addingReportingOverflow(selected.hashValue)
|
||||
for item in items {
|
||||
(value, _) = value.addingReportingOverflow(item.urlTestTime.hashValue)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
public init(tag: String, type: String, selected: String, selectable: Bool,isExpand: Bool,items: [OutboundGroupItem] ) {
|
||||
self.tag = tag
|
||||
self.type = type
|
||||
self.selected = selected
|
||||
self.selectable = selectable
|
||||
self.isExpand = isExpand
|
||||
self.items = items
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public extension OutboundGroup {
|
||||
|
||||
var newhashValue: Int {
|
||||
var value = tag.hashValue
|
||||
(value, _) = value.addingReportingOverflow(selected.hashValue)
|
||||
for item in items {
|
||||
(value, _) = value.addingReportingOverflow(item.urlTestTime.hashValue)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public extension OutboundGroup {
|
||||
var displayType: String {
|
||||
LibboxProxyDisplayType(type)
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import Foundation
|
||||
import Libbox
|
||||
import SwiftUI
|
||||
|
||||
public struct OutboundGroupItem: Codable {
|
||||
public let tag: String
|
||||
public let type: String
|
||||
|
||||
public let urlTestTime: Date
|
||||
public var urlTestDelay: UInt16
|
||||
|
||||
|
||||
public var server: String? = ""
|
||||
public var server_port: Int? = 0
|
||||
public var method: String? = ""
|
||||
public var password: String? = ""
|
||||
|
||||
//server: String?,server_port: String?,method: String?,serverpassword String?
|
||||
|
||||
// 手动定义初始化器
|
||||
public init(tag: String, type: String, urlTestTime: Date, urlTestDelay: UInt16) {
|
||||
self.tag = tag
|
||||
self.type = type
|
||||
self.urlTestTime = urlTestTime
|
||||
self.urlTestDelay = urlTestDelay
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public extension OutboundGroupItem {
|
||||
|
||||
mutating func setpingms(pingDelay: UInt16){
|
||||
urlTestDelay = pingDelay
|
||||
}
|
||||
|
||||
var toString: String {
|
||||
"\(tag) - \(type) - \(server ?? "") - \(server_port ?? 0) - \(method ?? "") - \(password ?? "") "
|
||||
}
|
||||
var displayType: String {
|
||||
LibboxProxyDisplayType(type)
|
||||
}
|
||||
|
||||
var delayString: String {
|
||||
"\(urlTestDelay)ms"
|
||||
}
|
||||
|
||||
var delayColor: Color {
|
||||
switch urlTestDelay {
|
||||
case 0:
|
||||
return .gray
|
||||
case ..<400:
|
||||
return .green
|
||||
case ..<800:
|
||||
return .yellow
|
||||
case 800 ..< 1500:
|
||||
return .orange
|
||||
default:
|
||||
return .red
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user