refactor: improve clipboard management and reliability

- Centralize clipboard operations through ClipboardManager

- Remove iOS-specific code

- Improve error handling and user feedback

- Make clipboard restoration non-blocking

- Add proper success/failure status for clipboard operations

- Increase error message visibility duration

- Use background queue for clipboard restoration
This commit is contained in:
Beingpax 2025-03-02 17:36:35 +05:45
parent e7e31f24d2
commit 9e5bb56242
4 changed files with 29 additions and 29 deletions

View File

@ -1,14 +1,20 @@
import SwiftUI
import AppKit
struct ClipboardManager {
static func copyToClipboard(_ text: String) {
#if os(macOS)
enum ClipboardError: Error {
case copyFailed
case accessDenied
}
static func copyToClipboard(_ text: String) -> Bool {
let pasteboard = NSPasteboard.general
pasteboard.clearContents()
pasteboard.setString(text, forType: .string)
#else
UIPasteboard.general.string = text
#endif
return pasteboard.setString(text, forType: .string)
}
static func getClipboardContent() -> String? {
return NSPasteboard.general.string(forType: .string)
}
}

View File

@ -1,7 +1,9 @@
import Foundation
import Cocoa
import AppKit
class CursorPaster {
private static let pasteCompletionDelay: TimeInterval = 0.3
static func pasteAtCursor(_ text: String) {
guard AXIsProcessTrusted() else {
print("Accessibility permissions not granted. Cannot paste at cursor.")
@ -33,8 +35,9 @@ class CursorPaster {
vUp?.post(tap: .cghidEventTap)
cmdUp?.post(tap: .cghidEventTap)
// Restore the original pasteboard contents
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
// Restore the original pasteboard contents after a delay
// Use a background queue to not block the main thread
DispatchQueue.global(qos: .userInitiated).asyncAfter(deadline: .now() + pasteCompletionDelay) {
if let oldContents = oldContents {
pasteboard.clearContents()
pasteboard.setString(oldContents, forType: .string)

View File

@ -536,9 +536,10 @@ struct TranscriptionCard: View {
}
private func copyToClipboard(_ text: String) {
let pasteboard = NSPasteboard.general
pasteboard.clearContents()
pasteboard.setString(text, forType: .string)
let success = ClipboardManager.copyToClipboard(text)
if !success {
print("Failed to copy text to clipboard")
}
}
private func formatDuration(_ duration: TimeInterval) -> String {

View File

@ -563,8 +563,13 @@ class WhisperState: NSObject, ObservableObject, AVAudioRecorderDelegate {
SoundManager.shared.playStopSound()
if isAutoCopyEnabled {
ClipboardManager.copyToClipboard(text)
clipboardMessage = "Transcription copied to clipboard"
let success = ClipboardManager.copyToClipboard(text)
if success {
clipboardMessage = "Transcription copied to clipboard"
} else {
clipboardMessage = "Failed to copy to clipboard"
messageLog += "Failed to copy transcription to clipboard\n"
}
}
if AXIsProcessTrusted() {
@ -576,11 +581,6 @@ class WhisperState: NSObject, ObservableObject, AVAudioRecorderDelegate {
messageLog += "Accessibility permissions not granted. Transcription not pasted automatically.\n"
}
Task {
try await Task.sleep(nanoseconds: 3_000_000_000)
clipboardMessage = ""
}
await cleanupResources()
// Don't set processing states to false here
@ -628,16 +628,6 @@ class WhisperState: NSObject, ObservableObject, AVAudioRecorderDelegate {
}
}
private func copyToClipboard(_ text: String) {
#if os(macOS)
let pasteboard = NSPasteboard.general
pasteboard.clearContents()
pasteboard.setString(text, forType: .string)
#else
UIPasteboard.general.string = text
#endif
}
@Published var isVisualizerActive = false
@Published var isMiniRecorderVisible = false {