Skip to content

Commit a7e31af

Browse files
committed
Merge branch 'meta-dev' into meta
2 parents 7e97b2e + ee68536 commit a7e31af

9 files changed

Lines changed: 415 additions & 392 deletions

File tree

ClashX.xcodeproj/project.pbxproj

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272
01CA6BC12B6A1B3100E386D6 /* MetaServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01CA6BBF2B6A1B3100E386D6 /* MetaServer.swift */; };
7373
01CA6BC22B6A1B3100E386D6 /* MetaServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01CA6BBF2B6A1B3100E386D6 /* MetaServer.swift */; };
7474
01D567E62AD158B600CDA0AE /* MetaPrefsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01D567E22AD158B500CDA0AE /* MetaPrefsViewController.swift */; };
75+
01E908FC2FEE786F00C95A3A /* Subprocess in Frameworks */ = {isa = PBXBuildFile; productRef = 01E908FB2FEE786F00C95A3A /* Subprocess */; };
76+
01E908FE2FEE787900C95A3A /* Subprocess in Frameworks */ = {isa = PBXBuildFile; productRef = 01E908FD2FEE787900C95A3A /* Subprocess */; };
7577
01EF33602B98D03B00D1DBD9 /* ProxyConfigHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EF335F2B98D03B00D1DBD9 /* ProxyConfigHelper.swift */; };
7678
01EF33622B98D3A700D1DBD9 /* ProxyConfigRemoteProcessProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EF33612B98D3A700D1DBD9 /* ProxyConfigRemoteProcessProtocol.swift */; };
7779
01EF33642B98D71600D1DBD9 /* ProxyConfigRemoteProcessProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EF33612B98D3A700D1DBD9 /* ProxyConfigRemoteProcessProtocol.swift */; };
@@ -409,6 +411,7 @@
409411
01F3362C2AD10D0B0048AF77 /* CocoaLumberjack in Frameworks */,
410412
01F3362D2AD10D0B0048AF77 /* Yams in Frameworks */,
411413
013B220E2F88A219009B30CB /* AsyncHTTPClient in Frameworks */,
414+
01E908FE2FEE787900C95A3A /* Subprocess in Frameworks */,
412415
01F3362E2AD10D0B0048AF77 /* RxCocoa in Frameworks */,
413416
01F3362F2AD10D0B0048AF77 /* FlexibleDiff in Frameworks */,
414417
01F336302AD10D0B0048AF77 /* libresolv.tbd in Frameworks */,
@@ -419,6 +422,7 @@
419422
isa = PBXFrameworksBuildPhase;
420423
buildActionMask = 2147483647;
421424
files = (
425+
01E908FC2FEE786F00C95A3A /* Subprocess in Frameworks */,
422426
);
423427
runOnlyForDeploymentPostprocessing = 0;
424428
};
@@ -911,6 +915,7 @@
911915
01BCDB202C9EEE260028FA94 /* Sparkle */,
912916
013B21FA2F7E95E0009B30CB /* DGCharts */,
913917
013B220D2F88A219009B30CB /* AsyncHTTPClient */,
918+
01E908FD2FEE787900C95A3A /* Subprocess */,
914919
);
915920
productName = ClashX;
916921
productReference = 01F336442AD10D0B0048AF77 /* ClashX Meta.app */;
@@ -973,6 +978,7 @@
973978
01BCDB1F2C9EEE260028FA94 /* XCRemoteSwiftPackageReference "Sparkle" */,
974979
013B21F92F7E95E0009B30CB /* XCRemoteSwiftPackageReference "Charts" */,
975980
013B220C2F88A219009B30CB /* XCRemoteSwiftPackageReference "async-http-client" */,
981+
01E908FA2FEE786F00C95A3A /* XCRemoteSwiftPackageReference "swift-subprocess" */,
976982
);
977983
productRefGroup = 49CF3B1E20CD7463001EBF94 /* Products */;
978984
projectDirPath = "";
@@ -1244,7 +1250,7 @@
12441250
"$(inherited)",
12451251
"$(PROJECT_DIR)/ClashX",
12461252
);
1247-
MACOSX_DEPLOYMENT_TARGET = 12.4;
1253+
MACOSX_DEPLOYMENT_TARGET = 13.0;
12481254
MARKETING_VERSION = v1.0;
12491255
PRODUCT_BUNDLE_IDENTIFIER = com.metacubex.ClashX.meta;
12501256
PRODUCT_NAME = "ClashX Meta";
@@ -1292,7 +1298,7 @@
12921298
"$(inherited)",
12931299
"$(PROJECT_DIR)/ClashX",
12941300
);
1295-
MACOSX_DEPLOYMENT_TARGET = 12.4;
1301+
MACOSX_DEPLOYMENT_TARGET = 13.0;
12961302
MARKETING_VERSION = v1.0;
12971303
OTHER_CODE_SIGN_FLAGS = "--timestamp";
12981304
PRODUCT_BUNDLE_IDENTIFIER = com.metacubex.ClashX.meta;
@@ -1454,7 +1460,7 @@
14541460
"@loader_path/../Frameworks",
14551461
);
14561462
LIBRARY_SEARCH_PATHS = "$(inherited)";
1457-
MACOSX_DEPLOYMENT_TARGET = 12.4;
1463+
MACOSX_DEPLOYMENT_TARGET = 13.0;
14581464
MARKETING_VERSION = 1.2;
14591465
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
14601466
MTL_FAST_MATH = YES;
@@ -1499,7 +1505,7 @@
14991505
"@loader_path/../Frameworks",
15001506
);
15011507
LIBRARY_SEARCH_PATHS = "$(inherited)";
1502-
MACOSX_DEPLOYMENT_TARGET = 12.4;
1508+
MACOSX_DEPLOYMENT_TARGET = 13.0;
15031509
MARKETING_VERSION = 1.2;
15041510
MTL_FAST_MATH = YES;
15051511
OTHER_LDFLAGS = (
@@ -1634,6 +1640,14 @@
16341640
minimumVersion = 2.6.4;
16351641
};
16361642
};
1643+
01E908FA2FEE786F00C95A3A /* XCRemoteSwiftPackageReference "swift-subprocess" */ = {
1644+
isa = XCRemoteSwiftPackageReference;
1645+
repositoryURL = "https://github.com/swiftlang/swift-subprocess";
1646+
requirement = {
1647+
kind = upToNextMajorVersion;
1648+
minimumVersion = 0.5.0;
1649+
};
1650+
};
16371651
01F335B72AD10D0B0048AF77 /* XCRemoteSwiftPackageReference "KeyboardShortcuts" */ = {
16381652
isa = XCRemoteSwiftPackageReference;
16391653
repositoryURL = "https://github.com/sindresorhus/KeyboardShortcuts.git";
@@ -1721,6 +1735,16 @@
17211735
package = 01BCDB1F2C9EEE260028FA94 /* XCRemoteSwiftPackageReference "Sparkle" */;
17221736
productName = Sparkle;
17231737
};
1738+
01E908FB2FEE786F00C95A3A /* Subprocess */ = {
1739+
isa = XCSwiftPackageProductDependency;
1740+
package = 01E908FA2FEE786F00C95A3A /* XCRemoteSwiftPackageReference "swift-subprocess" */;
1741+
productName = Subprocess;
1742+
};
1743+
01E908FD2FEE787900C95A3A /* Subprocess */ = {
1744+
isa = XCSwiftPackageProductDependency;
1745+
package = 01E908FA2FEE786F00C95A3A /* XCRemoteSwiftPackageReference "swift-subprocess" */;
1746+
productName = Subprocess;
1747+
};
17241748
01F335B62AD10D0B0048AF77 /* KeyboardShortcuts */ = {
17251749
isa = XCSwiftPackageProductDependency;
17261750
package = 01F335B72AD10D0B0048AF77 /* XCRemoteSwiftPackageReference "KeyboardShortcuts" */;

ClashX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 29 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ClashX/AppDelegate.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
8080
}
8181

