diff --git a/ClashX/General/ApiRequest.swift b/ClashX/General/ApiRequest.swift index 318e424..85baed8 100644 --- a/ClashX/General/ApiRequest.swift +++ b/ClashX/General/ApiRequest.swift @@ -227,7 +227,7 @@ class ApiRequest { } } - static func healthCheck(proxy: ClashProxyName) { + static func healthCheck(proxy: ClashProviderName) { Logger.log("HeathCheck for \(proxy) started") req("/providers/proxies/\(proxy.encoded)/healthcheck").response { res in if res.response?.statusCode == 204 { diff --git a/ClashX/General/Managers/MenuItemFactory.swift b/ClashX/General/Managers/MenuItemFactory.swift index 1a08f5b..9a92b21 100644 --- a/ClashX/General/Managers/MenuItemFactory.swift +++ b/ClashX/General/Managers/MenuItemFactory.swift @@ -122,8 +122,6 @@ class MenuItemFactory { guard proxyGroup.speedtestAble.count > 0 else { return } menus.addItem(NSMenuItem.separator()) let speedTestItem = ProxyGroupSpeedTestMenuItem(group: proxyGroup) - speedTestItem.target = MenuItemFactory.self - speedTestItem.action = #selector(actionSpeedTest) menus.addItem(speedTestItem) } @@ -157,21 +155,6 @@ class MenuItemFactory { return menu } - static func generateProviderMenuItems(_ provider: ClashProvider) -> NSMenuItem? { - let menu = NSMenuItem(title: provider.name, action: nil, keyEquivalent: "") - let submenu = NSMenu(title: provider.name) - - for proxy in provider.proxies { - let proxyMenuItem = NSMenuItem(title: proxy.name, action: #selector(empty), keyEquivalent: "") - proxyMenuItem.target = MenuItemFactory.self - proxyMenuItem.submenu = generateHistoryMenu(proxy) - submenu.addItem(proxyMenuItem) - } - - menu.submenu = submenu - return menu - } - static func generateSwitchConfigMenuItems() -> [NSMenuItem] { var items = [NSMenuItem]() for config in ConfigManager.getConfigFilesList() { @@ -217,10 +200,5 @@ extension MenuItemFactory { } } - @objc static func actionSpeedTest(sender: ProxyGroupSpeedTestMenuItem) { - guard sender.testType == .reTest else { return } - ApiRequest.healthCheck(proxy: sender.proxyGroup.name) - } - @objc static func empty() {} } diff --git a/ClashX/Models/ClashProvider.swift b/ClashX/Models/ClashProvider.swift index 4a7460b..d9665a6 100644 --- a/ClashX/Models/ClashProvider.swift +++ b/ClashX/Models/ClashProvider.swift @@ -43,7 +43,7 @@ class ClashProvider: Codable { case Unknown } - let name: String + let name: ClashProviderName let proxies: [ClashProxy] let type: ProviderType let vehicleType: ProviderVehicleType diff --git a/ClashX/Models/ClashProxy.swift b/ClashX/Models/ClashProxy.swift index 88cea56..0f1900e 100644 --- a/ClashX/Models/ClashProxy.swift +++ b/ClashX/Models/ClashProxy.swift @@ -40,6 +40,7 @@ enum ClashProxyType: String, Codable { } typealias ClashProxyName = String +typealias ClashProviderName = String class ClashProxySpeedHistory: Codable { let time: Date @@ -72,16 +73,23 @@ class ClashProxy: Codable { let all: [ClashProxyName]? let history: [ClashProxySpeedHistory] let now: ClashProxyName? - var providerProxy = false weak var enclosingResp: ClashProxyResp? = nil + weak var enclosingProvider: ClashProvider? = nil - lazy var speedtestAble: [ClashProxyName] = { - guard let resp = enclosingResp, let allProxys = all else { return all ?? [] } - var proxys = [ClashProxyName]() + enum SpeedtestAbleItem { + case proxy(name: ClashProxyName) + case provider(name: ClashProxyName, provider: ClashProviderName) + } + + lazy var speedtestAble: [SpeedtestAbleItem] = { + guard let resp = enclosingResp, let allProxys = all else { return [] } + var proxys = [SpeedtestAbleItem]() for proxy in allProxys { if let p = resp.proxiesMap[proxy], !ClashProxyType.isProxyGroup(p) { - if !p.providerProxy { - proxys.append(proxy) + if let provider = p.enclosingProvider { + proxys.append(.provider(name: p.name, provider: provider.name)) + } else { + proxys.append(.proxy(name: p.name)) } } } @@ -110,6 +118,8 @@ class ClashProxyResp { let proxies: [ClashProxy] var proxiesMap: [ClashProxyName: ClashProxy] + private var enclosingProviderResp: ClashProviderResp? + init(_ data: Any?) { guard let data = data as? [String: [String: Any]], @@ -145,9 +155,10 @@ class ClashProxyResp { } func updateProvider(_ providerResp: ClashProviderResp) { + enclosingProviderResp = providerResp for provider in providerResp.providers.values { for proxy in provider.proxies { - proxy.providerProxy = true + proxy.enclosingProvider = provider proxiesMap[proxy.name] = proxy } } diff --git a/ClashX/Views/MenuItemBaseView.swift b/ClashX/Views/MenuItemBaseView.swift index e635dd0..fed056b 100644 --- a/ClashX/Views/MenuItemBaseView.swift +++ b/ClashX/Views/MenuItemBaseView.swift @@ -16,7 +16,6 @@ class MenuItemBaseView: NSView { private let handleClick: Bool private let autolayout: Bool - // MARK: Public var isHighlighted: Bool { @@ -79,7 +78,6 @@ class MenuItemBaseView: NSView { effectView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true } - // MARK: Override override func draw(_ dirtyRect: NSRect) { @@ -101,7 +99,7 @@ class MenuItemBaseView: NSView { } } } - + override func mouseUp(with event: NSEvent) { didClickView() } diff --git a/ClashX/Views/ProxyGroupSpeedTestMenuItem.swift b/ClashX/Views/ProxyGroupSpeedTestMenuItem.swift index ebcdaf1..99f9df9 100644 --- a/ClashX/Views/ProxyGroupSpeedTestMenuItem.swift +++ b/ClashX/Views/ProxyGroupSpeedTestMenuItem.swift @@ -25,6 +25,8 @@ class ProxyGroupSpeedTestMenuItem: NSMenuItem { } super.init(title: NSLocalizedString("Benchmark", comment: ""), action: nil, keyEquivalent: "") + target = self + action = #selector(healthCheck) switch testType { case .benchmark: @@ -39,6 +41,12 @@ class ProxyGroupSpeedTestMenuItem: NSMenuItem { required init(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + @objc func healthCheck() { + guard testType == .reTest else { return } + ApiRequest.healthCheck(proxy: proxyGroup.name) + menu?.cancelTracking() + } } fileprivate class ProxyGroupSpeedTestMenuItemView: MenuItemBaseView { @@ -71,10 +79,19 @@ fileprivate class ProxyGroupSpeedTestMenuItemView: MenuItemBaseView { guard let group = (enclosingMenuItem as? ProxyGroupSpeedTestMenuItem)?.proxyGroup else { return } let testGroup = DispatchGroup() - label.stringValue = NSLocalizedString("Testing", comment: "") - enclosingMenuItem?.isEnabled = false - setNeedsDisplay(bounds) - for proxyName in group.speedtestAble { + + var proxies = [ClashProxyName]() + var providers = Set() + for testable in group.speedtestAble { + switch testable { + case let .provider(_, provider): + providers.insert(provider) + case let .proxy(name): + proxies.append(name) + } + } + + for proxyName in proxies { testGroup.enter() ApiRequest.getProxyDelay(proxyName: proxyName) { delay in let delayStr = delay == 0 ? "fail" : "\(delay) ms" @@ -85,12 +102,23 @@ fileprivate class ProxyGroupSpeedTestMenuItemView: MenuItemBaseView { } } - testGroup.notify(queue: .main) { - [weak self] in - guard let self = self, let menu = self.enclosingMenuItem else { return } - self.label.stringValue = menu.title - menu.isEnabled = true - self.setNeedsDisplay() + if providers.count > 0 { + for provider in providers { + ApiRequest.healthCheck(proxy: provider) + } + enclosingMenuItem?.menu?.cancelTracking() + + } else { + label.stringValue = NSLocalizedString("Testing", comment: "") + enclosingMenuItem?.isEnabled = false + setNeedsDisplay() + testGroup.notify(queue: .main) { + [weak self] in + guard let self = self, let menu = self.enclosingMenuItem else { return } + self.label.stringValue = menu.title + menu.isEnabled = true + self.setNeedsDisplay() + } } }