mirror of
https://github.com/yJason/ClashX-Dashboard.git
synced 2026-03-01 00:35:19 +08:00
fix: spm
This commit is contained in:
108
Sources/ClashX Dashboard/Models/DBConnectionSnapShot.swift
Normal file
108
Sources/ClashX Dashboard/Models/DBConnectionSnapShot.swift
Normal file
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// DBConnectionSnapShot.swift
|
||||
// ClashX Dashboard
|
||||
//
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import DifferenceKit
|
||||
|
||||
struct DBConnectionSnapShot: Codable {
|
||||
let downloadTotal: Int
|
||||
let uploadTotal: Int
|
||||
let connections: [DBConnection]
|
||||
}
|
||||
|
||||
struct DBConnection: Codable, Hashable {
|
||||
let id: String
|
||||
let chains: [String]
|
||||
let upload: Int64
|
||||
let download: Int64
|
||||
let start: Date
|
||||
let rule: String
|
||||
let rulePayload: String
|
||||
|
||||
let metadata: DBMetaConnectionData
|
||||
}
|
||||
|
||||
struct DBMetaConnectionData: Codable, Hashable {
|
||||
let uid: Int
|
||||
|
||||
let network: String
|
||||
let type: String
|
||||
let sourceIP: String
|
||||
let destinationIP: String
|
||||
let sourcePort: String
|
||||
let destinationPort: String
|
||||
let inboundIP: String
|
||||
let inboundPort: String
|
||||
let inboundName: String
|
||||
let host: String
|
||||
let dnsMode: String
|
||||
let process: String
|
||||
let processPath: String
|
||||
let specialProxy: String
|
||||
let specialRules: String
|
||||
let remoteDestination: String
|
||||
let sniffHost: String
|
||||
|
||||
}
|
||||
|
||||
|
||||
class DBConnectionObject: NSObject, Differentiable {
|
||||
@objc let id: String
|
||||
@objc let host: String
|
||||
@objc let sniffHost: String
|
||||
@objc let process: String
|
||||
@objc let download: Int64
|
||||
@objc let upload: Int64
|
||||
let downloadString: String
|
||||
let uploadString: String
|
||||
let chains: [String]
|
||||
@objc let chainString: String
|
||||
@objc let ruleString: String
|
||||
@objc let startDate: Date
|
||||
let startString: String
|
||||
@objc let source: String
|
||||
@objc let destinationIP: String?
|
||||
@objc let type: String
|
||||
|
||||
var differenceIdentifier: String {
|
||||
return id
|
||||
}
|
||||
|
||||
func isContentEqual(to source: DBConnectionObject) -> Bool {
|
||||
download == source.download &&
|
||||
upload == source.upload &&
|
||||
startString == source.startString
|
||||
}
|
||||
|
||||
init(_ conn: DBConnection) {
|
||||
let byteCountFormatter = ByteCountFormatter()
|
||||
let startFormatter = RelativeDateTimeFormatter()
|
||||
startFormatter.unitsStyle = .short
|
||||
|
||||
let metadata = conn.metadata
|
||||
|
||||
id = conn.id
|
||||
host = "\(metadata.host == "" ? metadata.destinationIP : metadata.host):\(metadata.destinationPort)"
|
||||
sniffHost = metadata.sniffHost == "" ? "-" : metadata.sniffHost
|
||||
process = metadata.process
|
||||
download = conn.download
|
||||
downloadString = byteCountFormatter.string(fromByteCount: conn.download)
|
||||
upload = conn.upload
|
||||
uploadString = byteCountFormatter.string(fromByteCount: conn.upload)
|
||||
chains = conn.chains
|
||||
chainString = conn.chains.reversed().joined(separator: "/")
|
||||
ruleString = conn.rulePayload == "" ? conn.rule : "\(conn.rule) :: \(conn.rulePayload)"
|
||||
startDate = conn.start
|
||||
startString = startFormatter.localizedString(for: conn.start, relativeTo: Date())
|
||||
source = "\(metadata.sourceIP):\(metadata.sourcePort)"
|
||||
destinationIP = [metadata.remoteDestination,
|
||||
metadata.destinationIP,
|
||||
metadata.host].first(where: { $0 != "" })
|
||||
|
||||
type = "\(metadata.type)(\(metadata.network))"
|
||||
}
|
||||
|
||||
}
|
||||
98
Sources/ClashX Dashboard/Models/DBProviderStorage.swift
Normal file
98
Sources/ClashX Dashboard/Models/DBProviderStorage.swift
Normal file
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// DBProviderStorage.swift
|
||||
// ClashX Dashboard
|
||||
//
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import SwiftUI
|
||||
|
||||
class DBProviderStorage: ObservableObject {
|
||||
@Published var proxyProviders = [DBProxyProvider]()
|
||||
@Published var ruleProviders = [DBRuleProvider]()
|
||||
|
||||
init() {}
|
||||
|
||||
}
|
||||
|
||||
class DBProxyProvider: ObservableObject, Identifiable {
|
||||
let id = UUID().uuidString
|
||||
|
||||
@Published var name: ClashProviderName
|
||||
@Published var proxies: [DBProxy]
|
||||
@Published var type: ClashProvider.ProviderType
|
||||
@Published var vehicleType: ClashProvider.ProviderVehicleType
|
||||
|
||||
@Published var trafficInfo: String
|
||||
@Published var trafficPercentage: String
|
||||
@Published var expireDate: String
|
||||
@Published var updatedAt: String
|
||||
|
||||
init(provider: ClashProvider) {
|
||||
name = provider.name
|
||||
proxies = provider.proxies.map(DBProxy.init)
|
||||
type = provider.type
|
||||
vehicleType = provider.vehicleType
|
||||
|
||||
if let info = provider.subscriptionInfo {
|
||||
let used = info.download + info.upload
|
||||
let total = info.total
|
||||
|
||||
let trafficRate = "\(String(format: "%.2f", Double(used)/Double(total/100)))%"
|
||||
|
||||
let formatter = ByteCountFormatter()
|
||||
|
||||
trafficInfo = formatter.string(fromByteCount: used)
|
||||
+ " / "
|
||||
+ formatter.string(fromByteCount: total)
|
||||
+ " ( \(trafficRate) )"
|
||||
|
||||
let expire = info.expire
|
||||
|
||||
expireDate = "Expire: "
|
||||
+ Date(timeIntervalSince1970: TimeInterval(expire))
|
||||
.formatted()
|
||||
self.trafficPercentage = trafficRate
|
||||
} else {
|
||||
trafficInfo = ""
|
||||
expireDate = ""
|
||||
trafficPercentage = "0.0%"
|
||||
}
|
||||
|
||||
if let updatedAt = provider.updatedAt {
|
||||
let formatter = RelativeDateTimeFormatter()
|
||||
formatter.unitsStyle = .abbreviated
|
||||
self.updatedAt = formatter.localizedString(for: updatedAt, relativeTo: .now)
|
||||
} else {
|
||||
self.updatedAt = ""
|
||||
}
|
||||
}
|
||||
|
||||
func updateInfo(_ new: DBProxyProvider) {
|
||||
proxies = new.proxies
|
||||
updatedAt = new.updatedAt
|
||||
expireDate = new.expireDate
|
||||
trafficInfo = new.trafficInfo
|
||||
trafficPercentage = new.trafficPercentage
|
||||
}
|
||||
}
|
||||
|
||||
class DBRuleProvider: ObservableObject, Identifiable {
|
||||
let id: String
|
||||
|
||||
@Published var name: ClashProviderName
|
||||
@Published var ruleCount: Int
|
||||
@Published var behavior: String
|
||||
@Published var type: String
|
||||
@Published var updatedAt: Date?
|
||||
|
||||
init(provider: ClashRuleProvider) {
|
||||
id = UUID().uuidString
|
||||
|
||||
name = provider.name
|
||||
ruleCount = provider.ruleCount
|
||||
behavior = provider.behavior
|
||||
type = provider.type
|
||||
updatedAt = provider.updatedAt
|
||||
}
|
||||
}
|
||||
120
Sources/ClashX Dashboard/Models/DBProxyStorage.swift
Normal file
120
Sources/ClashX Dashboard/Models/DBProxyStorage.swift
Normal file
@@ -0,0 +1,120 @@
|
||||
//
|
||||
// DBProxyStorage.swift
|
||||
// ClashX Dashboard
|
||||
//
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import SwiftUI
|
||||
|
||||
class DBProxyStorage: ObservableObject {
|
||||
@Published var groups = [DBProxyGroup]()
|
||||
|
||||
init() {
|
||||
|
||||
}
|
||||
|
||||
init(_ resp: ClashProxyResp) {
|
||||
groups = resp.proxyGroups.map {
|
||||
DBProxyGroup($0, resp: resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DBProxyGroup: ObservableObject, Identifiable {
|
||||
let id = UUID().uuidString
|
||||
@Published var name: ClashProxyName
|
||||
@Published var type: ClashProxyType
|
||||
@Published var now: ClashProxyName? {
|
||||
didSet {
|
||||
currentProxy = proxies.first {
|
||||
$0.name == now
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Published var proxies: [DBProxy]
|
||||
|
||||
@Published var currentProxy: DBProxy?
|
||||
|
||||
init(_ group: ClashProxy, resp: ClashProxyResp) {
|
||||
name = group.name
|
||||
type = group.type
|
||||
now = group.now
|
||||
|
||||
proxies = group.all?.compactMap { name in
|
||||
resp.proxiesMap[name]
|
||||
}.map(DBProxy.init) ?? []
|
||||
|
||||
currentProxy = proxies.first {
|
||||
$0.name == now
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DBProxy: ObservableObject {
|
||||
let id: String
|
||||
@Published var name: ClashProxyName
|
||||
@Published var type: ClashProxyType
|
||||
@Published var udpString: String
|
||||
@Published var tfo: Bool
|
||||
|
||||
var delay: Int {
|
||||
didSet {
|
||||
delayString = DBProxy.delayString(delay)
|
||||
delayColor = DBProxy.delayColor(delay)
|
||||
}
|
||||
}
|
||||
|
||||
@Published var delayString: String
|
||||
@Published var delayColor: Color
|
||||
|
||||
init(_ proxy: ClashProxy) {
|
||||
id = proxy.id ?? UUID().uuidString
|
||||
name = proxy.name
|
||||
type = proxy.type
|
||||
tfo = proxy.tfo
|
||||
delay = proxy.history.last?.delayInt ?? 0
|
||||
|
||||
udpString = {
|
||||
if proxy.udp {
|
||||
return "UDP"
|
||||
} else if proxy.xudp {
|
||||
return "XUDP"
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}()
|
||||
delayString = DBProxy.delayString(delay)
|
||||
delayColor = DBProxy.delayColor(delay)
|
||||
}
|
||||
|
||||
static func delayString(_ delay: Int) -> String {
|
||||
switch delay {
|
||||
case 0:
|
||||
return NSLocalizedString("fail", comment: "")
|
||||
default:
|
||||
return "\(delay) ms"
|
||||
}
|
||||
}
|
||||
|
||||
static func delayColor(_ delay: Int) -> Color {
|
||||
let httpsTest = true
|
||||
|
||||
switch delay {
|
||||
case 0:
|
||||
return .gray
|
||||
case ..<200 where !httpsTest:
|
||||
return .green
|
||||
case ..<800 where httpsTest:
|
||||
return .green
|
||||
case 200..<500 where !httpsTest:
|
||||
return .yellow
|
||||
case 800..<1500 where httpsTest:
|
||||
return .yellow
|
||||
default:
|
||||
return .orange
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user