Skip to content

Commit d57dfc4

Browse files
committed
feat: enhance health check and speed test result handling
1 parent 8f4cb4e commit d57dfc4

File tree

2 files changed

+89
-2
lines changed

2 files changed

+89
-2
lines changed

ClashX/Views/ProxyGroupSpeedTestMenuItem.swift

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,39 @@ class ProxyGroupSpeedTestMenuItem: NSMenuItem {
4444

4545
@objc func healthCheck() {
4646
guard testType == .reTest else { return }
47-
ApiRequest.getGroupDelay(groupName: proxyGroup.name) { _ in }
47+
48+
// Clear existing speed test results for all proxies in this group
49+
ApiRequest.getMergedProxyData { [weak self] proxyResp in
50+
guard let self = self else { return }
51+
var proxiesToClear = [ClashProxyName]()
52+
53+
// Get all proxy names in this group
54+
if let allProxies = self.proxyGroup.all {
55+
proxiesToClear.append(contentsOf: allProxies)
56+
}
57+
58+
// Clear speed test results by posting notifications with empty values
59+
for proxyName in proxiesToClear {
60+
NotificationCenter.default.post(name: .speedTestFinishForProxy,
61+
object: nil,
62+
userInfo: ["proxyName": proxyName, "delay": "", "rawValue": 0])
63+
}
64+
65+
// Start actual testing after clearing results
66+
ApiRequest.healthCheck(proxy: self.proxyGroup.name)
67+
ApiRequest.getMergedProxyData { [weak self] proxyResp in
68+
guard let self = self else { return }
69+
var providers = Set<ClashProxyName>()
70+
self.proxyGroup.all?.compactMap{
71+
proxyResp?.proxiesMap[$0]?.enclosingProvider?.name
72+
}.forEach{
73+
providers.insert($0)
74+
}
75+
providers.forEach{
76+
ApiRequest.healthCheck(proxy: $0)
77+
}
78+
}
79+
}
4880
menu?.cancelTracking()
4981
}
5082
}
@@ -89,11 +121,57 @@ private class ProxyGroupSpeedTestMenuItemView: MenuItemBaseView {
89121
private func startBenchmark() {
90122
guard let group = (enclosingMenuItem as? ProxyGroupSpeedTestMenuItem)?.proxyGroup
91123
else { return }
124+
let testGroup = DispatchGroup()
125+
126+
var proxies = [ClashProxyName]()
127+
var providers = Set<ClashProviderName>()
128+
for testable in group.speedtestAble {
129+
switch testable {
130+
case let .provider(_, provider):
131+
providers.insert(provider)
132+
case let .proxy(name):
133+
proxies.append(name)
134+
default:
135+
continue
136+
}
137+
}
92138

139+
// First, show "Testing" state and disable the menu item
93140
label.stringValue = NSLocalizedString("Testing", comment: "")
94141
enclosingMenuItem?.isEnabled = false
95142
setNeedsDisplay()
96143

144+
// Then clear existing speed test results for all proxies in this group
145+
ApiRequest.getMergedProxyData { [weak self] proxyResp in
146+
guard let self = self else { return }
147+
148+
var proxiesToClear = [ClashProxyName]()
149+
150+
// Get all proxy names in this group
151+
if let allProxies = group.all {
152+
proxiesToClear.append(contentsOf: allProxies)
153+
}
154+
155+
// Clear speed test results by posting notifications with empty values
156+
for proxyName in proxiesToClear {
157+
NotificationCenter.default.post(name: .speedTestFinishForProxy,
158+
object: nil,
159+
userInfo: ["proxyName": proxyName, "delay": "", "rawValue": 0])
160+
}
161+
162+
// Start actual testing after clearing results
163+
for proxyName in proxies {
164+
testGroup.enter()
165+
ApiRequest.getProxyDelay(proxyName: proxyName) { delay in
166+
let delayStr = delay == 0 ? NSLocalizedString("fail", comment: "") : "\(delay) ms"
167+
NotificationCenter.default.post(name: .speedTestFinishForProxy,
168+
object: nil,
169+
userInfo: ["proxyName": proxyName, "delay": delayStr, "rawValue": delay])
170+
testGroup.leave()
171+
}
172+
}
173+
}
174+
97175
ApiRequest.getGroupDelay(groupName: group.name) {
98176
[weak self] delays in
99177
guard let self = self, let menu = self.enclosingMenuItem else { return }

ClashX/Views/ProxyItemView.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,18 @@ class ProxyItemView: MenuItemBaseView {
8383
delayLabel.stringValue = str ?? ""
8484
needsLayout = true
8585

86-
guard let delay = value, str != nil else {
86+
guard let delay = value, let delayStr = str else {
8787
delayLabel.layer?.backgroundColor = NSColor.clear.cgColor
8888
return
8989
}
90+
91+
if delayStr.isEmpty {
92+
// Testing state - show gray badge
93+
delayLabel.stringValue = NSLocalizedString("Testing", comment: "")
94+
delayLabel.layer?.backgroundColor = CGColor.testing
95+
return
96+
}
97+
9098
switch delay {
9199
case 0:
92100
delayLabel.layer?.backgroundColor = CGColor.fail
@@ -134,4 +142,5 @@ private extension CGColor {
134142
static let good = CGColor(red: 30.0 / 255, green: 181.0 / 255, blue: 30.0 / 255, alpha: 1)
135143
static let meduim = CGColor(red: 1, green: 135.0 / 255, blue: 0, alpha: 1)
136144
static let fail = CGColor(red: 218.0 / 255, green: 0.0, blue: 3.0 / 255, alpha: 1)
145+
static let testing = CGColor(red: 128.0 / 255, green: 128.0 / 255, blue: 128.0 / 255, alpha: 1)
137146
}

0 commit comments

Comments
 (0)