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

149 lines
4.6 KiB
Swift

import AppKit
import Foundation
import SwiftUI
import MacToolsPluginKit
public final class IPOverviewPluginFactory: NSObject, MacToolsPluginBundleFactory {
public static func makeProvider(context: PluginRuntimeContext) throws -> any PluginProvider {
IPOverviewPluginProvider(context: context)
}
}
@MainActor
private struct IPOverviewPluginProvider: PluginProvider {
let context: PluginRuntimeContext
func makePlugins() -> [any MacToolsPlugin] {
[IPOverviewPlugin(context: context, localization: PluginLocalization(bundle: context.resourceBundle))]
}
}
@MainActor
final class IPOverviewPlugin: MacToolsPlugin, PluginPrimaryPanel, PluginConfigurationPresenting {
enum ControlID {
static let openSettings = "execute"
static let copyIP = "ip-overview-copy-ip"
}
let metadata: PluginMetadata
let primaryPanelDescriptor: PluginPrimaryPanelDescriptor
private let viewModel: IPOverviewViewModel
private let localization: PluginLocalization
var onStateChange: (() -> Void)?
var requestPermissionGuidance: ((String) -> Void)?
var shortcutBindingResolver: ((String) -> ShortcutBinding?)?
var requestConfigurationPresentation: (() -> Void)?
init(
context: PluginRuntimeContext = PluginRuntimeContext(pluginID: "ip-overview"),
viewModel: IPOverviewViewModel? = nil,
localization: PluginLocalization = PluginLocalization(bundle: .main)
) {
self.localization = localization
self.viewModel = viewModel ?? IPOverviewViewModel(storage: context.storage, localization: localization)
self.metadata = PluginMetadata(
id: "ip-overview",
title: localization.string("metadata.title", defaultValue: "IP 检测"),
iconName: "network",
iconTint: Color(nsColor: .systemBlue),
order: 12,
defaultDescription: localization.string(
"metadata.description",
defaultValue: "查看公网 IP、本地地址和归属地"
)
)
self.primaryPanelDescriptor = PluginPrimaryPanelDescriptor(
controlStyle: .button,
menuActionBehavior: .dismissBeforeHandling,
buttonTitleProvider: { localization.string("panel.button.check", defaultValue: "检测") }
)
self.viewModel.onSnapshotChange = { [weak self] in
self?.onStateChange?()
}
}
func activate(context: PluginRuntimeContext) {
viewModel.refreshIfNeeded()
}
func deactivate(reason: PluginDeactivationReason) {
viewModel.cancel()
}
func refresh() {
viewModel.refreshPublicIP()
}
var primaryPanelState: PluginPanelState {
PluginPanelState(
subtitle: panelSubtitle,
isOn: viewModel.snapshot.isRefreshing,
isExpanded: false,
isEnabled: true,
isVisible: true,
detail: nil,
errorMessage: viewModel.snapshot.errorMessage
)
}
var configuration: PluginConfiguration? {
PluginConfiguration(
description: metadata.defaultDescription,
prefersFullHeight: true
) { _ in
IPOverviewComponentView(
viewModel: self.viewModel,
localization: self.localization,
startsInDetails: true,
showsBackButton: false
)
}
}
func handleAction(_ action: PluginPanelAction) {
switch action {
case let .invokeAction(controlID):
handleInvoke(controlID: controlID)
case .setDisclosureExpanded,
.setSwitch,
.setSelection,
.setNavigationSelection,
.clearNavigationSelection,
.setDate,
.setSlider:
break
}
}
private var panelSubtitle: String {
let snapshot = viewModel.snapshot
if snapshot.isRefreshing {
return localization.string("panel.subtitle.refreshing", defaultValue: "正在检测公网 IP...")
}
if let ip = snapshot.preferredPublicIP?.ip {
return viewModel.hidesSensitiveInfo ? IPOverviewSensitiveValueMask.maskedIP(ip) : ip
}
if let errorMessage = snapshot.errorMessage {
return errorMessage
}
return metadata.defaultDescription
}
private func handleInvoke(controlID: String) {
switch controlID {
case ControlID.openSettings:
requestConfigurationPresentation?()
case ControlID.copyIP:
viewModel.copy(viewModel.snapshot.preferredPublicIP?.ip)
default:
break
}
}
}