Files
PowerBar/PowerBar/AppState.swift
leo12025 be65e275b3 feat(权限): 添加权限检查和管理功能
添加权限检查功能,包括自动启动和系统命令执行权限
在菜单中添加打开系统设置和登录项管理的按钮
2025-12-27 19:57:52 +08:00

259 lines
8.4 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Foundation
import Combine
import IOKit.pwr_mgt
import ServiceManagement
import AppKit
// MARK: - App State Manager
class AppState: ObservableObject {
// MARK: - Published Properties (UI )
//
@Published var isFunctionEnabled: Bool = false
//
@Published var isUserIdle: Bool = false
//
@Published var isLaunchAtLogin: Bool = false
//
private var monitorTimer: Timer?
private var caffeinateProcess: Process? // 使Process
//
private let idleThreshold: TimeInterval = 300 // 5
private let checkInterval: TimeInterval = 10 // 10
//
init() {
//
checkLaunchAtLoginStatus()
}
// MARK: - Public Methods
///
func toggleFunction() {
isFunctionEnabled.toggle()
if isFunctionEnabled {
//
performCheck()
startMonitoringTimer()
} else {
//
stopMonitoringTimer()
stopCaffeinate()
updateUserIdleStatus(false) //
}
}
// MARK: - Monitoring Logic
private func startMonitoringTimer() {
guard monitorTimer == nil else { return }
print("开始监控...")
// 使 weak self
monitorTimer = Timer.scheduledTimer(withTimeInterval: checkInterval, repeats: true) { [weak self] _ in
self?.performCheck()
}
}
private func stopMonitoringTimer() {
monitorTimer?.invalidate()
monitorTimer = nil
print("监控已停止。")
}
private func performCheck() {
// 1.
let idleTime = getSystemIdleTime()
// 2.
let isIdleNow = (idleTime >= idleThreshold)
// 3.
if isIdleNow != isUserIdle {
updateUserIdleStatus(isIdleNow)
if isIdleNow {
//
stopCaffeinate()
} else {
//
startCaffeinate()
}
}
}
// MARK: - User Idle Detection
/// 使 IOKit ()
/// - Returns:
private func getSystemIdleTime() -> TimeInterval {
//
var onPort: mach_port_t = 0
// IO Master Port
let kr = IOMainPort(0, &onPort)
guard kr == KERN_SUCCESS else { return 0 }
// HID HIDIdleTime
let hidSystem = IOServiceGetMatchingService(onPort, IOServiceMatching("IOHIDSystem"))
guard hidSystem != 0 else { return 0 }
//
let result = IORegistryEntryCreateCFProperty(hidSystem, "HIDIdleTime" as CFString, kCFAllocatorDefault, 0)
IOObjectRelease(hidSystem)
guard let data = result?.takeRetainedValue() as? Data else { return 0 }
// UInt64
var idleTime: UInt64 = 0
(data as NSData).getBytes(&idleTime, length: MemoryLayout<UInt64>.size)
return Double(idleTime) / 1_000_000_000.0 //
}
// MARK: - Caffeinate Management
private func startCaffeinate() {
guard caffeinateProcess == nil else { return }
print("用户活动,启动 caffeinate 阻止睡眠...")
// caffeinate
caffeinateProcess = Process()
caffeinateProcess?.executableURL = URL(fileURLWithPath: "/usr/bin/caffeinate")
caffeinateProcess?.arguments = ["-d"] // -d
//
let outputPipe = Pipe()
caffeinateProcess?.standardOutput = outputPipe
caffeinateProcess?.standardError = outputPipe
caffeinateProcess?.standardInput = Pipe()
do {
try caffeinateProcess?.run()
print("成功启动 caffeinate 进程")
} catch {
print("启动 caffeinate 失败: \(error)")
caffeinateProcess = nil
}
}
private func stopCaffeinate() {
guard let process = caffeinateProcess else { return }
print("用户空闲或功能关闭,停止 caffeinate 进程")
//
process.terminate()
// 退
caffeinateProcess = nil
print("已重置 caffeinate 进程引用")
}
// MARK: - UI State Update
/// 线
private func updateUserIdleStatus(_ isIdle: Bool) {
DispatchQueue.main.async {
self.isUserIdle = isIdle
}
}
// MARK: - Launch at Login Management
///
private func checkLaunchAtLoginStatus() {
// 使 Bundle.main.bundleIdentifier bundle ID
guard let bundleIdentifier = Bundle.main.bundleIdentifier else { return }
isLaunchAtLogin = SMAppService.mainApp.status == .enabled
}
///
func toggleLaunchAtLogin() {
isLaunchAtLogin.toggle()
do {
if isLaunchAtLogin {
try SMAppService.mainApp.register()
print("已设置开机自动启动")
} else {
try SMAppService.mainApp.unregister()
print("已取消开机自动启动")
}
} catch {
print("设置开机自动启动失败: \(error)")
//
isLaunchAtLogin.toggle()
}
}
// MARK: - Permission Management
///
func checkPermissions() {
print("检查应用程序权限...")
//
checkLaunchAtLoginStatus()
print("自动启动权限: \(isLaunchAtLogin ? "已启用" : "已禁用")")
//
let canExecuteSystemCommands = checkSystemCommandPermission()
print("系统命令执行权限: \(canExecuteSystemCommands ? "已允许" : "已拒绝")")
}
///
private func checkSystemCommandPermission() -> Bool {
//
let process = Process()
process.executableURL = URL(fileURLWithPath: "/bin/echo")
process.arguments = ["test"]
do {
try process.run()
process.waitUntilExit()
return process.terminationStatus == 0
} catch {
print("执行系统命令失败: \(error)")
return false
}
}
///
func openSecuritySettings() {
print("打开系统设置的隐私与安全性页面...")
let settingsUrl = URL(string: "x-apple.systempreferences:com.apple.preference.security")!
if NSWorkspace.shared.open(settingsUrl) {
print("已打开系统设置页面")
} else {
print("打开系统设置页面失败")
}
}
///
func openLoginItemsSettings() {
print("打开系统设置的登录项页面...")
let settingsUrl = URL(string: "x-apple.systempreferences:com.apple.preference.usersandgroups?LoginItems")!
if NSWorkspace.shared.open(settingsUrl) {
print("已打开登录项设置页面")
} else {
print("打开登录项设置页面失败")
}
}
// MARK: - Deinitializer
deinit {
// App 退
stopMonitoringTimer()
stopCaffeinate()
}
}