ClashX.Meta/ClashX/Actions/TerminalCleanUpAction.swift

92 lines
3.3 KiB
Swift

//
// TerminalCleanUpAction.swift
// ClashX
//
// Created by yicheng on 2023/9/5.
// Copyright © 2023 west2online. All rights reserved.
//
import AppKit
import Foundation
import RxSwift
enum TerminalConfirmAction {
static func run() -> NSApplication.TerminateReply {
guard confirmAction() else {
return .terminateCancel
}
let group = DispatchGroup()
var shouldWait = false
ConfigManager.shared.restoreTunProxy = ConfigManager.shared.isTunModeVariable.value
PrivilegedHelperManager.shared.helper()?.stopMeta()
PrivilegedHelperManager.shared.helper()?.updateTun(state: false, dns: ConfigManager.metaTunDNS)
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")
ConfigManager.shared.restoreSystemProxy = true
shouldWait = true
group.enter()
SystemProxyManager.shared.disableProxy(forceDisable: ConfigManager.shared.isProxySetByOtherVariable.value) {
group.leave()
}
} else {
ConfigManager.shared.restoreSystemProxy = false
}
if !shouldWait {
Logger.log("ClashX quit without clean waiting")
return .terminateNow
}
if let statusItem = AppDelegate.shared.statusItem, statusItem.menu != nil {
statusItem.menu = nil
}
AppDelegate.shared.disposeBag = DisposeBag()
DispatchQueue.global(qos: .default).async {
let res = group.wait(timeout: .now() + 5)
switch res {
case .success:
Logger.log("ClashX quit after clean up finish")
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
NSApp.reply(toApplicationShouldTerminate: true)
}
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
NSApp.reply(toApplicationShouldTerminate: true)
}
case .timedOut:
Logger.log("ClashX quit after clean up timeout")
DispatchQueue.main.async {
NSApp.reply(toApplicationShouldTerminate: true)
}
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
NSApp.reply(toApplicationShouldTerminate: true)
}
}
}
Logger.log("ClashX quit wait for clean up")
return .terminateLater
}
static func confirmAction() -> Bool {
if NSApp.activationPolicy() == .regular {
let alert = NSAlert()
alert.messageText = NSLocalizedString("Quit ClashX?", comment: "")
alert.informativeText = NSLocalizedString("The active connections will be interrupted.", comment: "")
alert.alertStyle = .informational
alert.addButton(withTitle: NSLocalizedString("Quit", comment: ""))
alert.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
return alert.runModal() == .alertFirstButtonReturn
}
return true
}
}