Fix paste-to-app, settings highlight, and titleBarStyle casing
Paste fix: - Switch from std::process::Command to tokio::process::Command to avoid blocking the async runtime (was stalling the paste action) - Use explicit AppleScript that activates the frontmost app before sending Cmd+V keystroke, making paste more reliable - Increase delay to 300ms for macOS app refocus - Add tokio "process" feature Settings highlight fix: - SettingsPanel now uses local useState for immediate optimistic updates when clicking position/history buttons, instead of waiting for the parent prop round-trip - Buttons highlight instantly on click, then sync with backend Config fix: - titleBarStyle must be PascalCase "Overlay" in Tauri 2 config (was lowercase "overlay" which caused a startup error) Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
80a6c01cdb
commit
11e91a4f36
11
src-tauri/Cargo.lock
generated
11
src-tauri/Cargo.lock
generated
@ -3098,6 +3098,16 @@ version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
|
||||
dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.9"
|
||||
@ -3742,6 +3752,7 @@ dependencies = [
|
||||
"libc",
|
||||
"mio",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.61.2",
|
||||
|
||||
@ -26,7 +26,7 @@ base64 = "0.22"
|
||||
log = "0.4"
|
||||
png = "0.17"
|
||||
dirs = "5"
|
||||
tokio = { version = "1", features = ["time", "macros"] }
|
||||
tokio = { version = "1", features = ["time", "macros", "process"] }
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-graphics = "0.24"
|
||||
|
||||
@ -74,16 +74,33 @@ pub async fn paste_and_refocus(app: tauri::AppHandle) -> Result<(), String> {
|
||||
}
|
||||
|
||||
// macOS needs time to refocus the previous application
|
||||
tokio::time::sleep(std::time::Duration::from_millis(250)).await;
|
||||
tokio::time::sleep(std::time::Duration::from_millis(300)).await;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
// .output() blocks until osascript finishes, ensuring the keystroke lands
|
||||
std::process::Command::new("osascript")
|
||||
// Activate the frontmost app explicitly, then send Cmd+V.
|
||||
// Using tokio::process::Command to avoid blocking the async runtime.
|
||||
let script = r#"
|
||||
tell application "System Events"
|
||||
set frontApp to name of first application process whose frontmost is true
|
||||
end tell
|
||||
tell application frontApp to activate
|
||||
delay 0.1
|
||||
tell application "System Events"
|
||||
keystroke "v" using command down
|
||||
end tell
|
||||
"#;
|
||||
let output = tokio::process::Command::new("osascript")
|
||||
.arg("-e")
|
||||
.arg(r#"tell application "System Events" to keystroke "v" using command down"#)
|
||||
.arg(script)
|
||||
.output()
|
||||
.map_err(|e| format!("osascript failed: {}", e))?;
|
||||
.await
|
||||
.map_err(|e| format!("osascript spawn failed: {}", e))?;
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
log::warn!("osascript paste failed: {}", stderr);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
"minWidth": 320,
|
||||
"minHeight": 300,
|
||||
"decorations": true,
|
||||
"titleBarStyle": "overlay",
|
||||
"titleBarStyle": "Overlay",
|
||||
"hiddenTitle": true,
|
||||
"visible": false,
|
||||
"alwaysOnTop": true,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useCallback } from "react";
|
||||
import { useState, useCallback } from "react";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import type { Settings } from "../types";
|
||||
|
||||
@ -19,11 +19,17 @@ const POSITION_OPTIONS: { value: string; label: string }[] = [
|
||||
{ value: "bottom-left", label: "Bottom left" },
|
||||
];
|
||||
|
||||
export default function SettingsPanel({ settings, onClose, onUpdate }: Props) {
|
||||
export default function SettingsPanel({ settings: initialSettings, onClose, onUpdate }: Props) {
|
||||
const [settings, setSettings] = useState<Settings>(initialSettings);
|
||||
|
||||
const updateSetting = useCallback(
|
||||
async (key: string, value: string) => {
|
||||
// Optimistically update local state for instant visual feedback
|
||||
setSettings((prev) => ({ ...prev, [key]: parseSettingValue(key, value) }));
|
||||
|
||||
await invoke("set_setting", { key, value });
|
||||
const updated: Settings = await invoke("get_settings");
|
||||
setSettings(updated);
|
||||
onUpdate(updated);
|
||||
},
|
||||
[onUpdate]
|
||||
@ -122,6 +128,13 @@ export default function SettingsPanel({ settings, onClose, onUpdate }: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
function parseSettingValue(key: string, value: string): unknown {
|
||||
if (key === "launch_at_login" || key === "show_images") return value === "true";
|
||||
if (key === "max_history" || key === "window_width" || key === "window_height")
|
||||
return parseInt(value, 10);
|
||||
return value;
|
||||
}
|
||||
|
||||
function ToggleRow({
|
||||
label,
|
||||
checked,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user