ClashX.Meta/ClashX/General/Managers/MenuItemFactory.swift

223 lines
8.3 KiB
Swift
Raw Normal View History

2018-08-04 21:49:32 +08:00
//
2018-11-30 22:14:20 +08:00
// MenuItemFactory.swift
2018-08-04 21:49:32 +08:00
// ClashX
//
// Created by CYC on 2018/8/4.
2018-08-08 13:47:38 +08:00
// Copyright © 2018 yichengchen. All rights reserved.
2018-08-04 21:49:32 +08:00
//
import Cocoa
import SwiftyJSON
import RxCocoa
2018-11-30 22:14:20 +08:00
class MenuItemFactory {
static func menuItems(completionHandler: @escaping (([NSMenuItem])->Void)){
2019-10-06 12:22:21 +08:00
if ConfigManager.shared.currentConfig?.mode == .direct {
completionHandler([])
return
2019-10-06 12:22:21 +08:00
}
ApiRequest.requestProxyGroupList() {
proxyInfo in
var menuItems = [NSMenuItem]()
for proxy in proxyInfo.proxyGroups {
var menu:NSMenuItem?
switch proxy.type {
case .select: menu = self.generateSelectorMenuItem(proxyGroup: proxy, proxyInfo: proxyInfo)
case .urltest,.fallback: menu = generateUrlTestFallBackMenuItem(proxyGroup: proxy, proxyInfo: proxyInfo)
case .loadBalance:
menu = generateLoadBalanceMenuItem(proxyGroup: proxy, proxyInfo: proxyInfo)
default: continue
}
if let menu = menu {
menuItems.append(menu)
menu.isEnabled=true
}
2018-08-04 21:49:32 +08:00
}
completionHandler(menuItems.reversed())
2018-08-04 21:49:32 +08:00
}
}
static func generateSelectorMenuItem(proxyGroup:ClashProxy,
proxyInfo:ClashProxyResp) -> NSMenuItem? {
let proxyMap = proxyInfo.proxiesMap
let isGlobalMode = ConfigManager.shared.currentConfig?.mode == .global
if isGlobalMode {
2019-03-17 22:00:47 +08:00
if proxyGroup.name != "GLOBAL" {return nil}
} else {
2019-03-17 22:00:47 +08:00
if proxyGroup.name == "GLOBAL" {return nil}
}
2019-03-17 22:00:47 +08:00
let menu = NSMenuItem(title: proxyGroup.name, action: nil, keyEquivalent: "")
let selectedName = proxyGroup.now ?? ""
2019-10-16 22:46:03 +08:00
if !ConfigManager.shared.disableShowCurrentProxyInMenu {
menu.view = ProxyGroupMenuItemView(group: proxyGroup.name, targetProxy: selectedName)
}
2019-03-17 22:00:47 +08:00
let submenu = NSMenu(title: proxyGroup.name)
var hasSelected = false
2019-03-17 22:00:47 +08:00
for proxy in proxyGroup.all ?? []{
guard let proxyModel = proxyMap[proxy] else {continue}
if isGlobalMode && proxyModel.type == .select {
2019-03-17 22:00:47 +08:00
continue
}
let proxyItem = ProxyMenuItem(proxy: proxyModel, action: #selector(MenuItemFactory.actionSelectProxy(sender:)),
maxProxyNameLength:proxyGroup.maxProxyNameLength)
2018-11-30 22:14:20 +08:00
proxyItem.target = MenuItemFactory.self
2019-03-17 22:00:47 +08:00
proxyItem.isSelected = proxy == selectedName
2019-02-18 21:38:34 +08:00
if proxyItem.isSelected {hasSelected = true}
submenu.addItem(proxyItem)
}
if (!hasSelected && submenu.items.count>0) {
self.actionSelectProxy(sender: submenu.items[0] as! ProxyMenuItem)
}
2019-10-16 22:46:03 +08:00
addSpeedTestMenuItem(submenu, proxyGroup: proxyGroup)
menu.submenu = submenu
if !ConfigManager.shared.disableShowCurrentProxyInMenu {
menu.view = ProxyGroupMenuItemView(group: proxyGroup.name, targetProxy: selectedName)
}
return menu
}
static func generateUrlTestFallBackMenuItem(proxyGroup:ClashProxy,proxyInfo:ClashProxyResp)->NSMenuItem? {
let proxyMap = proxyInfo.proxiesMap
2019-03-17 22:00:47 +08:00
let selectedName = proxyGroup.now ?? ""
let menu = NSMenuItem(title: proxyGroup.name, action: nil, keyEquivalent: "")
2019-10-16 22:46:03 +08:00
if !ConfigManager.shared.disableShowCurrentProxyInMenu {
menu.view = ProxyGroupMenuItemView(group: proxyGroup.name, targetProxy: selectedName)
}
2019-03-17 22:00:47 +08:00
let submenu = NSMenu(title: proxyGroup.name)
let nowMenuItem = NSMenuItem(title: "now:\(selectedName)", action: #selector(empty), keyEquivalent: "")
nowMenuItem.target = MenuItemFactory.self
if let nowProxy = proxyMap[selectedName],let historyMenu = generateHistoryMenu(nowProxy) {
nowMenuItem.submenu = historyMenu
}
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: #selector(empty), keyEquivalent: "")
proxyMenuItem.target = MenuItemFactory.self
if proxy.name == selectedName {
proxyMenuItem.state = .on
}
if let historyMenu = generateHistoryMenu(proxy){
proxyMenuItem.submenu = historyMenu
}
submenu.addItem(proxyMenuItem)
}
menu.submenu = submenu
return menu
}
2019-10-16 22:46:03 +08:00
static func addSpeedTestMenuItem(_ menus: NSMenu, proxyGroup: ClashProxy) {
menus.addItem(NSMenuItem.separator())
let speedTestItem = ProxyGroupSpeedTestMenuItem(group: proxyGroup, selector: #selector(actionSpeedTestGroup(sender:)))
speedTestItem.target = MenuItemFactory.self
menus.addItem(speedTestItem)
}
static func generateHistoryMenu(_ proxy:ClashProxy) -> NSMenu? {
let historyMenu = NSMenu(title: "")
for his in proxy.history {
historyMenu.addItem(
NSMenuItem(title: "\(his.dateDisplay) \(his.delayDisplay)", action: nil, keyEquivalent: ""))
}
return historyMenu.items.count > 0 ? historyMenu : nil
}
static func generateLoadBalanceMenuItem(proxyGroup:ClashProxy, proxyInfo:ClashProxyResp)->NSMenuItem? {
let proxyMap = proxyInfo.proxiesMap
2019-03-17 22:00:47 +08:00
let menu = NSMenuItem(title: proxyGroup.name, action: nil, keyEquivalent: "")
let submenu = NSMenu(title: proxyGroup.name)
2019-03-17 22:00:47 +08:00
for proxy in proxyGroup.all ?? [] {
guard let proxyModel = proxyMap[proxy] else {continue}
let proxyItem = ProxyMenuItem(proxy: proxyModel,
action:#selector(empty),
maxProxyNameLength:proxyGroup.maxProxyNameLength)
proxyItem.isSelected = false
proxyItem.target = MenuItemFactory.self
submenu.addItem(proxyItem)
}
menu.submenu = submenu
return menu
}
2018-11-30 22:14:20 +08:00
2018-12-01 22:57:39 +08:00
static func generateSwitchConfigSubMenu() -> NSMenu {
let subMenu = NSMenu(title: "Switch Configs")
2018-11-30 22:14:20 +08:00
for config in ConfigManager.getConfigFilesList() {
let item = NSMenuItem(title: config, action: #selector(MenuItemFactory.actionSelectConfig(sender:)), keyEquivalent: "")
item.target = MenuItemFactory.self
item.state = ConfigManager.selectConfigName == config ? .on : .off
2018-12-01 22:57:39 +08:00
subMenu.addItem(item)
2018-11-30 22:14:20 +08:00
}
2018-12-01 22:57:39 +08:00
return subMenu
2018-11-30 22:14:20 +08:00
}
}
extension MenuItemFactory {
@objc static func actionSelectProxy(sender:ProxyMenuItem){
2018-08-04 21:49:32 +08:00
guard let proxyGroup = sender.menu?.title else {return}
let proxyName = sender.proxyName
2018-08-04 21:49:32 +08:00
ApiRequest.updateProxyGroup(group: proxyGroup, selectProxy: proxyName) { (success) in
if (success) {
for items in sender.menu?.items ?? [NSMenuItem]() {
items.state = .off
}
sender.state = .on
// remember select proxy
ConfigManager.selectedProxyMap[proxyGroup] = proxyName
2018-08-04 21:49:32 +08:00
}
}
}
2018-11-30 22:14:20 +08:00
@objc static func actionSelectConfig(sender:NSMenuItem){
let config = sender.title
ConfigManager.selectConfigName = config
NotificationCenter.default.post(name: kShouldUpDateConfig,
object: nil,
userInfo: ["notification": false])
2018-11-30 22:14:20 +08:00
}
2019-10-16 22:46:03 +08:00
@objc static func actionSpeedTestGroup(sender: ProxyGroupSpeedTestMenuItem) {
let testGroup = DispatchGroup()
for proxyName in sender.proxyGroup.all ?? [] {
testGroup.enter()
ApiRequest.getProxyDelay(proxyName: proxyName) { delay in
testGroup.leave()
}
}
testGroup.notify(queue: DispatchQueue.main, execute: {
NSUserNotificationCenter.default.postSpeedTestFinishNotice()
})
}
@objc static func empty(){}
2018-08-04 21:49:32 +08:00
}