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

201 lines
7.6 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 RxCocoa
2019-10-20 13:40:50 +08:00
import SwiftyJSON
2018-08-04 21:49:32 +08:00
2018-11-30 22:14:20 +08:00
class MenuItemFactory {
2019-10-20 13:40:50 +08:00
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
}
2019-10-20 13:40:50 +08:00
ApiRequest.requestProxyGroupList() {
proxyInfo in
var menuItems = [NSMenuItem]()
2019-10-20 13:40:50 +08:00
for proxy in proxyInfo.proxyGroups {
2019-10-20 13:40:50 +08:00
var menu: NSMenuItem?
switch proxy.type {
case .select: menu = self.generateSelectorMenuItem(proxyGroup: proxy, proxyInfo: proxyInfo)
2019-10-20 13:40:50 +08:00
case .urltest, .fallback: menu = generateUrlTestFallBackMenuItem(proxyGroup: proxy, proxyInfo: proxyInfo)
case .loadBalance:
menu = generateLoadBalanceMenuItem(proxyGroup: proxy, proxyInfo: proxyInfo)
default: continue
}
2019-10-20 13:40:50 +08:00
if let menu = menu {
menuItems.append(menu)
2019-10-20 13:40:50 +08:00
menu.isEnabled = true
}
2018-08-04 21:49:32 +08:00
}
completionHandler(menuItems.reversed())
2018-08-04 21:49:32 +08:00
}
}
2019-10-20 13:40:50 +08:00
static func generateSelectorMenuItem(proxyGroup: ClashProxy,
proxyInfo: ClashProxyResp) -> NSMenuItem? {
let proxyMap = proxyInfo.proxiesMap
2019-10-20 13:40:50 +08:00
let isGlobalMode = ConfigManager.shared.currentConfig?.mode == .global
if isGlobalMode {
2019-10-20 13:40:50 +08:00
if proxyGroup.name != "GLOBAL" { return nil }
} else {
2019-10-20 13:40:50 +08:00
if proxyGroup.name == "GLOBAL" { return nil }
}
2019-10-20 13:40:50 +08:00
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-10-20 13:40:50 +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:)),
2019-10-20 13:40:50 +08:00
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-10-20 13:40:50 +08:00
if proxyItem.isSelected { hasSelected = true }
submenu.addItem(proxyItem)
}
2019-10-20 13:40:50 +08:00
if !hasSelected && submenu.items.count > 0 {
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
}
2019-10-20 13:40:50 +08:00
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)
for proxyName in proxyGroup.all ?? [] {
2019-10-20 13:40:50 +08:00
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
}
2019-10-20 13:40:50 +08:00
if let historyMenu = generateHistoryMenu(proxy) {
proxyMenuItem.submenu = historyMenu
}
2019-10-20 13:40:50 +08:00
submenu.addItem(proxyMenuItem)
}
menu.submenu = submenu
return menu
}
2019-10-20 13:40:50 +08:00
2019-10-16 22:46:03 +08:00
static func addSpeedTestMenuItem(_ menus: NSMenu, proxyGroup: ClashProxy) {
2019-10-20 13:40:50 +08:00
guard proxyGroup.speedtestAble.count > 0 else { return }
2019-10-16 22:46:03 +08:00
menus.addItem(NSMenuItem.separator())
let speedTestItem = ProxyGroupSpeedTestMenuItem(group: proxyGroup)
2019-10-16 22:46:03 +08:00
speedTestItem.target = MenuItemFactory.self
speedTestItem.action = #selector(empty)
2019-10-16 22:46:03 +08:00
menus.addItem(speedTestItem)
}
2019-10-20 13:40:50 +08:00
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
}
2019-10-20 13:40:50 +08:00
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-10-20 13:40:50 +08:00
2019-03-17 22:00:47 +08:00
for proxy in proxyGroup.all ?? [] {
2019-10-20 13:40:50 +08:00
guard let proxyModel = proxyMap[proxy] else { continue }
let proxyItem = ProxyMenuItem(proxy: proxyModel,
2019-10-20 13:40:50 +08:00
action: #selector(empty),
maxProxyNameLength: proxyGroup.maxProxyNameLength)
proxyItem.isSelected = false
proxyItem.target = MenuItemFactory.self
submenu.addItem(proxyItem)
}
2019-10-20 13:40:50 +08:00
menu.submenu = submenu
2019-10-20 13:40:50 +08:00
return menu
}
2019-10-20 13:40:50 +08:00
2019-10-20 00:10:27 +08:00
static func generateSwitchConfigMenuItems() -> [NSMenuItem] {
var items = [NSMenuItem]()
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
2019-10-20 00:10:27 +08:00
items.append(item)
2018-11-30 22:14:20 +08:00
}
2019-10-20 00:10:27 +08:00
return items
2018-11-30 22:14:20 +08:00
}
}
extension MenuItemFactory {
2019-10-20 13:40:50 +08:00
@objc static func actionSelectProxy(sender: ProxyMenuItem) {
guard let proxyGroup = sender.menu?.title else { return }
let proxyName = sender.proxyName
2019-10-20 13:40:50 +08:00
ApiRequest.updateProxyGroup(group: proxyGroup, selectProxy: proxyName) { success in
if success {
2018-08-04 21:49:32 +08:00
for items in sender.menu?.items ?? [NSMenuItem]() {
items.state = .off
}
sender.state = .on
// remember select proxy
let newModel = SavedProxyModel(group: proxyGroup, selected: proxyName, config: ConfigManager.selectConfigName)
2019-11-02 00:04:42 +08:00
ConfigManager.selectedProxyRecords.removeAll { model -> Bool in
2019-12-11 20:27:17 +08:00
return model.key == newModel.key
}
2019-11-02 00:04:42 +08:00
ConfigManager.selectedProxyRecords.append(newModel)
// terminal Connections for this group
ConnectionManager.closeConnection(for: proxyGroup)
2018-08-04 21:49:32 +08:00
}
}
}
2019-10-20 13:40:50 +08:00
@objc static func actionSelectConfig(sender: NSMenuItem) {
2018-11-30 22:14:20 +08:00
let config = sender.title
AppDelegate.shared.updateConfig(configName: config, showNotification: false) {
err in
if err == nil {
ConnectionManager.closeAllConnection()
}
}
2018-11-30 22:14:20 +08:00
}
2019-10-20 13:40:50 +08:00
@objc static func empty() {}
}