mirror of
https://github.com/yJason/ClashX-Dashboard.git
synced 2026-03-01 00:35:19 +08:00
refactor: DBConnectionSnapShot
This commit is contained in:
@@ -284,24 +284,24 @@ class ApiRequest {
|
||||
// MARK: - Connections
|
||||
|
||||
extension ApiRequest {
|
||||
static func getConnections(completeHandler: @escaping (ClashConnectionSnapShot) -> Void) {
|
||||
static func getConnections(completeHandler: @escaping (DBConnectionSnapShot) -> Void) {
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
decoder.dateDecodingStrategy = .formatted(DateFormatter.js)
|
||||
|
||||
req("/connections").responseDecodable(of: ClashConnectionSnapShot.self, decoder: decoder) { resp in
|
||||
req("/connections").responseDecodable(of: DBConnectionSnapShot.self, decoder: decoder) { resp in
|
||||
switch resp.result {
|
||||
case let .success(snapshot):
|
||||
completeHandler(snapshot)
|
||||
case .failure:
|
||||
return
|
||||
// assertionFailure()
|
||||
// completeHandler(ClashConnectionSnapShot())
|
||||
// completeHandler(DBConnectionSnapShot())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func closeConnection(_ conn: ClashConnection) {
|
||||
static func closeConnection(_ conn: ClashConnectionSnapShot.Connection) {
|
||||
req("/connections/".appending(conn.id), method: .delete).response { _ in }
|
||||
}
|
||||
|
||||
|
||||
@@ -7,104 +7,14 @@
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import DifferenceKit
|
||||
|
||||
struct ClashConnectionSnapShot: Codable {
|
||||
let downloadTotal: Int
|
||||
let uploadTotal: Int
|
||||
let connections: [ClashConnection]
|
||||
let connections: [Connection]
|
||||
}
|
||||
|
||||
struct ClashConnection: 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: MetaConnectionData
|
||||
}
|
||||
|
||||
struct MetaConnectionData: 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 ClashConnectionObject: 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: ClashConnectionObject) -> Bool {
|
||||
download == source.download &&
|
||||
upload == source.upload &&
|
||||
startString == source.startString
|
||||
}
|
||||
|
||||
init(_ conn: ClashConnection) {
|
||||
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))"
|
||||
}
|
||||
|
||||
extension ClashConnectionSnapShot {
|
||||
struct Connection: Codable {
|
||||
let id: String
|
||||
let chains: [String]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -148,5 +148,5 @@ class ClashLogStorage: ObservableObject {
|
||||
}
|
||||
|
||||
class ClashConnsStorage: ObservableObject {
|
||||
@Published var conns = [ClashConnection]()
|
||||
@Published var conns = [DBConnection]()
|
||||
}
|
||||
|
||||
@@ -72,27 +72,27 @@ struct CollectionsTableView<Item: Hashable>: NSViewRepresentable {
|
||||
|
||||
switch $0 {
|
||||
case .host:
|
||||
sort = .init(keyPath: \ClashConnectionObject.host, ascending: true)
|
||||
sort = .init(keyPath: \DBConnectionObject.host, ascending: true)
|
||||
case .sniffHost:
|
||||
sort = .init(keyPath: \ClashConnectionObject.sniffHost, ascending: true)
|
||||
sort = .init(keyPath: \DBConnectionObject.sniffHost, ascending: true)
|
||||
case .process:
|
||||
sort = .init(keyPath: \ClashConnectionObject.process, ascending: true)
|
||||
sort = .init(keyPath: \DBConnectionObject.process, ascending: true)
|
||||
case .dl:
|
||||
sort = .init(keyPath: \ClashConnectionObject.download, ascending: true)
|
||||
sort = .init(keyPath: \DBConnectionObject.download, ascending: true)
|
||||
case .ul:
|
||||
sort = .init(keyPath: \ClashConnectionObject.upload, ascending: true)
|
||||
sort = .init(keyPath: \DBConnectionObject.upload, ascending: true)
|
||||
case .chain:
|
||||
sort = .init(keyPath: \ClashConnectionObject.chainString, ascending: true)
|
||||
sort = .init(keyPath: \DBConnectionObject.chainString, ascending: true)
|
||||
case .rule:
|
||||
sort = .init(keyPath: \ClashConnectionObject.ruleString, ascending: true)
|
||||
sort = .init(keyPath: \DBConnectionObject.ruleString, ascending: true)
|
||||
case .time:
|
||||
sort = .init(keyPath: \ClashConnectionObject.startDate, ascending: true)
|
||||
sort = .init(keyPath: \DBConnectionObject.startDate, ascending: true)
|
||||
case .source:
|
||||
sort = .init(keyPath: \ClashConnectionObject.source, ascending: true)
|
||||
sort = .init(keyPath: \DBConnectionObject.source, ascending: true)
|
||||
case .destinationIP:
|
||||
sort = .init(keyPath: \ClashConnectionObject.destinationIP, ascending: true)
|
||||
sort = .init(keyPath: \DBConnectionObject.destinationIP, ascending: true)
|
||||
case .type:
|
||||
sort = .init(keyPath: \ClashConnectionObject.type, ascending: true)
|
||||
sort = .init(keyPath: \DBConnectionObject.type, ascending: true)
|
||||
default:
|
||||
sort = nil
|
||||
}
|
||||
@@ -114,11 +114,11 @@ struct CollectionsTableView<Item: Hashable>: NSViewRepresentable {
|
||||
func updateNSView(_ nsView: NSScrollView, context: Context) {
|
||||
context.coordinator.parent = self
|
||||
guard let tableView = nsView.documentView as? NSTableView,
|
||||
let data = data as? [ClashConnection] else {
|
||||
let data = data as? [DBConnection] else {
|
||||
return
|
||||
}
|
||||
|
||||
let target = updateSorts(data.map(ClashConnectionObject.init), tableView: tableView)
|
||||
let target = updateSorts(data.map(DBConnectionObject.init), tableView: tableView)
|
||||
|
||||
let source = context.coordinator.conns
|
||||
let changeset = StagedChangeset(source: source, target: target)
|
||||
@@ -129,12 +129,12 @@ struct CollectionsTableView<Item: Hashable>: NSViewRepresentable {
|
||||
}
|
||||
}
|
||||
|
||||
func updateSorts(_ objects: [ClashConnectionObject],
|
||||
tableView: NSTableView) -> [ClashConnectionObject] {
|
||||
func updateSorts(_ objects: [DBConnectionObject],
|
||||
tableView: NSTableView) -> [DBConnectionObject] {
|
||||
var re = objects
|
||||
|
||||
var sortDescriptors = tableView.sortDescriptors
|
||||
sortDescriptors.append(.init(keyPath: \ClashConnectionObject.id, ascending: true))
|
||||
sortDescriptors.append(.init(keyPath: \DBConnectionObject.id, ascending: true))
|
||||
re = re.sorted(descriptors: sortDescriptors)
|
||||
|
||||
let filterKeys = [
|
||||
@@ -161,7 +161,7 @@ struct CollectionsTableView<Item: Hashable>: NSViewRepresentable {
|
||||
|
||||
var parent: CollectionsTableView
|
||||
|
||||
var conns = [ClashConnectionObject]()
|
||||
var conns = [DBConnectionObject]()
|
||||
|
||||
init(parent: CollectionsTableView) {
|
||||
self.parent = parent
|
||||
|
||||
Reference in New Issue
Block a user