Files
wehub-resource-sync 1d1286fadb
Build / Build and test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:18:38 +08:00

155 lines
5.0 KiB
Swift

import AppKit
import Foundation
import SwiftUI
import MacToolsPluginKit
public final class HomebrewPluginFactory: NSObject, MacToolsPluginBundleFactory {
public static func makeProvider(context: PluginRuntimeContext) throws -> any PluginProvider {
HomebrewPluginProvider(context: context)
}
}
@MainActor
private struct HomebrewPluginProvider: PluginProvider {
let context: PluginRuntimeContext
func makePlugins() -> [any MacToolsPlugin] {
let localization = PluginLocalization(bundle: context.resourceBundle)
let controller = HomebrewController(localization: localization)
return [HomebrewPlugin(
controller: controller,
localization: localization
)]
}
}
@MainActor
public final class HomebrewPlugin: MacToolsPlugin, PluginPrimaryPanel, PluginConfigurationPresenting {
public enum ControlID {
static let manage = "execute"
}
public let metadata: PluginMetadata
public let primaryPanelDescriptor: PluginPrimaryPanelDescriptor
public var onStateChange: (() -> Void)?
public var requestPermissionGuidance: ((String) -> Void)?
public var shortcutBindingResolver: ((String) -> ShortcutBinding?)?
public var requestConfigurationPresentation: (() -> Void)?
private let controller: HomebrewController
private let localization: PluginLocalization
public init(
controller: HomebrewController,
localization: PluginLocalization
) {
self.controller = controller
self.localization = localization
self.primaryPanelDescriptor = PluginPrimaryPanelDescriptor(
controlStyle: .button,
menuActionBehavior: .dismissBeforeHandling,
buttonTitleProvider: { localization.string("panel.action.manage", defaultValue: "管理") }
)
self.metadata = PluginMetadata(
id: "homebrew",
title: localization.string("metadata.title", defaultValue: "Homebrew"),
iconName: "shippingbox.fill",
iconTint: Color(nsColor: .systemOrange),
order: 92,
defaultDescription: localization.string("metadata.description", defaultValue: "Manage Homebrew packages, repositories, and perform diagnostics")
)
self.controller.onStateChange = { [weak self] in
self?.onStateChange?()
}
}
public func activate(context: PluginRuntimeContext) {
onStateChange?()
}
public func deactivate(reason: PluginDeactivationReason) {
guard reason.requiresStateCleanup else { return }
controller.cancelCurrentOperation()
}
public func refresh() {
onStateChange?()
}
public var primaryPanelState: PluginPanelState {
PluginPanelState(
subtitle: subtitleText,
isOn: controller.isBusy,
isExpanded: false,
isEnabled: true,
isVisible: true,
detail: nil,
errorMessage: controller.isBrewAvailable
? nil
: localization.string("panel.error.brewPathRequired", defaultValue: "需要配置 brew 路径")
)
}
public var permissionRequirements: [PluginPermissionRequirement] { [] }
public var settingsSections: [PluginSettingsSection] { [] }
public var shortcutDefinitions: [PluginShortcutDefinition] { [] }
public var configuration: PluginConfiguration? {
let controller = self.controller
let localization = self.localization
return PluginConfiguration(
description: metadata.defaultDescription,
prefersFullHeight: true
) { _ in
HomebrewDetailView(
controller: controller,
localization: localization,
showsHeader: false,
contentPadding: 0,
minimumContentHeight: 480
)
}
}
public func handleAction(_ action: PluginPanelAction) {
switch action {
case let .invokeAction(controlID):
handleInvoke(controlID: controlID)
default:
break
}
}
public func permissionState(for permissionID: String) -> PluginPermissionState {
PluginPermissionState(isGranted: true, footnote: nil)
}
public func handlePermissionAction(id: String) {}
public func handleSettingsAction(id: String) {}
public func handleShortcutAction(id: String) {}
// MARK: - Private
private var subtitleText: String {
guard controller.isBrewAvailable else {
return localization.string("panel.error.brewPathRequired", defaultValue: "需要配置 brew 路径")
}
if controller.isBusy {
return controller.currentOperationName
}
return localization.string("panel.subtitle.manage", defaultValue: "管理包、软件源与诊断")
}
private func handleInvoke(controlID: String) {
switch controlID {
case ControlID.manage:
requestConfigurationPresentation?()
default:
break
}
}
}