Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ final class TextTranslationCoordinator {

// Step 3: Translate the captured text
if #available(macOS 13.0, *) {
let config = await TextTranslationConfig.fromAppSettings()
let config = TextTranslationConfig.fromAppSettings()
let translationResult = try await TextTranslationFlow.shared.translate(
selectionResult.text,
config: config
Expand Down Expand Up @@ -203,7 +203,7 @@ final class TextTranslationCoordinator {

do {
if #available(macOS 13.0, *) {
let config = await TextTranslationConfig.forTranslateAndInsert()
let config = TextTranslationConfig.forTranslateAndInsert()
let translationResult = try await TextTranslationFlow.shared.translate(selectedText, config: config)
translatedText = translationResult.translatedText

Expand Down
8 changes: 5 additions & 3 deletions ScreenTranslate/Features/Capture/ScreenDetector.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import Foundation
@preconcurrency import ScreenCaptureKit
import AppKit
import os

/// Service responsible for enumerating connected displays using ScreenCaptureKit.
/// Thread-safe actor that provides display discovery and matching with NSScreen.
actor ScreenDetector {
private let logger = Logger.capture
// MARK: - Types

/// Error types specific to screen detection
Expand Down Expand Up @@ -129,18 +131,18 @@ actor ScreenDetector {
// Quick check first using CGPreflightScreenCaptureAccess
guard CGPreflightScreenCaptureAccess() else {
cachedPermissionStatus = false
if !silent { print("[ScreenDetector] Permission check: denied (CGPreflight)") }
if !silent { logger.debug("Permission check: denied (CGPreflight)") }
return false
}
// Actually verify by trying to get shareable content
do {
_ = try await SCShareableContent.current
cachedPermissionStatus = true
if !silent { print("[ScreenDetector] Permission check: granted") }
if !silent { logger.debug("Permission check: granted") }
return true
} catch {
cachedPermissionStatus = false
if !silent { print("[ScreenDetector] Permission check: denied (SCShareableContent)") }
if !silent { logger.debug("Permission check: denied (SCShareableContent)") }
return false
}
}
Expand Down
6 changes: 4 additions & 2 deletions ScreenTranslate/Features/Preview/AnnotationCanvas.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import SwiftUI
import AppKit
import CoreImage
import os

/// SwiftUI Canvas view for drawing and displaying annotations.
/// Renders existing annotations and in-progress drawing.
struct AnnotationCanvas: View {
// MARK: - Shared CIContext for performance

private static let sharedCIContext = CIContext()
private static let logger = Logger.ui

// MARK: - Properties

Expand Down Expand Up @@ -399,14 +401,14 @@ struct AnnotationCanvas: View {

// Apply pixelation using CIPixellate filter
guard let pixellateFilter = CIFilter(name: "CIPixellate") else {
print("[Mosaic] Warning: CIPixellate filter not available, falling back to gray block")
Self.logger.warning("CIPixellate filter not available, falling back to gray block")
return nil
}
pixellateFilter.setValue(ciImage, forKey: kCIInputImageKey)
pixellateFilter.setValue(max(1, blockSize), forKey: kCIInputScaleKey)

guard let outputImage = pixellateFilter.outputImage else {
print("[Mosaic] Warning: Pixellation failed, falling back to gray block")
Self.logger.warning("Pixellation failed, falling back to gray block")
return nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,6 @@ struct CompatibleEngineConfigSheet: View {
let provider = try await CompatibleTranslationProvider(
config: engineConfig,
compatibleConfig: tempConfig,
instanceIndex: index,
keychain: KeychainService.shared
)

Expand Down
4 changes: 3 additions & 1 deletion ScreenTranslate/Features/Settings/EngineConfigSheet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import SwiftUI
import os

struct EngineConfigSheet: View {
let engine: TranslationEngineType
Expand All @@ -21,6 +22,7 @@ struct EngineConfigSheet: View {
@State private var isTesting = false
@State private var testResult: String?
@State private var testSuccess = false
private let logger = Logger.settings

var body: some View {
VStack(spacing: 20) {
Expand Down Expand Up @@ -339,7 +341,7 @@ struct EngineConfigSheet: View {
)
}
} catch {
print("Failed to save credentials: \(error)")
logger.error("Failed to save credentials: \(error.localizedDescription, privacy: .private(mask: .hash))")
}
}
}
Expand Down
28 changes: 6 additions & 22 deletions ScreenTranslate/Features/Settings/MultiEngineSettingsSection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -495,21 +495,11 @@ struct MultiEngineSettingsSection: View {
private func deleteCompatibleEngine(at index: Int) {
Task {
do {
let compositeId = "custom:\(index)"
try await KeychainService.shared.deleteCredentials(forCompatibleId: compositeId)

// Shift credentials for remaining engines
for i in (index + 1)..<viewModel.settings.compatibleProviderConfigs.count {
let oldId = "custom:\(i)"
let newId = "custom:\(i - 1)"
if let creds = try? await KeychainService.shared.getCredentials(forCompatibleId: oldId) {
try await KeychainService.shared.saveCredentials(apiKey: creds.apiKey, forCompatibleId: newId)
try await KeychainService.shared.deleteCredentials(forCompatibleId: oldId)
}
}
let config = viewModel.settings.compatibleProviderConfigs[index]
try await KeychainService.shared.deleteCredentials(forCompatibleId: config.keychainId)

// Clear cached provider for this engine
await TranslationEngineRegistry.shared.removeCompatibleProvider(for: compositeId)
await TranslationEngineRegistry.shared.removeCompatibleProvider(for: config.keychainId)

await MainActor.run {
viewModel.settings.compatibleProviderConfigs.remove(at: index)
Expand All @@ -531,10 +521,8 @@ struct MultiEngineSettingsSection: View {
private func setCompatibleAsEngineAtIndex(config: CompatibleTranslationProvider.CompatibleConfig, index: Int) {
Task {
do {
let configIndex = viewModel.settings.compatibleProviderConfigs.firstIndex(where: { $0.id == config.id }) ?? 0
let provider = try await TranslationEngineRegistry.shared.createCompatibleProvider(
compatibleConfig: config,
index: configIndex
compatibleConfig: config
)

let isAvailable = await provider.isAvailable
Expand Down Expand Up @@ -562,10 +550,8 @@ struct MultiEngineSettingsSection: View {
private func appendCompatibleAsEngine(config: CompatibleTranslationProvider.CompatibleConfig) {
Task {
do {
let configIndex = viewModel.settings.compatibleProviderConfigs.firstIndex(where: { $0.id == config.id }) ?? 0
let provider = try await TranslationEngineRegistry.shared.createCompatibleProvider(
compatibleConfig: config,
index: configIndex
compatibleConfig: config
)

let isAvailable = await provider.isAvailable
Expand Down Expand Up @@ -594,10 +580,8 @@ struct MultiEngineSettingsSection: View {
Task {
do {
// Create provider to verify configuration
let index = viewModel.settings.compatibleProviderConfigs.firstIndex(where: { $0.id == config.id }) ?? 0
let provider = try await TranslationEngineRegistry.shared.createCompatibleProvider(
compatibleConfig: config,
index: index
compatibleConfig: config
)

// Verify availability
Expand Down
24 changes: 12 additions & 12 deletions ScreenTranslate/Features/Settings/PromptSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ struct PromptSettingsView: View {
.font(.subheadline)
.foregroundStyle(.secondary)

ForEach(Array(viewModel.settings.compatibleProviderConfigs.enumerated()), id: \.element.id) { index, config in
ForEach(viewModel.settings.compatibleProviderConfigs) { config in
HStack {
Image(systemName: "gearshape.2")
.frame(width: 24)
Expand All @@ -109,14 +109,14 @@ struct PromptSettingsView: View {
Spacer()

// Show if custom prompt is set
if let prompt = viewModel.settings.promptConfig.compatibleEnginePrompts[index], !prompt.isEmpty {
if let prompt = viewModel.settings.promptConfig.compatibleEnginePrompts[config.id.uuidString], !prompt.isEmpty {
Image(systemName: "pencil.circle.fill")
.foregroundStyle(.tint)
}

Button(localized("prompt.button.edit")) {
editingTarget = .compatibleEngine(index)
editingPrompt = viewModel.settings.promptConfig.compatibleEnginePrompts[index] ?? ""
editingTarget = .compatibleEngine(config.id.uuidString, config.displayName)
editingPrompt = viewModel.settings.promptConfig.compatibleEnginePrompts[config.id.uuidString] ?? ""
}
.buttonStyle(.bordered)
.controlSize(.small)
Expand Down Expand Up @@ -212,11 +212,11 @@ struct PromptSettingsView: View {
} else {
config.enginePrompts[engine] = prompt
}
case .compatibleEngine(let index):
case .compatibleEngine(let promptID, _):
if prompt.isEmpty {
config.compatibleEnginePrompts.removeValue(forKey: index)
config.compatibleEnginePrompts.removeValue(forKey: promptID)
} else {
config.compatibleEnginePrompts[index] = prompt
config.compatibleEnginePrompts[promptID] = prompt
}
case .scene(let scene):
if prompt.isEmpty {
Expand Down Expand Up @@ -251,15 +251,15 @@ struct PromptSettingsView: View {

enum PromptEditTarget: Identifiable {
case engine(TranslationEngineType)
case compatibleEngine(Int)
case compatibleEngine(String, String)
case scene(TranslationScene)

var id: String {
switch self {
case .engine(let engine):
return "engine-\(engine.rawValue)"
case .compatibleEngine(let index):
return "compatible-\(index)"
case .compatibleEngine(let promptID, _):
return "compatible-\(promptID)"
case .scene(let scene):
return "scene-\(scene.rawValue)"
}
Expand All @@ -269,8 +269,8 @@ enum PromptEditTarget: Identifiable {
switch self {
case .engine(let engine):
return engine.localizedName
case .compatibleEngine(let index):
return "Compatible Engine \(index + 1)"
case .compatibleEngine(_, let displayName):
return displayName
case .scene(let scene):
return scene.localizedName
}
Expand Down
Loading
Loading