Preserve transcription in clipboard by default, add restore option with configurable delay
This commit is contained in:
parent
45dbd57722
commit
baae439aae
@ -5,12 +5,11 @@ class CursorPaster {
|
|||||||
|
|
||||||
static func pasteAtCursor(_ text: String) {
|
static func pasteAtCursor(_ text: String) {
|
||||||
let pasteboard = NSPasteboard.general
|
let pasteboard = NSPasteboard.general
|
||||||
let preserveTranscript = UserDefaults.standard.bool(forKey: "preserveTranscriptInClipboard")
|
let shouldRestoreClipboard = UserDefaults.standard.bool(forKey: "restoreClipboardAfterPaste")
|
||||||
|
|
||||||
var savedContents: [(NSPasteboard.PasteboardType, Data)] = []
|
var savedContents: [(NSPasteboard.PasteboardType, Data)] = []
|
||||||
|
|
||||||
// Only save clipboard contents if we plan to restore them
|
if shouldRestoreClipboard {
|
||||||
if !preserveTranscript {
|
|
||||||
let currentItems = pasteboard.pasteboardItems ?? []
|
let currentItems = pasteboard.pasteboardItems ?? []
|
||||||
|
|
||||||
for item in currentItems {
|
for item in currentItems {
|
||||||
@ -22,7 +21,7 @@ class CursorPaster {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipboardManager.setClipboard(text, transient: !preserveTranscript)
|
ClipboardManager.setClipboard(text, transient: shouldRestoreClipboard)
|
||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
|
||||||
if UserDefaults.standard.bool(forKey: "UseAppleScriptPaste") {
|
if UserDefaults.standard.bool(forKey: "UseAppleScriptPaste") {
|
||||||
@ -32,8 +31,11 @@ class CursorPaster {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !preserveTranscript {
|
if shouldRestoreClipboard {
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.9) {
|
let restoreDelay = UserDefaults.standard.double(forKey: "clipboardRestoreDelay")
|
||||||
|
let delay = restoreDelay > 0 ? restoreDelay : 1.5
|
||||||
|
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
|
||||||
if !savedContents.isEmpty {
|
if !savedContents.isEmpty {
|
||||||
pasteboard.clearContents()
|
pasteboard.clearContents()
|
||||||
for (type, data) in savedContents {
|
for (type, data) in savedContents {
|
||||||
|
|||||||
@ -24,6 +24,8 @@ struct GeneralSettings: Codable {
|
|||||||
let isPauseMediaEnabled: Bool?
|
let isPauseMediaEnabled: Bool?
|
||||||
let isTextFormattingEnabled: Bool?
|
let isTextFormattingEnabled: Bool?
|
||||||
let isExperimentalFeaturesEnabled: Bool?
|
let isExperimentalFeaturesEnabled: Bool?
|
||||||
|
let restoreClipboardAfterPaste: Bool?
|
||||||
|
let clipboardRestoreDelay: Double?
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VoiceInkExportedSettings: Codable {
|
struct VoiceInkExportedSettings: Codable {
|
||||||
@ -103,7 +105,9 @@ class ImportExportService {
|
|||||||
isSystemMuteEnabled: mediaController.isSystemMuteEnabled,
|
isSystemMuteEnabled: mediaController.isSystemMuteEnabled,
|
||||||
isPauseMediaEnabled: playbackController.isPauseMediaEnabled,
|
isPauseMediaEnabled: playbackController.isPauseMediaEnabled,
|
||||||
isTextFormattingEnabled: UserDefaults.standard.object(forKey: keyIsTextFormattingEnabled) as? Bool ?? true,
|
isTextFormattingEnabled: UserDefaults.standard.object(forKey: keyIsTextFormattingEnabled) as? Bool ?? true,
|
||||||
isExperimentalFeaturesEnabled: UserDefaults.standard.bool(forKey: "isExperimentalFeaturesEnabled")
|
isExperimentalFeaturesEnabled: UserDefaults.standard.bool(forKey: "isExperimentalFeaturesEnabled"),
|
||||||
|
restoreClipboardAfterPaste: UserDefaults.standard.bool(forKey: "restoreClipboardAfterPaste"),
|
||||||
|
clipboardRestoreDelay: UserDefaults.standard.double(forKey: "clipboardRestoreDelay")
|
||||||
)
|
)
|
||||||
|
|
||||||
let exportedSettings = VoiceInkExportedSettings(
|
let exportedSettings = VoiceInkExportedSettings(
|
||||||
@ -275,6 +279,12 @@ class ImportExportService {
|
|||||||
if let textFormattingEnabled = general.isTextFormattingEnabled {
|
if let textFormattingEnabled = general.isTextFormattingEnabled {
|
||||||
UserDefaults.standard.set(textFormattingEnabled, forKey: self.keyIsTextFormattingEnabled)
|
UserDefaults.standard.set(textFormattingEnabled, forKey: self.keyIsTextFormattingEnabled)
|
||||||
}
|
}
|
||||||
|
if let restoreClipboard = general.restoreClipboardAfterPaste {
|
||||||
|
UserDefaults.standard.set(restoreClipboard, forKey: "restoreClipboardAfterPaste")
|
||||||
|
}
|
||||||
|
if let clipboardDelay = general.clipboardRestoreDelay {
|
||||||
|
UserDefaults.standard.set(clipboardDelay, forKey: "clipboardRestoreDelay")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.showRestartAlert(message: "Settings imported successfully from \(url.lastPathComponent). All settings (including general app settings) have been applied.")
|
self.showRestartAlert(message: "Settings imported successfully from \(url.lastPathComponent). All settings (including general app settings) have been applied.")
|
||||||
|
|||||||
@ -17,6 +17,8 @@ struct SettingsView: View {
|
|||||||
@AppStorage("hasCompletedOnboarding") private var hasCompletedOnboarding = true
|
@AppStorage("hasCompletedOnboarding") private var hasCompletedOnboarding = true
|
||||||
@AppStorage("autoUpdateCheck") private var autoUpdateCheck = true
|
@AppStorage("autoUpdateCheck") private var autoUpdateCheck = true
|
||||||
@AppStorage("enableAnnouncements") private var enableAnnouncements = true
|
@AppStorage("enableAnnouncements") private var enableAnnouncements = true
|
||||||
|
@AppStorage("restoreClipboardAfterPaste") private var restoreClipboardAfterPaste = false
|
||||||
|
@AppStorage("clipboardRestoreDelay") private var clipboardRestoreDelay = 1.5
|
||||||
@State private var showResetOnboardingAlert = false
|
@State private var showResetOnboardingAlert = false
|
||||||
@State private var currentShortcut = KeyboardShortcuts.getShortcut(for: .toggleMiniRecorder)
|
@State private var currentShortcut = KeyboardShortcuts.getShortcut(for: .toggleMiniRecorder)
|
||||||
@State private var isCustomCancelEnabled = false
|
@State private var isCustomCancelEnabled = false
|
||||||
@ -174,9 +176,9 @@ struct SettingsView: View {
|
|||||||
// Middle-Click Toggle
|
// Middle-Click Toggle
|
||||||
VStack(alignment: .leading, spacing: 12) {
|
VStack(alignment: .leading, spacing: 12) {
|
||||||
HStack(spacing: 8) {
|
HStack(spacing: 8) {
|
||||||
Toggle("Enable Middle-Click Toggle", isOn: $hotkeyManager.isMiddleClickToggleEnabled.animation())
|
Toggle("Enable Middle-Click Toggle", isOn: $hotkeyManager.isMiddleClickToggleEnabled)
|
||||||
.toggleStyle(.switch)
|
.toggleStyle(.switch)
|
||||||
|
|
||||||
InfoTip(
|
InfoTip(
|
||||||
title: "Middle-Click Toggle",
|
title: "Middle-Click Toggle",
|
||||||
message: "Use middle mouse button to toggle VoiceInk recording."
|
message: "Use middle mouse button to toggle VoiceInk recording."
|
||||||
@ -188,7 +190,7 @@ struct SettingsView: View {
|
|||||||
Text("Activation Delay")
|
Text("Activation Delay")
|
||||||
.font(.system(size: 13, weight: .medium))
|
.font(.system(size: 13, weight: .medium))
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
|
|
||||||
TextField("", value: $hotkeyManager.middleClickActivationDelay, formatter: {
|
TextField("", value: $hotkeyManager.middleClickActivationDelay, formatter: {
|
||||||
let formatter = NumberFormatter()
|
let formatter = NumberFormatter()
|
||||||
formatter.numberStyle = .none
|
formatter.numberStyle = .none
|
||||||
@ -200,14 +202,13 @@ struct SettingsView: View {
|
|||||||
.background(Color(NSColor.textBackgroundColor))
|
.background(Color(NSColor.textBackgroundColor))
|
||||||
.cornerRadius(5)
|
.cornerRadius(5)
|
||||||
.frame(width: 70)
|
.frame(width: 70)
|
||||||
|
|
||||||
Text("ms")
|
Text("ms")
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.padding(.leading, 16)
|
.padding(.leading, 16)
|
||||||
.transition(.opacity.combined(with: .move(edge: .top)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -258,14 +259,41 @@ struct SettingsView: View {
|
|||||||
.toggleStyle(.switch)
|
.toggleStyle(.switch)
|
||||||
.help("Automatically mute system audio when recording starts and restore when recording stops")
|
.help("Automatically mute system audio when recording starts and restore when recording stops")
|
||||||
|
|
||||||
Toggle(isOn: Binding(
|
VStack(alignment: .leading, spacing: 12) {
|
||||||
get: { UserDefaults.standard.bool(forKey: "preserveTranscriptInClipboard") },
|
HStack(spacing: 8) {
|
||||||
set: { UserDefaults.standard.set($0, forKey: "preserveTranscriptInClipboard") }
|
Toggle("Restore clipboard after paste", isOn: $restoreClipboardAfterPaste)
|
||||||
)) {
|
.toggleStyle(.switch)
|
||||||
Text("Preserve transcript in clipboard")
|
|
||||||
|
InfoTip(
|
||||||
|
title: "Restore Clipboard",
|
||||||
|
message: "When enabled, VoiceInk will restore your original clipboard content after pasting the transcription."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if restoreClipboardAfterPaste {
|
||||||
|
HStack(spacing: 8) {
|
||||||
|
Text("Restore Delay")
|
||||||
|
.font(.system(size: 13, weight: .medium))
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
|
||||||
|
Picker("", selection: $clipboardRestoreDelay) {
|
||||||
|
Text("0.5s").tag(0.5)
|
||||||
|
Text("1.0s").tag(1.0)
|
||||||
|
Text("1.5s").tag(1.5)
|
||||||
|
Text("2.0s").tag(2.0)
|
||||||
|
Text("2.5s").tag(2.5)
|
||||||
|
Text("3.0s").tag(3.0)
|
||||||
|
Text("4.0s").tag(4.0)
|
||||||
|
Text("5.0s").tag(5.0)
|
||||||
|
}
|
||||||
|
.pickerStyle(.menu)
|
||||||
|
.frame(width: 90)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.padding(.leading, 16)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.toggleStyle(.switch)
|
|
||||||
.help("Keep the transcribed text in clipboard instead of restoring the original clipboard content")
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user