diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d7344b28e..41bd274c6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,17 +11,15 @@ jobs: build: runs-on: macos-13 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: FranzDiebold/github-env-vars-action@v2 - - name: download meta core - uses: robinraju/release-downloader@v1.8 + uses: robinraju/release-downloader@v1.9 with: repository: 'MetaCubeX/mihomo' - tag: "v1.18.0" + tag: "v1.18.1" fileName: ".*darwin.*64-v.*.gz" # releaseId: "62870807" @@ -35,8 +33,8 @@ jobs: /usr/libexec/PlistBuddy -c "Set CFBundleVersion $(git rev-list --count origin/master..origin/meta)" ClashX/Info.plist /usr/libexec/PlistBuddy -c "Set CFBundleShortVersionString $(git describe --tags --abbrev=0)" ClashX/Info.plist /usr/libexec/PlistBuddy -c "Add coreVersion string $(ls clash.meta | grep -m1 "" | sed -ne 's/.*64-\(.*\).gz/\1/p')" ClashX/Info.plist - /usr/libexec/PlistBuddy -c "Add gitBranch string $CI_ACTION_REF_NAME" ClashX/Info.plist - /usr/libexec/PlistBuddy -c "Add gitCommit string $CI_SHA_SHORT" ClashX/Info.plist + /usr/libexec/PlistBuddy -c "Add gitBranch string $GITHUB_REF_NAME" ClashX/Info.plist + /usr/libexec/PlistBuddy -c "Add gitCommit string ${GITHUB_SHA::7}" ClashX/Info.plist /usr/libexec/PlistBuddy -c "Add buildTime string $(date +%Y-%m-%d\ %H:%M)" ClashX/Info.plist /usr/libexec/PlistBuddy -c 'Print CFBundleVersion' ClashX/Info.plist @@ -51,8 +49,8 @@ jobs: /usr/libexec/PlistBuddy -c "Set CFBundleVersion $(git rev-list --count origin/master..origin/meta)" ClashX/ClashX\ Meta\ SwiftUI-Info.plist /usr/libexec/PlistBuddy -c "Set CFBundleShortVersionString $(git describe --tags --abbrev=0)" ClashX/ClashX\ Meta\ SwiftUI-Info.plist /usr/libexec/PlistBuddy -c "Add coreVersion string $(ls clash.meta | grep -m1 "" | sed -ne 's/.*64-\(.*\).gz/\1/p')" ClashX/ClashX\ Meta\ SwiftUI-Info.plist - /usr/libexec/PlistBuddy -c "Add gitBranch string $CI_ACTION_REF_NAME" ClashX/ClashX\ Meta\ SwiftUI-Info.plist - /usr/libexec/PlistBuddy -c "Add gitCommit string $CI_SHA_SHORT" ClashX/ClashX\ Meta\ SwiftUI-Info.plist + /usr/libexec/PlistBuddy -c "Add gitBranch string $GITHUB_REF_NAME" ClashX/ClashX\ Meta\ SwiftUI-Info.plist + /usr/libexec/PlistBuddy -c "Add gitCommit string ${GITHUB_SHA::7}" ClashX/ClashX\ Meta\ SwiftUI-Info.plist /usr/libexec/PlistBuddy -c "Add buildTime string $(date +%Y-%m-%d\ %H:%M)" ClashX/ClashX\ Meta\ SwiftUI-Info.plist /usr/libexec/PlistBuddy -c 'Print CFBundleVersion' ClashX/ClashX\ Meta\ SwiftUI-Info.plist @@ -88,7 +86,7 @@ jobs: - name: upload Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: "!startsWith(github.ref, 'refs/tags/')" with: name: "ClashX Meta.zip" diff --git a/ClashX.xcodeproj/project.pbxproj b/ClashX.xcodeproj/project.pbxproj index 89f0631ac..f1c10c8d0 100644 --- a/ClashX.xcodeproj/project.pbxproj +++ b/ClashX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 53; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -32,6 +32,9 @@ 01B2274B29B845F100FE35C9 /* country.mmdb.gz in Resources */ = {isa = PBXBuildFile; fileRef = 01B2274A29B845F100FE35C9 /* country.mmdb.gz */; }; 01BC9ABE2928EB5A00F9B177 /* MetaDNS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01BC9ABD2928E5C600F9B177 /* MetaDNS.swift */; }; 01C1462A28962E4E00346AF3 /* com.metacubex.ClashX.ProxyConfigHelper.meta.gz in Resources */ = {isa = PBXBuildFile; fileRef = 01C1462928962E4E00346AF3 /* com.metacubex.ClashX.ProxyConfigHelper.meta.gz */; }; + 01CA6BC02B6A1B3100E386D6 /* MetaServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01CA6BBF2B6A1B3100E386D6 /* MetaServer.swift */; }; + 01CA6BC12B6A1B3100E386D6 /* MetaServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01CA6BBF2B6A1B3100E386D6 /* MetaServer.swift */; }; + 01CA6BC22B6A1B3100E386D6 /* MetaServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01CA6BBF2B6A1B3100E386D6 /* MetaServer.swift */; }; 01D567E32AD158B600CDA0AE /* MetaPrefs.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 01D567E12AD158B500CDA0AE /* MetaPrefs.storyboard */; }; 01D567E42AD158B600CDA0AE /* MetaPrefs.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 01D567E12AD158B500CDA0AE /* MetaPrefs.storyboard */; }; 01D567E52AD158B600CDA0AE /* MetaPrefsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D567E22AD158B500CDA0AE /* MetaPrefsViewController.swift */; }; @@ -314,6 +317,7 @@ 01B2274A29B845F100FE35C9 /* country.mmdb.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = country.mmdb.gz; sourceTree = ""; }; 01BC9ABD2928E5C600F9B177 /* MetaDNS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetaDNS.swift; sourceTree = ""; }; 01C1462928962E4E00346AF3 /* com.metacubex.ClashX.ProxyConfigHelper.meta.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = com.metacubex.ClashX.ProxyConfigHelper.meta.gz; sourceTree = ""; }; + 01CA6BBF2B6A1B3100E386D6 /* MetaServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetaServer.swift; sourceTree = ""; }; 01D567DF2AD1562700CDA0AE /* ClashX Meta SwiftUI-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ClashX Meta SwiftUI-Info.plist"; sourceTree = ""; }; 01D567E12AD158B500CDA0AE /* MetaPrefs.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = MetaPrefs.storyboard; sourceTree = ""; }; 01D567E22AD158B500CDA0AE /* MetaPrefsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetaPrefsViewController.swift; sourceTree = ""; }; @@ -778,6 +782,7 @@ 498960722340F21C00AFB7EC /* com.metacubex.ClashX.ProxyConfigHelper.entitlements */, 019A239528657A7A00AE5698 /* main.swift */, 0162E74E2864B819007218A6 /* MetaTask.swift */, + 01CA6BBF2B6A1B3100E386D6 /* MetaServer.swift */, 01BC9ABD2928E5C600F9B177 /* MetaDNS.swift */, F935B2F12307C802009E4D33 /* Helper-Launchd.plist */, F935B2EA2307B6BA009E4D33 /* Helper-Info.plist */, @@ -994,6 +999,7 @@ files = ( 01F335CD2AD10D0B0048AF77 /* UnsafePointer+bridge.swift in Sources */, 01F335CE2AD10D0B0048AF77 /* RemoteConfigViewController.swift in Sources */, + 01CA6BC22B6A1B3100E386D6 /* MetaServer.swift in Sources */, 01F335CF2AD10D0B0048AF77 /* StatusItemTool.swift in Sources */, 01F335D02AD10D0B0048AF77 /* ClashResourceManager.swift in Sources */, 01F335D12AD10D0B0048AF77 /* ConfigFileManager.swift in Sources */, @@ -1089,6 +1095,7 @@ files = ( 49ABB749236B0F9E00535CD7 /* UnsafePointer+bridge.swift in Sources */, 499A485522ED707300F6C675 /* RemoteConfigViewController.swift in Sources */, + 01CA6BC02B6A1B3100E386D6 /* MetaServer.swift in Sources */, 49D6A45229AEEC15006487EF /* StatusItemTool.swift in Sources */, 49CF3B5C20CE8068001EBF94 /* ClashResourceManager.swift in Sources */, 4952C3D02117027C004A4FA8 /* ConfigFileManager.swift in Sources */, @@ -1187,6 +1194,7 @@ 019A239628657A7A00AE5698 /* main.swift in Sources */, 491E6203258A424D00313AEF /* CommonUtils.m in Sources */, 01BC9ABE2928EB5A00F9B177 /* MetaDNS.swift in Sources */, + 01CA6BC12B6A1B3100E386D6 /* MetaServer.swift in Sources */, F935B2FA23083EE6009E4D33 /* ProxySettingTool.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/ClashX/Actions/TerminalCleanUpAction.swift b/ClashX/Actions/TerminalCleanUpAction.swift index 9583771e2..ed9a0054e 100644 --- a/ClashX/Actions/TerminalCleanUpAction.swift +++ b/ClashX/Actions/TerminalCleanUpAction.swift @@ -21,6 +21,9 @@ enum TerminalConfirmAction { PrivilegedHelperManager.shared.helper()?.stopMeta() PrivilegedHelperManager.shared.helper()?.updateTun(with: false) + let path = Paths.tempPath() + "/cacheConfigs" + try? FileManager.default.removeItem(atPath: path) + if ConfigManager.shared.proxyPortAutoSet && !ConfigManager.shared.isProxySetByOtherVariable.value || NetworkChangeNotifier.isCurrentSystemSetToClash(looser: true) || NetworkChangeNotifier.hasInterfaceProxySetToClash() { Logger.log("ClashX quit need clean proxy setting") diff --git a/ClashX/AppDelegate.swift b/ClashX/AppDelegate.swift index 67b3ded48..98d3169b4 100644 --- a/ClashX/AppDelegate.swift +++ b/ClashX/AppDelegate.swift @@ -777,33 +777,27 @@ extension AppDelegate { case pushConfigFailed(String) } - struct StartProxyResp: Codable { - let externalController: String - let secret: String - let log: String? - } - func startProxy() { if ConfigManager.shared.isRunning { return } Logger.log("Trying start meta core") - + prepareConfigFile().then { self.generateInitConfig() - }.then { + }.then { self.startMeta($0) }.get { res in - if let log = res.log { + if res.log != "" { Logger.log(""" \n######## Clash Meta Start Log ######### -\(log) +\(res.log) ######## END ######### """, level: .info) } let port = res.externalController.components(separatedBy: ":").last ?? "9090" ConfigManager.shared.apiPort = port - ConfigManager.shared.apiSecret = res.secret + ConfigManager.shared.apiSecret = res.secret ConfigManager.shared.isRunning = true self.proxyModeMenuItem.isEnabled = true self.dashboardMenuItem.isEnabled = true @@ -893,16 +887,19 @@ extension AppDelegate { } } - func startMeta(_ config: ClashMetaConfig.Config) -> Promise { + func startMeta(_ config: ClashMetaConfig.Config) -> Promise { .init { resolver in + let confJSON = MetaServer(externalController: config.externalController, secret: config.secret ?? "").jsonString() + PrivilegedHelperManager.shared.helper { Logger.log("helperNotFound, startMeta failed", level: .error) resolver.reject(StartMetaError.helperNotFound) }?.startMeta(withConfPath: kConfigFolderPath, - confFilePath: config.path) { + confFilePath: config.path, + confJSON: confJSON) { if let string = $0 { guard let jsonData = string.data(using: .utf8), - let res = try? JSONDecoder().decode(StartProxyResp.self, from: jsonData) else { + let res = try? JSONDecoder().decode(MetaServer.self, from: jsonData) else { resolver.reject(StartMetaError.startMetaFailed(string)) return } diff --git a/ClashX/General/Managers/MenuItemFactory.swift b/ClashX/General/Managers/MenuItemFactory.swift index e37207353..98e553c1f 100644 --- a/ClashX/General/Managers/MenuItemFactory.swift +++ b/ClashX/General/Managers/MenuItemFactory.swift @@ -80,6 +80,10 @@ class MenuItemFactory { guard let menu = menu else { continue } + + if let hidden = proxy.hidden, hidden { + continue + } switch hideState { case .mixed where [.urltest, .fallback, .loadBalance, .relay].contains(proxy.type): diff --git a/ClashX/Macro/Paths.swift b/ClashX/Macro/Paths.swift index 116655c0c..9808f0d19 100644 --- a/ClashX/Macro/Paths.swift +++ b/ClashX/Macro/Paths.swift @@ -49,6 +49,14 @@ enum Paths { } static func tempPath() -> String { - NSTemporaryDirectory().appending("com.MetaCubeX.ClashX.meta") + guard let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask) + .first? + .appendingPathComponent("com.MetaCubeX.ClashX.meta") else { + return NSTemporaryDirectory().appending("com.MetaCubeX.ClashX.meta") + } + + try? FileManager.default.createDirectory(at: url, withIntermediateDirectories: true) + + return url.path } } diff --git a/ClashX/Models/ClashProxy.swift b/ClashX/Models/ClashProxy.swift index c1b9e9123..6692598df 100644 --- a/ClashX/Models/ClashProxy.swift +++ b/ClashX/Models/ClashProxy.swift @@ -63,7 +63,7 @@ enum ClashProxyType: String, Codable, CaseIterable { static func isBuiltInProxy(_ proxy: ClashProxy) -> Bool { switch proxy.name { - case "DIRECT", "REJECT", "PASS": return true + case "DIRECT", "REJECT", "REJECT-DROP", "PASS", "COMPATIBLE": return true default: return false } } @@ -108,6 +108,8 @@ class ClashProxy: Codable { let alive: Bool? weak var enclosingResp: ClashProxyResp? weak var enclosingProvider: ClashProvider? + + let hidden: Bool? enum SpeedtestAbleItem { case proxy(name: ClashProxyName) @@ -138,7 +140,7 @@ class ClashProxy: Codable { lazy var isSpeedTestable: Bool = !speedtestAble.isEmpty private enum CodingKeys: String, CodingKey { - case type, all, history, now, name, alive + case type, all, history, now, name, alive, hidden } lazy var maxProxyNameLength: CGFloat = { diff --git a/ClashX/Views/ProxyItemView.swift b/ClashX/Views/ProxyItemView.swift index d207e3eab..890bbdb85 100644 --- a/ClashX/Views/ProxyItemView.swift +++ b/ClashX/Views/ProxyItemView.swift @@ -12,10 +12,14 @@ class ProxyItemView: MenuItemBaseView { let nameLabel: NSTextField let delayLabel: NSTextField var imageView: NSImageView? + + let isBuiltInProxy: Bool static let fixedPlaceHolderWidth: CGFloat = 20 + 50 + 25 init(proxy: ClashProxy) { + isBuiltInProxy = ClashProxyType.isBuiltInProxy(proxy) + nameLabel = VibrancyTextField(labelWithString: proxy.name) delayLabel = VibrancyTextField(labelWithString: "").setup(allowsVibrancy: false) let cell = PaddedNSTextFieldCell() @@ -63,8 +67,19 @@ class ProxyItemView: MenuItemBaseView { width: delayLabel.bounds.width, height: delayLabel.bounds.height) } + + func updateBuiltIn() { + delayLabel.stringValue = "IN" + needsLayout = true + delayLabel.layer?.backgroundColor = NSColor.systemBlue.cgColor + } func update(str: String?, value: Int?) { + guard !isBuiltInProxy else { + updateBuiltIn() + return + } + delayLabel.stringValue = str ?? "" needsLayout = true diff --git a/ProxyConfigHelper/Helper-Info.plist b/ProxyConfigHelper/Helper-Info.plist index dda3bf0dc..5a5e7f194 100755 --- a/ProxyConfigHelper/Helper-Info.plist +++ b/ProxyConfigHelper/Helper-Info.plist @@ -9,9 +9,9 @@ CFBundleName com.metacubex.ClashX.ProxyConfigHelper CFBundleShortVersionString - 1.8 + 1.11 CFBundleVersion - 18 + 21 SMAuthorizedClients anchor apple generic and identifier "com.metacubex.ClashX.ProxyConfigHelper" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = MEWHFZ92DY) diff --git a/ProxyConfigHelper/MetaServer.swift b/ProxyConfigHelper/MetaServer.swift new file mode 100644 index 000000000..4f26e42a5 --- /dev/null +++ b/ProxyConfigHelper/MetaServer.swift @@ -0,0 +1,25 @@ +// +// MetaServer.swift +// ClashX +// +// Copyright © 2024 west2online. All rights reserved. +// + +import Cocoa + +struct MetaServer: Codable { + var externalController: String + let secret: String + var log: String = "" + + func jsonString() -> String { + let encoder = JSONEncoder() + encoder.outputFormatting = .prettyPrinted + + guard let data = try? encoder.encode(self), + let string = String(data: data, encoding: .utf8) else { + return "" + } + return string + } +} diff --git a/ProxyConfigHelper/MetaTask.swift b/ProxyConfigHelper/MetaTask.swift index 84a15bd27..8356ebc88 100644 --- a/ProxyConfigHelper/MetaTask.swift +++ b/ProxyConfigHelper/MetaTask.swift @@ -7,23 +7,6 @@ import Cocoa class MetaTask: NSObject { - struct MetaServer: Encodable { - var externalController: String - let secret: String - var log: String = "" - - func jsonString() -> String { - let encoder = JSONEncoder() - encoder.outputFormatting = .prettyPrinted - - guard let data = try? encoder.encode(self), - let string = String(data: data, encoding: .utf8) else { - return "" - } - return string - } - } - struct MetaCurl: Decodable { let hello: String } @@ -38,8 +21,9 @@ class MetaTask: NSObject { } @objc func start(_ confPath: String, - confFilePath: String, - result: @escaping stringReplyBlock) { + confFilePath: String, + confJSON: String, + result: @escaping stringReplyBlock) { var resultReturned = false @@ -73,7 +57,8 @@ class MetaTask: NSObject { print("Test meta config success.") } - guard var serverResult = self.parseConfFile(confPath, confFilePath: confFilePath) else { + guard let confData = confJSON.data(using: .utf8), + var serverResult = try? JSONDecoder().decode(MetaServer.self, from: confData) else { returnResult("Can't decode config file.") return } diff --git a/ProxyConfigHelper/ProxyConfigHelper.m b/ProxyConfigHelper/ProxyConfigHelper.m index f5eb2eaa7..7469e7b77 100644 --- a/ProxyConfigHelper/ProxyConfigHelper.m +++ b/ProxyConfigHelper/ProxyConfigHelper.m @@ -145,10 +145,9 @@ - (void)initMetaCoreWithPath:(NSString *)path { }); } - -- (void)startMetaWithConfPath:(NSString *)confPath ConfFilePath:(NSString *)confFilePath result:(stringReplyBlock)reply { +- (void)startMetaWithConfPath:(NSString *)confPath ConfFilePath:(NSString *)confFilePath ConfJSON:(NSString *)confJSON result:(stringReplyBlock)reply { dispatch_async(dispatch_get_main_queue(), ^{ - [self.metaTask start:confPath confFilePath:confFilePath result:reply]; + [self.metaTask start:confPath confFilePath:confFilePath confJSON:confJSON result:reply]; }); } diff --git a/ProxyConfigHelper/ProxyConfigRemoteProcessProtocol.h b/ProxyConfigHelper/ProxyConfigRemoteProcessProtocol.h index c29ff3b4e..d0d275a10 100644 --- a/ProxyConfigHelper/ProxyConfigRemoteProcessProtocol.h +++ b/ProxyConfigHelper/ProxyConfigRemoteProcessProtocol.h @@ -19,6 +19,7 @@ typedef void(^dictReplyBlock)(NSDictionary *); - (void)startMetaWithConfPath:(NSString *)confPath ConfFilePath:(NSString *)confFilePath + ConfJSON:(NSString *)confJSON result:(stringReplyBlock)reply; - (void)verifyMetaWithConfPath:(NSString *)confPath