Files
ggbond268--mactools/Plugins/AutoHideMenuBar/Sources/AutoHideMenuBarPlugin.swift
T
wehub-resource-sync 1d1286fadb
Build / Build and test (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:18:38 +08:00

196 lines
6.5 KiB
Swift

import AppKit
import Foundation
import OSLog
import SwiftUI
import MacToolsPluginKit
protocol MenuBarCommandRunning {
func setMenuBarAutohide(_ isEnabled: Bool) throws
}
struct ProcessMenuBarCommandRunner: MenuBarCommandRunning {
private let localization: PluginLocalization
init(localization: PluginLocalization = PluginLocalization(bundle: .main)) {
self.localization = localization
}
func setMenuBarAutohide(_ isEnabled: Bool) throws {
let script = """
tell application "System Events"
tell dock preferences
set autohide menu bar to \(isEnabled ? "true" : "false")
end tell
end tell
"""
let appleScript = NSAppleScript(source: script)
var error: NSDictionary?
appleScript?.executeAndReturnError(&error)
if let error {
let message = (error[NSAppleScript.errorMessage] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines)
throw NSError(
domain: "AutoHideMenuBarPlugin",
code: (error[NSAppleScript.errorNumber] as? Int) ?? 1,
userInfo: [
NSLocalizedDescriptionKey: message?.isEmpty == false
? message!
: localization.string(
"error.toggleFailed",
defaultValue: "切换菜单栏自动隐藏失败"
)
]
)
}
}
}
public final class AutoHideMenuBarPluginFactory: NSObject, MacToolsPluginBundleFactory {
public static func makeProvider(context: PluginRuntimeContext) throws -> any PluginProvider {
AutoHideMenuBarPluginProvider(context: context)
}
}
@MainActor
private struct AutoHideMenuBarPluginProvider: PluginProvider {
let context: PluginRuntimeContext
func makePlugins() -> [any MacToolsPlugin] {
[AutoHideMenuBarPlugin(localization: PluginLocalization(bundle: context.resourceBundle))]
}
}
@MainActor
final class AutoHideMenuBarPlugin: MacToolsPlugin, PluginPrimaryPanel {
let metadata: PluginMetadata
let primaryPanelDescriptor = PluginPrimaryPanelDescriptor(
controlStyle: .switch,
menuActionBehavior: .keepPresented
)
var onStateChange: (() -> Void)?
var requestPermissionGuidance: ((String) -> Void)?
var shortcutBindingResolver: ((String) -> ShortcutBinding?)?
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "cc.ggbond.mactools", category: "AutoHideMenuBarPlugin")
private let commandRunner: any MenuBarCommandRunning
private let stateReader: () -> Bool
private let localization: PluginLocalization
private var isMenuBarHidden: Bool
private var lastErrorMessage: String?
init(
commandRunner: (any MenuBarCommandRunning)? = nil,
stateReader: @escaping () -> Bool = { AutoHideMenuBarPlugin.readMenuBarAutohideState() },
localization: PluginLocalization = PluginLocalization(bundle: .main)
) {
self.localization = localization
self.commandRunner = commandRunner ?? ProcessMenuBarCommandRunner(localization: localization)
self.stateReader = stateReader
self.metadata = PluginMetadata(
id: "auto-hide-menu-bar",
title: localization.string("metadata.title", defaultValue: "自动隐藏菜单栏"),
iconName: "menubar.rectangle",
iconTint: Color(nsColor: .systemIndigo),
order: 42,
defaultDescription: localization.string(
"metadata.description",
defaultValue: "自动隐藏菜单栏,提供更完整的屏幕显示空间"
)
)
self.isMenuBarHidden = stateReader()
}
var primaryPanelState: PluginPanelState {
PluginPanelState(
subtitle: isMenuBarHidden
? localization.string("panel.subtitle.enabled", defaultValue: "已开启")
: localization.string("panel.subtitle.disabled", defaultValue: "已关闭"),
isOn: isMenuBarHidden,
isExpanded: false,
isEnabled: true,
isVisible: true,
detail: nil,
errorMessage: lastErrorMessage
)
}
var permissionRequirements: [PluginPermissionRequirement] { [] }
var settingsSections: [PluginSettingsSection] { [] }
var shortcutDefinitions: [PluginShortcutDefinition] { [] }
func refresh() {
let latestState = stateReader()
if latestState != isMenuBarHidden {
isMenuBarHidden = latestState
onStateChange?()
}
}
func handleAction(_ action: PluginPanelAction) {
guard case let .setSwitch(isEnabled) = action else {
return
}
setMenuBarHidden(isEnabled)
}
func permissionState(for permissionID: String) -> PluginPermissionState {
PluginPermissionState(isGranted: true, footnote: nil)
}
func handlePermissionAction(id: String) {}
func handleSettingsAction(id: String) {}
func handleShortcutAction(id: String) {}
private func setMenuBarHidden(_ isEnabled: Bool) {
do {
try commandRunner.setMenuBarAutohide(isEnabled)
isMenuBarHidden = isEnabled
lastErrorMessage = nil
onStateChange?()
} catch {
logger.error("Failed to update menu bar auto-hide: \(error.localizedDescription, privacy: .public)")
lastErrorMessage = error.localizedDescription
refresh()
onStateChange?()
}
}
nonisolated static func readMenuBarAutohideState(
globalDefaults: UserDefaults = .standard,
dockDefaults: UserDefaults? = UserDefaults(suiteName: "com.apple.dock")
) -> Bool {
resolvedMenuBarAutohideState(
globalValue: globalDefaults.object(forKey: "_HIHideMenuBar"),
dockValue: dockDefaults?.object(forKey: "autohide-menubar")
)
}
nonisolated static func resolvedMenuBarAutohideState(globalValue: Any?, dockValue: Any?) -> Bool {
if let value = boolValue(from: globalValue) {
return value
}
if let value = boolValue(from: dockValue) {
return value
}
return false
}
private nonisolated static func boolValue(from value: Any?) -> Bool? {
switch value {
case let value as Bool:
value
case let value as NSNumber:
value.boolValue
default:
nil
}
}
}