2018-08-04 21:49:32 +08:00
//
2018-11-30 22:14:20 +08:00
// M e n u I t e m F a c t o r y . s w i f t
2018-08-04 21:49:32 +08:00
// C l a s h X
//
// C r e a t e d b y C Y C o n 2 0 1 8 / 8 / 4 .
2018-08-08 13:47:38 +08:00
// C o p y r i g h t © 2 0 1 8 年 y i c h e n g c h e n . A l l r i g h t s r e s e r v e d .
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 {
2020-04-25 12:06:02 +08:00
private static var cachedProxyData : ClashProxyResp ?
2023-08-07 23:57:24 +08:00
static var useViewToRenderProxy : Bool = AppDelegate . isAboveMacOS152
2022-07-26 09:14:58 +08:00
2022-06-25 18:05:40 +08:00
static var hideUnselectable : Int = UserDefaults . standard . object ( forKey : " hideUnselectable " ) as ? Int ? ? NSControl . StateValue . off . rawValue {
didSet {
UserDefaults . standard . set ( hideUnselectable , forKey : " hideUnselectable " )
recreateProxyMenuItems ( )
}
}
2023-06-13 14:12:51 +08:00
2022-07-26 09:14:58 +08:00
2022-08-07 12:11:03 +08:00
static let updateAllProvidersTitle = NSLocalizedString ( " Update All Providers " , comment : " " )
2020-02-26 17:26:12 +08:00
2020-02-22 12:35:25 +08:00
// MARK: - P u b l i c
2020-02-22 11:46:49 +08:00
2020-04-25 12:06:02 +08:00
static func refreshExistingMenuItems ( ) {
2020-04-29 20:29:08 +08:00
ApiRequest . getMergedProxyData {
2020-04-25 12:06:02 +08:00
info in
2020-04-29 20:29:08 +08:00
if info ? . proxiesMap . keys != cachedProxyData ? . proxiesMap . keys {
2020-04-25 12:06:02 +08:00
// f o r c e u p d a t e m e n u
refreshMenuItems ( mergedData : info )
return
}
2020-06-20 11:48:21 +08:00
for proxy in info ? . proxies ? ? [ ] {
NotificationCenter . default . post ( name : . proxyUpdate ( for : proxy . name ) , object : proxy , userInfo : nil )
2020-04-25 12:06:02 +08:00
}
}
}
static func recreateProxyMenuItems ( ) {
2020-04-29 20:29:08 +08:00
ApiRequest . getMergedProxyData {
2020-04-25 12:06:02 +08:00
proxyInfo in
2020-04-29 20:29:08 +08:00
cachedProxyData = proxyInfo
2020-04-25 12:06:02 +08:00
refreshMenuItems ( mergedData : proxyInfo )
2019-10-06 12:22:21 +08:00
}
2020-04-25 12:06:02 +08:00
}
2022-07-26 09:14:58 +08:00
2022-07-12 12:35:21 +08:00
static func recreateRuleProvidersMenuItems ( ) {
ApiRequest . requestRuleProviderList {
refreshRuleProviderMenuItems ( $0 . allProviders . map ( { $0 . value } ) )
}
}
2020-04-25 12:06:02 +08:00
static func refreshMenuItems ( mergedData proxyInfo : ClashProxyResp ? ) {
2020-11-14 15:01:28 +08:00
let leftPadding = AppDelegate . shared . hasMenuSelected ( )
2020-04-25 12:06:02 +08:00
guard let proxyInfo = proxyInfo else { return }
2022-07-26 09:14:58 +08:00
2022-06-25 18:05:40 +08:00
let hideState = NSControl . StateValue ( rawValue : hideUnselectable )
2022-07-26 09:14:58 +08:00
2020-04-25 12:06:02 +08:00
var menuItems = [ NSMenuItem ] ( )
2022-07-03 22:08:38 +08:00
var collapsedItems = [ NSMenuItem ] ( )
2020-04-25 12:06:02 +08:00
for proxy in proxyInfo . proxyGroups {
var menu : NSMenuItem ?
switch proxy . type {
2020-11-14 15:01:28 +08:00
case . select : menu = generateSelectorMenuItem ( proxyGroup : proxy , proxyInfo : proxyInfo , leftPadding : leftPadding )
case . urltest , . fallback : menu = generateUrlTestFallBackMenuItem ( proxyGroup : proxy , proxyInfo : proxyInfo , leftPadding : leftPadding )
2020-04-25 12:06:02 +08:00
case . loadBalance :
2021-04-18 11:58:17 +08:00
menu = generateLoadBalanceMenuItem ( proxyGroup : proxy , proxyInfo : proxyInfo , leftPadding : leftPadding )
2020-04-25 12:06:02 +08:00
case . relay :
menu = generateListOnlyMenuItem ( proxyGroup : proxy , proxyInfo : proxyInfo )
default : continue
}
2022-07-03 22:08:38 +08:00
guard let menu = menu else {
continue
}
2024-01-26 16:41:20 +08:00
if let hidden = proxy . hidden , hidden {
continue
}
2022-07-26 09:14:58 +08:00
2022-07-03 22:08:38 +08:00
switch hideState {
case . mixed where [ . urltest , . fallback , . loadBalance , . relay ] . contains ( proxy . type ) :
collapsedItems . append ( menu )
menu . isEnabled = true
case . on where [ . urltest , . fallback , . loadBalance , . relay ] . contains ( proxy . type ) :
continue
default :
2020-04-25 12:06:02 +08:00
menuItems . append ( menu )
menu . isEnabled = true
}
2020-02-22 11:46:49 +08:00
}
2022-07-26 09:14:58 +08:00
2022-07-03 22:08:38 +08:00
if hideState = = . mixed {
let collapsedItem = NSMenuItem ( title : " Collapsed " , action : nil , keyEquivalent : " " )
collapsedItem . isEnabled = true
collapsedItem . submenu = . init ( title : " " )
collapsedItem . submenu ? . items = collapsedItems
2022-07-26 09:14:58 +08:00
2022-07-03 22:08:38 +08:00
menuItems . append ( collapsedItem )
}
2022-07-26 09:14:58 +08:00
2020-04-25 12:06:02 +08:00
let items = Array ( menuItems . reversed ( ) )
updateProxyList ( withMenus : items )
2022-07-26 09:14:58 +08:00
2022-07-11 22:21:29 +08:00
refreshProxyProviderMenuItems ( mergedData : proxyInfo )
2022-07-12 12:35:21 +08:00
recreateRuleProvidersMenuItems ( )
2020-04-25 12:06:02 +08:00
}
2019-10-20 13:40:50 +08:00
2020-05-10 23:36:43 +08:00
static func generateSwitchConfigMenuItems ( complete : @ escaping ( ( [ NSMenuItem ] ) -> Void ) ) {
let generateMenuItem : ( ( String ) -> NSMenuItem ) = {
config in
2020-04-25 12:06:02 +08:00
let item = NSMenuItem ( title : config , action : #selector ( MenuItemFactory . actionSelectConfig ( sender : ) ) , keyEquivalent : " " )
item . target = MenuItemFactory . self
item . state = ConfigManager . selectConfigName = = config ? . on : . off
2020-05-10 23:36:43 +08:00
return item
}
2022-06-19 14:48:24 +08:00
2021-12-08 20:18:35 +08:00
if RemoteControlManager . selectConfig != nil {
complete ( [ ] )
return
}
2020-05-10 23:36:43 +08:00
2022-11-20 12:08:46 +08:00
if ICloudManager . shared . useiCloud . value {
2022-06-19 14:48:24 +08:00
ICloudManager . shared . getConfigFilesList {
2020-05-10 23:36:43 +08:00
complete ( $0 . map { generateMenuItem ( $0 ) } )
}
} else {
complete ( ConfigManager . getConfigFilesList ( ) . map { generateMenuItem ( $0 ) } )
2020-04-25 12:06:02 +08:00
}
}
// MARK: - P r i v a t e
// MARK: U p d a t e r s
static func updateProxyList ( withMenus menus : [ NSMenuItem ] ) {
let app = AppDelegate . shared
let startIndex = app . statusMenu . items . firstIndex ( of : app . separatorLineTop ) ! + 1
let endIndex = app . statusMenu . items . firstIndex ( of : app . sepatatorLineEndProxySelect ) !
2023-07-16 12:16:15 +08:00
app . sepatatorLineEndProxySelect . isHidden = menus . isEmpty
2023-09-05 10:07:46 +08:00
for _ in 0 . . < endIndex - startIndex {
2020-04-25 12:06:02 +08:00
app . statusMenu . removeItem ( at : startIndex )
}
for each in menus {
app . statusMenu . insertItem ( each , at : startIndex )
2020-02-22 12:35:25 +08:00
}
}
2020-04-25 12:06:02 +08:00
// MARK: G e n e r a t o r s
2020-02-22 12:35:25 +08:00
private static func generateSelectorMenuItem ( proxyGroup : ClashProxy ,
2020-11-14 15:01:28 +08:00
proxyInfo : ClashProxyResp ,
2022-06-19 14:48:24 +08:00
leftPadding : Bool ) -> NSMenuItem ? {
2019-03-23 19:13:28 +08:00
let proxyMap = proxyInfo . proxiesMap
2019-10-20 13:40:50 +08:00
2020-04-08 11:24:13 +08:00
let isGlobalMode = ConfigManager . shared . currentConfig ? . mode = = . global
if ! isGlobalMode {
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 ? ? " "
2023-07-12 14:39:53 +08:00
if ! Settings . disableShowCurrentProxyInMenu {
2020-11-14 15:01:28 +08:00
menu . view = ProxyGroupMenuItemView ( group : proxyGroup . name , targetProxy : selectedName , hasLeftPadding : leftPadding )
2019-10-16 22:46:03 +08:00
}
2020-02-22 18:31:13 +08:00
let submenu = ProxyGroupMenu ( title : proxyGroup . name )
2019-10-20 13:40:50 +08:00
for proxy in proxyGroup . all ? ? [ ] {
guard let proxyModel = proxyMap [ proxy ] else { continue }
2020-02-24 19:58:09 +08:00
let proxyItem = ProxyMenuItem ( proxy : proxyModel ,
2020-04-26 16:40:29 +08:00
group : proxyGroup ,
2020-04-26 18:32:20 +08:00
action : #selector ( MenuItemFactory . actionSelectProxy ( sender : ) ) )
2018-11-30 22:14:20 +08:00
proxyItem . target = MenuItemFactory . self
2020-02-22 18:31:13 +08:00
submenu . add ( delegate : proxyItem )
2018-08-05 19:45:37 +08:00
submenu . addItem ( proxyItem )
2018-11-04 17:20:25 +08:00
}
2020-02-24 22:26:35 +08:00
2020-04-26 18:32:20 +08:00
if proxyGroup . isSpeedTestable && useViewToRenderProxy {
2020-02-24 22:26:35 +08:00
submenu . minimumWidth = proxyGroup . maxProxyNameLength + ProxyItemView . fixedPlaceHolderWidth
}
2019-10-16 22:46:03 +08:00
addSpeedTestMenuItem ( submenu , proxyGroup : proxyGroup )
menu . submenu = submenu
2018-08-05 19:45:37 +08:00
return menu
}
2019-10-20 13:40:50 +08:00
2020-11-14 15:01:28 +08:00
private static func generateUrlTestFallBackMenuItem ( proxyGroup : ClashProxy ,
proxyInfo : ClashProxyResp ,
2022-06-19 14:48:24 +08:00
leftPadding : Bool ) -> NSMenuItem ? {
2019-03-23 19:13:28 +08:00
let proxyMap = proxyInfo . proxiesMap
2019-03-17 22:00:47 +08:00
let selectedName = proxyGroup . now ? ? " "
2019-05-10 21:42:43 +08:00
let menu = NSMenuItem ( title : proxyGroup . name , action : nil , keyEquivalent : " " )
2023-07-12 14:39:53 +08:00
if ! Settings . disableShowCurrentProxyInMenu {
2020-11-14 15:01:28 +08:00
menu . view = ProxyGroupMenuItemView ( group : proxyGroup . name , targetProxy : selectedName , hasLeftPadding : leftPadding )
2019-10-16 22:46:03 +08:00
}
2019-03-17 22:00:47 +08:00
let submenu = NSMenu ( title : proxyGroup . name )
2018-08-05 19:45:37 +08:00
2019-03-23 19:13:28 +08:00
for proxyName in proxyGroup . all ? ? [ ] {
2019-10-20 13:40:50 +08:00
guard let proxy = proxyMap [ proxyName ] else { continue }
2020-04-26 18:32:20 +08:00
let proxyMenuItem = ProxyMenuItem ( proxy : proxy , group : proxyGroup , action : #selector ( empty ) , simpleItem : true )
2019-05-10 21:42:43 +08:00
proxyMenuItem . target = MenuItemFactory . self
2019-03-23 19:13:28 +08:00
if proxy . name = = selectedName {
proxyMenuItem . state = . on
}
2019-10-20 13:40:50 +08:00
2020-04-25 12:06:02 +08:00
proxyMenuItem . submenu = ProxyDelayHistoryMenu ( proxy : proxy )
2019-10-20 13:40:50 +08:00
2019-05-10 21:42:43 +08:00
submenu . addItem ( proxyMenuItem )
2019-03-23 19:13:28 +08:00
}
2019-12-11 22:04:53 +08:00
addSpeedTestMenuItem ( submenu , proxyGroup : proxyGroup )
2018-08-05 19:45:37 +08:00
menu . submenu = submenu
return menu
}
2019-10-20 13:40:50 +08:00
2020-02-22 18:31:13 +08:00
private static func addSpeedTestMenuItem ( _ menu : NSMenu , proxyGroup : ClashProxy ) {
2023-07-16 12:16:15 +08:00
guard ! proxyGroup . speedtestAble . isEmpty else { return }
2019-10-17 17:07:47 +08:00
let speedTestItem = ProxyGroupSpeedTestMenuItem ( group : proxyGroup )
2020-02-22 12:35:25 +08:00
let separator = NSMenuItem . separator ( )
2020-04-29 19:44:01 +08:00
menu . insertItem ( separator , at : 0 )
menu . insertItem ( speedTestItem , at : 0 )
2020-02-22 18:31:13 +08:00
( menu as ? ProxyGroupMenu ) ? . add ( delegate : speedTestItem )
2019-10-16 22:46:03 +08:00
}
2019-10-20 13:40:50 +08:00
2021-04-18 11:58:17 +08:00
private static func generateLoadBalanceMenuItem ( proxyGroup : ClashProxy , proxyInfo : ClashProxyResp , leftPadding : Bool ) -> NSMenuItem ? {
2019-03-23 19:13:28 +08:00
let proxyMap = proxyInfo . proxiesMap
2019-03-17 22:00:47 +08:00
let menu = NSMenuItem ( title : proxyGroup . name , action : nil , keyEquivalent : " " )
2023-07-12 14:39:53 +08:00
if ! Settings . disableShowCurrentProxyInMenu {
2021-04-18 11:58:17 +08:00
menu . view = ProxyGroupMenuItemView ( group : proxyGroup . name , targetProxy : NSLocalizedString ( " Load Balance " , comment : " " ) , hasLeftPadding : leftPadding , observeUpdate : false )
}
2020-02-22 18:31:13 +08:00
let submenu = ProxyGroupMenu ( 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 }
2019-03-17 23:32:37 +08:00
let proxyItem = ProxyMenuItem ( proxy : proxyModel ,
2020-04-26 16:40:29 +08:00
group : proxyGroup ,
2020-04-26 18:32:20 +08:00
action : #selector ( empty ) )
2019-03-23 19:13:28 +08:00
proxyItem . target = MenuItemFactory . self
2020-02-22 18:31:13 +08:00
submenu . add ( delegate : proxyItem )
2019-02-15 22:47:17 +08:00
submenu . addItem ( proxyItem )
}
2020-04-26 18:32:20 +08:00
if proxyGroup . isSpeedTestable && useViewToRenderProxy {
2020-02-24 22:26:35 +08:00
submenu . minimumWidth = proxyGroup . maxProxyNameLength + ProxyItemView . fixedPlaceHolderWidth
}
2019-12-11 22:04:53 +08:00
addSpeedTestMenuItem ( submenu , proxyGroup : proxyGroup )
2019-02-15 22:47:17 +08:00
menu . submenu = submenu
2019-10-20 13:40:50 +08:00
2019-02-15 22:47:17 +08:00
return menu
}
2020-03-24 23:34:57 +08:00
private static func generateListOnlyMenuItem ( proxyGroup : ClashProxy , proxyInfo : ClashProxyResp ) -> NSMenuItem ? {
let menu = NSMenuItem ( title : proxyGroup . name , action : nil , keyEquivalent : " " )
let submenu = ProxyGroupMenu ( title : proxyGroup . name )
let proxyMap = proxyInfo . proxiesMap
for proxy in proxyGroup . all ? ? [ ] {
guard let proxyModel = proxyMap [ proxy ] else { continue }
let proxyItem = ProxyMenuItem ( proxy : proxyModel ,
2020-04-26 16:40:29 +08:00
group : proxyGroup ,
2020-03-24 23:34:57 +08:00
action : #selector ( empty ) ,
2020-04-26 18:32:20 +08:00
simpleItem : true )
2020-03-24 23:34:57 +08:00
proxyItem . target = MenuItemFactory . self
submenu . add ( delegate : proxyItem )
submenu . addItem ( proxyItem )
}
menu . submenu = submenu
return menu
}
2020-02-22 12:35:25 +08:00
}
2019-10-20 13:40:50 +08:00
2020-02-22 12:35:25 +08:00
// MARK: - E x p e r i m e n t a l
extension MenuItemFactory {
static func addExperimentalMenuItem ( _ menu : inout NSMenu ) {
2020-02-26 17:26:12 +08:00
let useViewRender = NSMenuItem ( title : NSLocalizedString ( " Enhance proxy list render " , comment : " " ) , action : #selector ( optionUseViewRenderMenuItemTap ( sender : ) ) , keyEquivalent : " " )
useViewRender . target = self
menu . addItem ( useViewRender )
updateUseViewRenderMenuItem ( useViewRender )
2020-02-22 12:35:25 +08:00
}
2020-02-26 17:26:12 +08:00
static func updateUseViewRenderMenuItem ( _ item : NSMenuItem ) {
item . state = useViewToRenderProxy ? . on : . off
}
@objc static func optionUseViewRenderMenuItemTap ( sender : NSMenuItem ) {
useViewToRenderProxy = ! useViewToRenderProxy
updateUseViewRenderMenuItem ( sender )
2020-04-25 12:06:02 +08:00
recreateProxyMenuItems ( )
2018-11-30 22:14:20 +08:00
}
}
2022-07-05 14:38:39 +08:00
// MARK: - M e t a
extension MenuItemFactory {
2022-07-26 09:14:58 +08:00
2022-07-11 22:21:29 +08:00
static func refreshProxyProviderMenuItems ( mergedData proxyInfo : ClashProxyResp ? ) {
2022-07-05 14:38:39 +08:00
let app = AppDelegate . shared
guard let proxyInfo = proxyInfo ,
let menu = app . proxyProvidersMenu ,
let providers = proxyInfo . enclosingProviderResp
else { return }
2022-07-12 12:59:32 +08:00
2022-07-12 12:35:21 +08:00
let proxyProviders = providers . allProviders . filter {
$0 . value . vehicleType = = . HTTP
} . values . sorted ( by : { $0 . name < $1 . name } )
2022-07-26 09:14:58 +08:00
2022-07-12 12:59:32 +08:00
let isEmpty = proxyProviders . count = = 0
app . proxyProvidersMenuItem . isEnabled = ! isEmpty
guard ! isEmpty else { return }
initUpdateAllProvidersMenuItem ( for : menu , type : . proxy )
2022-07-12 12:35:21 +08:00
let maxNameLength = maxProvidersLength ( for : proxyProviders . map ( { $0 . name } ) )
proxyProviders . forEach { provider in
let item = DualTitleMenuItem (
provider . name ,
subTitle : providerUpdateTitle ( provider . updatedAt ) ,
action : #selector ( actionUpdateSelectProvider ) ,
maxLength : maxNameLength )
item . tag = ApiRequest . ProviderType . proxy . rawValue
item . target = self
menu . addItem ( item )
}
}
2022-07-26 09:14:58 +08:00
2022-07-12 12:35:21 +08:00
static func refreshRuleProviderMenuItems ( _ ruleProviders : [ ClashRuleProvider ] ) {
let app = AppDelegate . shared
2022-07-12 12:59:32 +08:00
let isEmpty = ruleProviders . count = = 0
app . ruleProvidersMenuItem . isEnabled = ! isEmpty
2022-07-26 09:14:58 +08:00
2022-07-12 12:59:32 +08:00
guard ! isEmpty ,
let menu = app . ruleProvidersMenu
else { return }
2022-07-26 09:14:58 +08:00
2022-07-12 12:59:32 +08:00
initUpdateAllProvidersMenuItem ( for : menu , type : . rule )
2022-07-12 12:35:21 +08:00
let maxNameLength = maxProvidersLength ( for : ruleProviders . map ( { $0 . name } ) )
ruleProviders . sorted ( by : { $0 . name < $1 . name } )
. forEach { provider in
let item = DualTitleMenuItem (
provider . name ,
subTitle : providerUpdateTitle ( provider . updatedAt ) ,
action : #selector ( actionUpdateSelectProvider ) ,
maxLength : maxNameLength )
item . tag = ApiRequest . ProviderType . rule . rawValue
item . target = self
menu . addItem ( item )
}
}
2022-07-26 09:14:58 +08:00
2022-07-12 12:35:21 +08:00
static func initUpdateAllProvidersMenuItem ( for menu : NSMenu , type : ApiRequest . ProviderType ) {
2022-07-05 14:38:39 +08:00
if menu . items . count > 1 {
menu . items . enumerated ( ) . filter {
$0 . offset > 1
} . forEach {
menu . removeItem ( $0 . element )
}
} else {
2022-07-12 12:35:21 +08:00
let updateAllItem = NSMenuItem ( title : updateAllProvidersTitle , action : #selector ( actionUpdateAllProviders ) , keyEquivalent : " " )
updateAllItem . tag = type . rawValue
2022-07-05 14:38:39 +08:00
updateAllItem . target = self
menu . addItem ( updateAllItem )
menu . addItem ( . separator ( ) )
}
2022-07-12 12:35:21 +08:00
}
2022-07-26 09:14:58 +08:00
2022-07-12 12:35:21 +08:00
static func maxProvidersLength ( for names : [ String ] ) -> CGFloat {
func getLength ( _ string : String ) -> CGFloat {
let rect = CGSize ( width : CGFloat . greatestFiniteMagnitude , height : 20 )
let attr = [ NSAttributedString . Key . font : NSFont . menuBarFont ( ofSize : 14 ) ]
let length = ( string as NSString )
. boundingRect ( with : rect ,
options : . usesLineFragmentOrigin ,
attributes : attr ) . width
return length
}
2022-07-26 09:14:58 +08:00
2022-07-12 12:35:21 +08:00
var lengths = names . map {
getLength ( $0 ) + 65
}
lengths . append ( getLength ( updateAllProvidersTitle ) )
return lengths . max ( ) ? ? 0
}
2022-07-26 09:14:58 +08:00
2022-07-12 12:35:21 +08:00
static func providerUpdateTitle ( _ updatedAt : String ? ) -> String ? {
let dateCF = DateComponentsFormatter ( )
dateCF . allowedUnits = [ . day , . hour , . minute ]
dateCF . maximumUnitCount = 1
dateCF . unitsStyle = . abbreviated
dateCF . zeroFormattingBehavior = . dropAll
2022-07-26 09:14:58 +08:00
2022-07-12 12:35:21 +08:00
guard let dateStr = updatedAt ,
let date = DateFormatter . provider . date ( from : dateStr ) ,
! date . timeIntervalSinceNow . isNaN ,
! date . timeIntervalSinceNow . isInfinite ,
let re = dateCF . string ( from : abs ( date . timeIntervalSinceNow ) ) else { return nil }
2022-07-26 09:14:58 +08:00
2022-08-07 12:11:03 +08:00
return re + NSLocalizedString ( " ago " , comment : " Provider update time title " )
2022-07-05 14:38:39 +08:00
}
2022-07-26 09:14:58 +08:00
2022-07-12 12:35:21 +08:00
@objc static func actionUpdateAllProviders ( sender : NSMenuItem ) {
let type = ApiRequest . ProviderType ( rawValue : sender . tag ) !
let s = " Update All \( type . logString ( ) ) Providers "
2022-07-05 14:38:39 +08:00
Logger . log ( s )
2022-07-12 12:35:21 +08:00
ApiRequest . updateAllProviders ( for : type ) {
2022-07-05 14:38:39 +08:00
Logger . log ( " \( s ) \( $0 ) failed " )
let info = $0 = = 0 ? " Success " : " \( $0 ) failed "
NSUserNotificationCenter . default . post ( title : s , info : info )
recreateProxyMenuItems ( )
}
}
2022-07-26 09:14:58 +08:00
2022-07-12 12:35:21 +08:00
@objc static func actionUpdateSelectProvider ( sender : DualTitleMenuItem ) {
2022-07-05 14:38:39 +08:00
let name = sender . originTitle
2022-07-12 12:35:21 +08:00
let type = ApiRequest . ProviderType ( rawValue : sender . tag ) !
2022-07-26 09:14:58 +08:00
2022-07-12 12:35:21 +08:00
let log = " Update \( type . logString ( ) ) Provider \( name ) "
2022-07-05 14:38:39 +08:00
Logger . log ( log )
2022-07-12 12:35:21 +08:00
ApiRequest . updateProvider ( for : type , name : name ) {
2022-07-05 14:38:39 +08:00
let info = $0 ? " Success " : " Failed "
Logger . log ( " \( log ) info " )
NSUserNotificationCenter . default . post ( title : log , info : info )
recreateProxyMenuItems ( )
}
}
}
2020-02-22 12:35:25 +08:00
// MARK: - A c t i o n
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 }
2018-12-09 00:46:36 +08:00
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
2018-08-06 23:06:50 +08:00
// r e m e m b e r s e l e c t p r o x y
2019-11-01 20:47:55 +08:00
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-01 20:47:55 +08:00
}
2019-11-02 00:04:42 +08:00
ConfigManager . selectedProxyRecords . append ( newModel )
2019-10-28 14:47:47 +08:00
// t e r m i n a l C o n n e c t i o n s f o r t h i s g r o u p
ConnectionManager . closeConnection ( for : proxyGroup )
2020-02-22 11:46:49 +08:00
// r e f r e s h m e n u i t e m s
2020-04-25 12:06:02 +08:00
MenuItemFactory . refreshExistingMenuItems ( )
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
2019-10-28 14:47:47 +08:00
AppDelegate . shared . updateConfig ( configName : config , showNotification : false ) {
err in
if err = = nil {
2019-11-21 22:43:46 +08:00
ConnectionManager . closeAllConnection ( )
2019-10-28 14:47:47 +08:00
}
}
2018-11-30 22:14:20 +08:00
}
2018-10-02 12:05:55 +08:00
2019-10-20 13:40:50 +08:00
@objc static func empty ( ) { }
}