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

224 lines
6.4 KiB
Swift

import Foundation
import MacToolsPluginKit
enum TranslatorQuerySource: Equatable, Sendable {
case selectedText
case screenshot
var sourceTitle: String {
switch self {
case .selectedText:
return "selectedText"
case .screenshot:
return "screenshot"
}
}
}
enum TranslatorCaptureStage: Equatable, Sendable {
case selectedText
case screenshotRegion
case ocr
var placeholderKey: String {
switch self {
case .selectedText:
return "panel.sourcePlaceholder.capturing"
case .screenshotRegion:
return "panel.sourcePlaceholder.screenshotRegion"
case .ocr:
return "panel.sourcePlaceholder.ocr"
}
}
}
enum TranslatorPanelPhase: Equatable, Sendable {
case idle
case capturing
case translating
case success
case error(TranslatorPanelError)
}
enum TranslatorPanelError: Equatable, Sendable {
case missingSelection
case missingOCRText
case missingConfiguration
case permissionRequired
case screenRecordingPermissionRequired
case screenshotCancelled
case screenshotRegionTooSmall
case screenshotFailed
case requestFailed(String)
var message: String {
message()
}
func message(localization: PluginLocalization = PluginLocalization(bundle: .main)) -> String {
switch self {
case .missingSelection:
return localization.string("panelError.missingSelection", defaultValue: "未找到选中文本")
case .missingOCRText:
return localization.string("panelError.missingOCRText", defaultValue: "截图中没有识别到文字")
case .missingConfiguration:
return localization.string("panelError.missingConfiguration", defaultValue: "请先配置 OpenAI")
case .permissionRequired:
return localization.string("panelError.permissionRequired", defaultValue: "需要辅助功能授权")
case .screenRecordingPermissionRequired:
return localization.string("panelError.screenRecordingPermissionRequired", defaultValue: "需要屏幕录制授权")
case .screenshotCancelled:
return localization.string("panelError.screenshotCancelled", defaultValue: "已取消截图")
case .screenshotRegionTooSmall:
return localization.string("panelError.screenshotRegionTooSmall", defaultValue: "截图区域太小")
case .screenshotFailed:
return localization.string("panelError.screenshotFailed", defaultValue: "截图失败")
case let .requestFailed(message):
return message
}
}
}
struct TranslatorPanelSnapshot: Equatable, Sendable {
var phase: TranslatorPanelPhase
var sourceText: String?
var languageSelection: TranslatorLanguageSelection?
var translation: TranslationResult?
var providerResults: [TranslatorProviderResult] = []
var errorMessage: String?
var querySource: TranslatorQuerySource? = nil
var captureStage: TranslatorCaptureStage? = nil
static let idle = TranslatorPanelSnapshot(
phase: .idle,
sourceText: nil,
languageSelection: nil,
translation: nil,
providerResults: [],
errorMessage: nil,
querySource: nil,
captureStage: nil
)
}
enum TranslatorPanelAction: Equatable, Sendable {
case retry
case close
case copySource
case copyTranslation
case copyProviderTranslation(String)
case speakSource
case speakTranslation
case openSettings
}
enum TranslatorProviderResultPhase: Equatable, Sendable {
case waiting
case translating
case success
case error
}
struct TranslatorProviderResult: Equatable, Identifiable, Sendable {
var id: String
var providerTitle: String
var phase: TranslatorProviderResultPhase
var translation: TranslationResult?
var errorMessage: String?
var text: String? {
translation?.text
}
}
struct ResolvedTranslationProvider: Sendable {
var id: String
var title: String
var provider: (any TranslationProviding)?
var errorMessage: String?
init(
id: String,
title: String,
provider: any TranslationProviding
) {
self.id = id
self.title = title
self.provider = provider
self.errorMessage = nil
}
init(
id: String,
title: String,
errorMessage: String
) {
self.id = id
self.title = title
self.provider = nil
self.errorMessage = errorMessage
}
}
enum TranslatorProviderBuildResult {
case provider(any TranslationProviding)
case providers([ResolvedTranslationProvider])
case missing(message: String)
var resolvedProviders: [ResolvedTranslationProvider]? {
resolvedProviders()
}
func resolvedProviders(
localization: PluginLocalization = PluginLocalization(bundle: .main)
) -> [ResolvedTranslationProvider]? {
switch self {
case let .provider(provider):
return [
ResolvedTranslationProvider(
id: "default",
title: localization.string("openAIClient.providerTitle", defaultValue: "OpenAI 翻译"),
provider: provider
),
]
case let .providers(providers):
return providers
case .missing:
return nil
}
}
var waitingProviderResults: [TranslatorProviderResult] {
waitingProviderResults()
}
func waitingProviderResults(
localization: PluginLocalization = PluginLocalization(bundle: .main)
) -> [TranslatorProviderResult] {
switch self {
case .provider:
return [
TranslatorProviderResult(
id: "default",
providerTitle: localization.string("openAIClient.providerTitle", defaultValue: "OpenAI 翻译"),
phase: .waiting,
translation: nil,
errorMessage: nil
),
]
case let .providers(providers):
return providers.map {
TranslatorProviderResult(
id: $0.id,
providerTitle: $0.title,
phase: .waiting,
translation: nil,
errorMessage: $0.errorMessage
)
}
case .missing:
return []
}
}
}