feat: add TextInserter with clipboard restore and PassthroughCleaner
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
import Foundation
|
||||
|
||||
public typealias PasteboardItem = [String: Data]
|
||||
|
||||
public protocol PasteboardProviding {
|
||||
func readItems() -> [PasteboardItem]
|
||||
func writeString(_ text: String)
|
||||
func writeItems(_ items: [PasteboardItem])
|
||||
}
|
||||
|
||||
public protocol KeystrokePosting {
|
||||
func postPaste() throws
|
||||
}
|
||||
|
||||
public struct TextInserter: TextInserting {
|
||||
private let pasteboard: PasteboardProviding
|
||||
private let paster: KeystrokePosting
|
||||
private let restoreDelay: Duration
|
||||
|
||||
public init(
|
||||
pasteboard: PasteboardProviding,
|
||||
paster: KeystrokePosting,
|
||||
restoreDelay: Duration = .milliseconds(150)
|
||||
) {
|
||||
self.pasteboard = pasteboard
|
||||
self.paster = paster
|
||||
self.restoreDelay = restoreDelay
|
||||
}
|
||||
|
||||
public func insert(_ text: String) async throws {
|
||||
let saved = pasteboard.readItems()
|
||||
pasteboard.writeString(text)
|
||||
// On failure the text deliberately stays on the clipboard.
|
||||
try paster.postPaste()
|
||||
// Give the target app time to read the clipboard before restoring it.
|
||||
try await Task.sleep(for: restoreDelay)
|
||||
pasteboard.writeItems(saved)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user