Feature: show speedtest history in proxy group
This commit is contained in:
parent
670ad02b49
commit
61e87ed07c
|
@ -18,24 +18,30 @@ class MenuItemFactory {
|
|||
completionHandler(menuItems)
|
||||
return
|
||||
}
|
||||
for proxy in proxyInfo.proxies.sorted(by: { $0.name < $1.name}) {
|
||||
|
||||
for proxy in proxyInfo.proxyGroups {
|
||||
var menu:NSMenuItem?
|
||||
switch proxy.type {
|
||||
case .select: menu = self.generateSelectorMenuItem(proxyGroup: proxy, proxyMap: proxyInfo.proxiesMap)
|
||||
case .urltest,.fallback: menu = generateUrlTestMenuItem(proxyGroup: proxy)
|
||||
case .select: menu = self.generateSelectorMenuItem(proxyGroup: proxy, proxyInfo: proxyInfo)
|
||||
case .urltest,.fallback: menu = generateUrlTestMenuItem(proxyGroup: proxy, proxyInfo: proxyInfo)
|
||||
case .loadBalance:
|
||||
menu = generateLoadBalanceMenuItem(proxyGroup: proxy, proxyMap: proxyInfo.proxiesMap)
|
||||
menu = generateLoadBalanceMenuItem(proxyGroup: proxy, proxyInfo: proxyInfo)
|
||||
default: continue
|
||||
}
|
||||
if let menu = menu {menuItems.append(menu)}
|
||||
|
||||
if let menu = menu {
|
||||
menuItems.append(menu)
|
||||
menu.isEnabled=true
|
||||
}
|
||||
}
|
||||
completionHandler(menuItems.reversed())
|
||||
completionHandler(menuItems)
|
||||
}
|
||||
}
|
||||
|
||||
static func generateSelectorMenuItem(proxyGroup:ClashProxy,
|
||||
proxyMap:[ClashProxyName:ClashProxy]) -> NSMenuItem? {
|
||||
proxyInfo:ClashProxyResp) -> NSMenuItem? {
|
||||
let proxyMap = proxyInfo.proxiesMap
|
||||
|
||||
let isGlobalMode = ConfigManager.shared.currentConfig?.mode == .global
|
||||
if (isGlobalMode) {
|
||||
if proxyGroup.name != "GLOBAL" {return nil}
|
||||
|
@ -54,18 +60,13 @@ class MenuItemFactory {
|
|||
if isGlobalMode && proxyModel.type == .select {
|
||||
continue
|
||||
}
|
||||
|
||||
let proxyItem = ProxyMenuItem(proxy: proxyModel, action: #selector(MenuItemFactory.actionSelectProxy(sender:)),
|
||||
maxProxyNameLength:proxyGroup.maxProxyNameLength)
|
||||
|
||||
proxyItem.target = MenuItemFactory.self
|
||||
proxyItem.isSelected = proxy == selectedName
|
||||
|
||||
|
||||
if proxyItem.isSelected {hasSelected = true}
|
||||
submenu.addItem(proxyItem)
|
||||
submenu.autoenablesItems = false
|
||||
|
||||
}
|
||||
|
||||
menu.submenu = submenu
|
||||
|
@ -75,29 +76,56 @@ class MenuItemFactory {
|
|||
return menu
|
||||
}
|
||||
|
||||
static func generateUrlTestMenuItem(proxyGroup:ClashProxy)->NSMenuItem? {
|
||||
static func generateUrlTestMenuItem(proxyGroup:ClashProxy,proxyInfo:ClashProxyResp)->NSMenuItem? {
|
||||
|
||||
let proxyMap = proxyInfo.proxiesMap
|
||||
|
||||
let menu = NSMenuItem(title: proxyGroup.name, action: nil, keyEquivalent: "")
|
||||
let selectedName = proxyGroup.now ?? ""
|
||||
let submenu = NSMenu(title: proxyGroup.name)
|
||||
|
||||
let nowMenuItem = NSMenuItem(title: "now:\(selectedName)", action: nil, keyEquivalent: "")
|
||||
|
||||
let nowMenuItem = NSMenuItem(title: "now:\(selectedName)", action: #selector(empty), keyEquivalent: "")
|
||||
nowMenuItem.target = MenuItemFactory.self
|
||||
|
||||
submenu.addItem(nowMenuItem)
|
||||
submenu.addItem(NSMenuItem.separator())
|
||||
|
||||
for proxyName in proxyGroup.all ?? [] {
|
||||
guard let proxy = proxyMap[proxyName] else {continue}
|
||||
let proxyMenuItem = NSMenuItem(title: proxy.name, action: nil, keyEquivalent: "")
|
||||
if proxy.name == selectedName {
|
||||
proxyMenuItem.state = .on
|
||||
}
|
||||
var historyItems = [NSMenuItem]()
|
||||
for his in proxy.history {
|
||||
historyItems.append(
|
||||
NSMenuItem(title: "\(his.dateDisplay) \(his.delayDisplay)", action: nil, keyEquivalent: ""))
|
||||
}
|
||||
if historyItems.count > 0 {
|
||||
let historyMenu = NSMenu(title: "")
|
||||
historyMenu.items = historyItems
|
||||
proxyMenuItem.submenu = historyMenu
|
||||
submenu.addItem(proxyMenuItem)
|
||||
}
|
||||
}
|
||||
menu.submenu = submenu
|
||||
return menu
|
||||
}
|
||||
|
||||
static func generateLoadBalanceMenuItem(proxyGroup:ClashProxy, proxyMap:[ClashProxyName:ClashProxy])->NSMenuItem? {
|
||||
static func generateLoadBalanceMenuItem(proxyGroup:ClashProxy, proxyInfo:ClashProxyResp)->NSMenuItem? {
|
||||
|
||||
let proxyMap = proxyInfo.proxiesMap
|
||||
|
||||
let menu = NSMenuItem(title: proxyGroup.name, action: nil, keyEquivalent: "")
|
||||
let submenu = NSMenu(title: proxyGroup.name)
|
||||
|
||||
for proxy in proxyGroup.all ?? [] {
|
||||
guard let proxyModel = proxyMap[proxy] else {continue}
|
||||
let proxyItem = ProxyMenuItem(proxy: proxyModel,
|
||||
action:nil,
|
||||
action:#selector(empty),
|
||||
maxProxyNameLength:proxyGroup.maxProxyNameLength)
|
||||
proxyItem.isSelected = false
|
||||
proxyItem.target = MenuItemFactory.self
|
||||
submenu.addItem(proxyItem)
|
||||
}
|
||||
|
||||
|
@ -142,5 +170,7 @@ extension MenuItemFactory {
|
|||
ConfigManager.selectConfigName = config
|
||||
NotificationCenter.default.post(Notification(name: kShouldUpDateConfig))
|
||||
}
|
||||
|
||||
@objc static func empty(){}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,26 @@ typealias ClashProxyName = String
|
|||
class ClashProxySpeedHistory:Codable {
|
||||
let time:Date
|
||||
let delay:Int
|
||||
|
||||
class hisDateFormaterInstance {
|
||||
static let shared = hisDateFormaterInstance()
|
||||
lazy var formater:DateFormatter = {
|
||||
var f = DateFormatter()
|
||||
f.dateFormat = "HH:mm"
|
||||
return f
|
||||
}()
|
||||
}
|
||||
|
||||
lazy var delayDisplay:String = {
|
||||
switch delay {
|
||||
case 0: return "fail"
|
||||
default:return "\(delay) ms"
|
||||
}
|
||||
}()
|
||||
|
||||
lazy var dateDisplay:String = {
|
||||
return hisDateFormaterInstance.shared.formater.string(from: time)
|
||||
}()
|
||||
}
|
||||
|
||||
|
||||
|
@ -54,7 +74,6 @@ class ClashProxy:Codable {
|
|||
options: .usesLineFragmentOrigin,
|
||||
attributes: attr).width;
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
class ClashProxyResp{
|
||||
|
@ -96,6 +115,28 @@ class ClashProxyResp{
|
|||
self.proxies = proxiesModel
|
||||
}
|
||||
|
||||
lazy var proxyGroups:[ClashProxy] = {
|
||||
return proxies.filter{
|
||||
switch $0.type {
|
||||
case .select,.urltest,.fallback,.loadBalance:return true
|
||||
default:return false
|
||||
}
|
||||
}.sorted(by: {$0.name < $1.name})
|
||||
}()
|
||||
|
||||
lazy var longestProxyGroupName = {
|
||||
return proxyGroups.max{$1.name.count > $0.name.count}?.name ?? ""
|
||||
}()
|
||||
|
||||
lazy var maxProxyNameLength:CGFloat = {
|
||||
let rect = CGSize(width: CGFloat.greatestFiniteMagnitude, height: 20)
|
||||
let attr = [NSAttributedString.Key.font: NSFont.menuBarFont(ofSize: 0)]
|
||||
return (self.longestProxyGroupName as NSString)
|
||||
.boundingRect(with: rect,
|
||||
options: .usesLineFragmentOrigin,
|
||||
attributes: attr).width;
|
||||
}()
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -16,21 +16,14 @@ class ProxyMenuItem:NSMenuItem {
|
|||
|
||||
proxyName = proxy.name
|
||||
|
||||
if let delay = proxy.history.first?.delay {
|
||||
|
||||
func getDelayDisplay() -> String {
|
||||
switch delay {
|
||||
case 0: return "fail"
|
||||
default:return "\(delay) ms"
|
||||
}
|
||||
}
|
||||
if let his = proxy.history.first {
|
||||
|
||||
let paragraph = NSMutableParagraphStyle()
|
||||
paragraph.tabStops = [
|
||||
NSTextTab(textAlignment: .right, location: maxProxyNameLength + 80, options: [:]),
|
||||
]
|
||||
|
||||
let str = "\(proxy.name)\t\(getDelayDisplay())"
|
||||
let str = "\(proxy.name)\t\(his.delayDisplay)"
|
||||
|
||||
let attributed = NSMutableAttributedString(
|
||||
string: str,
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module github.com/yichengchen/clashX/ClashX
|
||||
|
||||
require github.com/Dreamacro/clash v0.12.1-0.20190317065239-7a9d986ff38c
|
||||
require github.com/Dreamacro/clash v0.12.1-0.20190323082927-f99da37168ac
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
github.com/Dreamacro/clash v0.12.1-0.20190317065239-7a9d986ff38c h1:SRELShfh3m6DJxlnNqKdhAPNY2eXUvFZNsUtUlTrkzk=
|
||||
github.com/Dreamacro/clash v0.12.1-0.20190317065239-7a9d986ff38c/go.mod h1:jIxj6LTv5e5Yr+0Yt682at2dyXqUR9p16asV9yya6Vc=
|
||||
github.com/Dreamacro/clash v0.12.1-0.20190323082927-f99da37168ac h1:9WV1wjtHo9Gm9Dq1chmEjpJkefLC1ck64yzhd6aQXUA=
|
||||
github.com/Dreamacro/clash v0.12.1-0.20190323082927-f99da37168ac/go.mod h1:jIxj6LTv5e5Yr+0Yt682at2dyXqUR9p16asV9yya6Vc=
|
||||
github.com/Dreamacro/go-shadowsocks2 v0.1.3-0.20190202135136-da4602d8f112 h1:1axYxE0ZLJy40+ulq46XQt7MaJDJr4iGer1NQz7jmKw=
|
||||
github.com/Dreamacro/go-shadowsocks2 v0.1.3-0.20190202135136-da4602d8f112/go.mod h1:giIuN+TuUudTxHc1jjTOyyQYiJ3VXp1pWOHdJbSCAPo=
|
||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
||||
|
|
Loading…
Reference in New Issue