224 lines
6.4 KiB
Swift
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 []
|
|
}
|
|
}
|
|
}
|