Feature: show speedtest history in proxy group

This commit is contained in:
yicheng 2019-03-23 19:13:28 +08:00
parent 670ad02b49
commit 61e87ed07c
5 changed files with 94 additions and 30 deletions

View File

@ -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(){}
}

View File

@ -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;
}()
}

View File

@ -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,

View File

@ -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

View File

@ -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=