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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
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]]
|
[[package]]
|
||||||
name = "simd-adler32"
|
name = "simd-adler32"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@ -3742,6 +3752,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"signal-hook-registry",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
|
|||||||
@ -26,7 +26,7 @@ base64 = "0.22"
|
|||||||
log = "0.4"
|
log = "0.4"
|
||||||
png = "0.17"
|
png = "0.17"
|
||||||
dirs = "5"
|
dirs = "5"
|
||||||
tokio = { version = "1", features = ["time", "macros"] }
|
tokio = { version = "1", features = ["time", "macros", "process"] }
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
core-graphics = "0.24"
|
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
|
// 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")]
|
#[cfg(target_os = "macos")]
|
||||||
{
|
{
|
||||||
// .output() blocks until osascript finishes, ensuring the keystroke lands
|
// Activate the frontmost app explicitly, then send Cmd+V.
|
||||||
std::process::Command::new("osascript")
|
// 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("-e")
|
||||||
.arg(r#"tell application "System Events" to keystroke "v" using command down"#)
|
.arg(script)
|
||||||
.output()
|
.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(())
|
Ok(())
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
"minWidth": 320,
|
"minWidth": 320,
|
||||||
"minHeight": 300,
|
"minHeight": 300,
|
||||||
"decorations": true,
|
"decorations": true,
|
||||||
"titleBarStyle": "overlay",
|
"titleBarStyle": "Overlay",
|
||||||
"hiddenTitle": true,
|
"hiddenTitle": true,
|
||||||
"visible": false,
|
"visible": false,
|
||||||
"alwaysOnTop": true,
|
"alwaysOnTop": true,
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useCallback } from "react";
|
import { useState, useCallback } from "react";
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
import type { Settings } from "../types";
|
import type { Settings } from "../types";
|
||||||
|
|
||||||
@ -19,11 +19,17 @@ const POSITION_OPTIONS: { value: string; label: string }[] = [
|
|||||||
{ value: "bottom-left", label: "Bottom left" },
|
{ 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(
|
const updateSetting = useCallback(
|
||||||
async (key: string, value: string) => {
|
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 });
|
await invoke("set_setting", { key, value });
|
||||||
const updated: Settings = await invoke("get_settings");
|
const updated: Settings = await invoke("get_settings");
|
||||||
|
setSettings(updated);
|
||||||
onUpdate(updated);
|
onUpdate(updated);
|
||||||
},
|
},
|
||||||
[onUpdate]
|
[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({
|
function ToggleRow({
|
||||||
label,
|
label,
|
||||||
checked,
|
checked,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user