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

185 lines
6.0 KiB
Swift

import SwiftUI
@MainActor
public protocol MacToolsPlugin: AnyObject {
var metadata: PluginMetadata { get }
var primaryPanel: (any PluginPrimaryPanel)? { get }
var componentPanel: (any PluginComponentPanel)? { get }
var permissionRequirements: [PluginPermissionRequirement] { get }
var settingsSections: [PluginSettingsSection] { get }
var shortcutDefinitions: [PluginShortcutDefinition] { get }
var configuration: PluginConfiguration? { get }
var onStateChange: (() -> Void)? { get set }
var requestPermissionGuidance: ((String) -> Void)? { get set }
var shortcutBindingResolver: ((String) -> ShortcutBinding?)? { get set }
func refresh()
func activate(context: PluginRuntimeContext)
func deactivate(reason: PluginDeactivationReason)
func permissionState(for permissionID: String) -> PluginPermissionState
func handlePermissionAction(id: String)
func handleSettingsAction(id: String)
func handleShortcutAction(id: String)
}
@MainActor
public protocol PluginPrimaryPanel: AnyObject {
var primaryPanelDescriptor: PluginPrimaryPanelDescriptor { get }
var primaryPanelState: PluginPanelState { get }
func handleAction(_ action: PluginPanelAction)
}
public enum PluginShortcutEventPhase: Sendable {
case pressed
case released
}
@MainActor
public protocol PluginShortcutEventHandling: AnyObject {
func handleShortcutEvent(id: String, phase: PluginShortcutEventPhase)
}
public extension MacToolsPlugin {
var primaryPanel: (any PluginPrimaryPanel)? {
nil
}
var componentPanel: (any PluginComponentPanel)? {
nil
}
var permissionRequirements: [PluginPermissionRequirement] {
[]
}
var settingsSections: [PluginSettingsSection] {
[]
}
var shortcutDefinitions: [PluginShortcutDefinition] {
[]
}
var configuration: PluginConfiguration? {
nil
}
func refresh() {}
func activate(context: PluginRuntimeContext) {}
func deactivate(reason: PluginDeactivationReason) {}
func permissionState(for permissionID: String) -> PluginPermissionState {
PluginPermissionState(isGranted: true, footnote: nil)
}
func handlePermissionAction(id: String) {}
func handleSettingsAction(id: String) {}
func handleShortcutAction(id: String) {}
}
public extension MacToolsPlugin where Self: PluginPrimaryPanel {
var primaryPanel: (any PluginPrimaryPanel)? {
self
}
}
@MainActor
public protocol PluginComponentPanel: AnyObject {
var descriptor: PluginComponentDescriptor { get }
var componentPanelState: PluginComponentState { get }
func makeView(context: PluginComponentContext) -> AnyView
}
public extension MacToolsPlugin where Self: PluginComponentPanel {
var componentPanel: (any PluginComponentPanel)? {
self
}
}
public enum PluginPanelSurface: CaseIterable, Hashable, Sendable {
case component
case primary
}
@MainActor
public protocol PluginPanelSurfaceLifecycleHandling: AnyObject {
func panelSurfaceDidBecomeVisible(_ surface: PluginPanelSurface)
func panelSurfaceDidBecomeHidden(_ surface: PluginPanelSurface)
}
public extension PluginPanelSurfaceLifecycleHandling {
func panelSurfaceDidBecomeVisible(_ surface: PluginPanelSurface) {}
func panelSurfaceDidBecomeHidden(_ surface: PluginPanelSurface) {}
}
@MainActor
public protocol PluginProvider {
func makePlugins() -> [any MacToolsPlugin]
}
public protocol MacToolsPluginBundleFactory: AnyObject {
static func makeProvider(context: PluginRuntimeContext) throws -> any PluginProvider
}
@MainActor
public protocol AccessibilityPermissionRefreshing {
func refreshAccessibilityPermission()
}
@MainActor
public protocol DisplayTopologyRefreshing {
func refreshDisplayTopology()
}
/// Optional protocol for plugins that expose a compact, read-only status in the primary panel row.
/// Does not change the `MacToolsPlugin` witness table, so installed legacy plugins are unaffected.
@MainActor
public protocol PluginPrimaryPanelIndicatorProviding: AnyObject {
var primaryPanelIndicator: PluginPrimaryPanelIndicator? { get }
}
/// Optional protocol for plugins that need a floating-window anchor.
/// Does not change the `MacToolsPlugin` witness table, so installed legacy plugins are unaffected.
@MainActor
public protocol DropZoneAnchorProviding: AnyObject {
/// Host-injected provider returning the status-item button frame in screen coordinates.
var anchorRectProvider: (() -> NSRect?)? { get set }
}
/// Optional protocol for plugins that need to protect the host menu-bar status-item position.
@MainActor
public protocol MenuBarHostStatusItemRecovering: AnyObject {
var hostStatusItemFrameProvider: (() -> NSRect?)? { get set }
var resetHostStatusItemPosition: (() -> Void)? { get set }
}
/// Optional protocol for plugins that need to open their settings page from custom UI, such as a floating panel.
/// Does not change the `MacToolsPlugin` witness table, so installed legacy plugins are unaffected.
@MainActor
public protocol PluginConfigurationPresenting: AnyObject {
/// Host-injected callback requesting presentation of this plugin's settings page.
var requestConfigurationPresentation: (() -> Void)? { get set }
}
/// Optional protocol for built-in plugins whose feature visibility should
/// pause/resume heavyweight observers or external side effects.
/// Dynamic plugins are paused by `DynamicPluginManager` instead.
@MainActor
public protocol PluginFeatureVisibilityLifecycleHandling: AnyObject {
func featureVisibilityDidChange(_ isVisible: Bool)
}
/// Optional hook for built-in plugins that cache localized descriptors or
/// other language-dependent presentation data. The host invokes it when the
/// app language changes; implementations must not activate, deactivate, or
/// reset the plugin's functional state. Dynamic plugins read localization at
/// render time and do not need this hook.
@MainActor
public protocol PluginRuntimeLocalizationRefreshing: AnyObject {
func refreshLocalization()
}