8282
func applicationDidFinishLaunching(_ notification: Notification) {
83+
Logger.shared.setupLogSession()
8384
Logger.log("———————————————————————————————————————————————————————————")
8485
Logger.log("———————————————applicationDidFinishLaunching———————————————")
8586
Logger.log("———————————————————————————————————————————————————————————")

ClashX/Basic/Logger.swift

Lines changed: 82 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,58 @@
88

99
import CocoaLumberjackSwift
1010
import Foundation
11+
12+
private class AppLogFileManager: DDLogFileManagerDefault {
13+
override var newLogFileName: String {
14+
let df = DateFormatter()
15+
df.dateFormat = "dd_HH-mm-ss"
16+
return "clashx_\(df.string(from: Date())).log"
17+
}
18+
19+
override func isLogFile(withName fileName: String) -> Bool {
20+
fileName.range(of: #"^clashx_\d{2}_\d{2}-\d{2}-\d{2}\.log$"#, options: .regularExpression) != nil
21+
}
22+
}
23+
1124
class Logger {
1225
static let shared = Logger()
1326
var fileLogger: DDFileLogger = .init()
27+
private(set) var sessionId = ""
28+
29+
private var cleanupLogTask: Task<Void, Never>?
30+
31+
var coreLogPath: String {
32+
"\(logFolder())/\(kCoreLogName)"
33+
}
34+
35+
var coreCrashLogPath: String {
36+
"\(logFolder())/\(kCoreCrashLogName)"
37+
}
1438

1539
private init() {
1640
#if DEBUG
1741
DDLog.add(DDOSLogger.sharedInstance)
1842
#endif
19-
// default time zone is "UTC"
20-
let dataFormatter = DateFormatter()
21-
dataFormatter.setLocalizedDateFormatFromTemplate("YYYY/MM/dd HH:mm:ss:SSS")
22-
fileLogger.logFormatter = DDLogFileFormatterDefault(dateFormatter: dataFormatter)
23-
fileLogger.rollingFrequency = TimeInterval(60 * 60 * 24) // 24 hours
24-
fileLogger.maximumFileSize = 5 * 1024 * 1024 // 5MB
25-
fileLogger.logFileManager.maximumNumberOfLogFiles = 3
26-
DDLog.add(fileLogger)
2743
dynamicLogLevel = ConfigManager.selectLoggingApiLevel.toDDLogLevel()
2844
}
2945

46+
func configure(logDirectory: String, sessionId: String) {
47+
self.sessionId = sessionId
48+
let dateFormatter = DateFormatter()
49+
dateFormatter.setLocalizedDateFormatFromTemplate("YYYY/MM/dd HH:mm:ss:SSS")
50+
let fm = AppLogFileManager(logsDirectory: logDirectory)
51+
let newLogger = DDFileLogger(logFileManager: fm)
52+
newLogger.logFormatter = DDLogFileFormatterDefault(dateFormatter: dateFormatter)
53+
newLogger.rollingFrequency = TimeInterval(60 * 60 * 24) // 24 hours
54+
newLogger.maximumFileSize = 5 * 1024 * 1024 // 5MB
55+
newLogger.logFileManager.maximumNumberOfLogFiles = 3
56+
DDLog.remove(fileLogger)
57+
fileLogger = newLogger
58+
DDLog.add(newLogger)
59+
60+
startCleanup()
61+
}
62+
3063
private func logToFile(msg: String, level: ClashLogLevel) {
3164
switch level {
3265
case .debug, .silent:
@@ -54,4 +87,45 @@ class Logger {
5487
func logFolder() -> String {
5588
return fileLogger.logFileManager.logsDirectory
5689
}
90+
91+
func setupLogSession() {
92+
let dateFormatter = DateFormatter()
93+
dateFormatter.dateFormat = "yyyy-MM-dd_HH-mm-ss"
94+
let sessionId = dateFormatter.string(from: Date())
95+
96+
let logsDir = "\(kConfigFolderPath)logs/\(sessionId)"
97+
try? FileManager.default.createDirectory(atPath: logsDir, withIntermediateDirectories: true)
98+
99+
configure(logDirectory: logsDir, sessionId: sessionId)
100+
101+
FileManager.default.createFile(atPath: coreLogPath, contents: nil)
102+
FileManager.default.createFile(atPath: coreCrashLogPath, contents: nil)
103+
104+
cleanupLogDirectories()
105+
}
106+
107+
108+
private func cleanupLogDirectories() {
109+
let logsRoot = "\(kConfigFolderPath)logs/"
110+
guard let contents = try? FileManager.default.contentsOfDirectory(atPath: logsRoot) else { return }
111+
112+
let maxCount = 20
113+
let sorted = contents
114+
.filter { $0.contains("-") }
115+
.sorted(by: >)
116+
117+
guard sorted.count > maxCount else { return }
118+
119+
for name in sorted[maxCount...] {
120+
try? FileManager.default.removeItem(atPath: "\(logsRoot)\(name)")
121+
}
122+
}
123+
124+
125+
func startCleanup() {
126+
cleanupLogTask = Task {
127+
try? await Task.sleep(seconds: 5 * 60)
128+
try? FileHandle(forWritingTo: URL(fileURLWithPath: coreLogPath)).truncate(atOffset: 0)
129+
}
130+
}
57131
}

ClashX/General/ClashProcess.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ actor ClashProcess {
262262
let confJSON = MetaServer(
263263
externalController: config.externalController,
264264
secret: config.secret ?? "",
265-
safePaths: config.safePaths ?? ""
265+
safePaths: config.safePaths ?? "",
266+
sessionId: Logger.shared.sessionId
266267
).jsonString()
267268

268269
let response: String?

ProxyConfigHelper/Helper-Info.plist

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
<key>CFBundleName</key>
1010
<string>com.metacubex.ClashX.ProxyConfigHelper</string>
1111
<key>CFBundleShortVersionString</key>
12-
<string>1.22</string>
12+
<string>1.23</string>
1313
<key>CFBundleVersion</key>
14-
<string>28</string>
14+
<string>30</string>
1515
<key>SMAuthorizedClients</key>
1616
<array>
1717
<string>anchor apple generic and identifier &quot;com.metacubex.ClashX.ProxyConfigHelper&quot; 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)</string>

ProxyConfigHelper/MetaServer.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,16 @@
77

88
import Cocoa
99

10+
let kCoreLogName = "clashx_mihomo.log"
11+
let kCoreCrashLogName = "clashx_mihomo_error.log"
12+
1013
struct MetaServer: Codable {
1114
var externalController: String
1215
let secret: String
1316
var log: String = ""
1417

1518
var safePaths = ""
19+
var sessionId = ""
1620

1721
func jsonString() -> String {
1822
let encoder = JSONEncoder()

0 commit comments

Comments
 (0)