feat: add native clipboard support for screenshot paste (#67)
CI / Lint & Test (push) Successful in 14m34s
CI / Build Linux (push) Successful in 18m19s
CI / Build Windows (cross-compile) (push) Successful in 27m57s
Security Scan and Upload / Security & DefectDojo Upload (push) Successful in 1m3s

## Summary
- Adds Tauri clipboard-manager plugin to read images from native clipboard
- Falls back to native clipboard when WebView clipboard API returns empty (fixes screenshot paste)
- Allows sending messages with just attachments (no text required)
- Logs attached files to output with 📎 emoji

## Test plan
- [ ] Build and run the app natively on Windows
- [ ] Copy a screenshot (Win+Shift+S) and paste in the chat input
- [ ] Verify the screenshot appears as an attachment preview
- [ ] Send the attachment and verify Claude receives the file path
- [ ] Test sending a message with only an attachment (no text)
- [ ] Verify the 📎 log line shows the attached filename

**Note:** Paste will not work in WSLg dev environment due to clipboard isolation - needs native Windows build to test.

 This PR was created with help from Hikari~ 🌸

Co-authored-by: Hikari <hikari@nhcarrigan.com>
Reviewed-on: #67
Co-authored-by: Naomi Carrigan <commits@nhcarrigan.com>
Co-committed-by: Naomi Carrigan <commits@nhcarrigan.com>
This commit was merged in pull request #67.
This commit is contained in:
2026-01-25 13:08:38 -08:00
committed by Naomi Carrigan
parent bbeff7ae2e
commit 852a4d6661
15 changed files with 1397 additions and 19 deletions
+20
View File
@@ -4,6 +4,7 @@ mod commands;
mod config;
mod notifications;
mod stats;
mod temp_manager;
mod types;
mod vbs_notification;
mod windows_toast;
@@ -14,6 +15,7 @@ use bridge_manager::create_shared_bridge_manager;
use commands::load_saved_achievements;
use commands::*;
use notifications::*;
use temp_manager::create_shared_temp_manager;
use vbs_notification::*;
use windows_toast::*;
use wsl_notifications::*;
@@ -21,6 +23,7 @@ use wsl_notifications::*;
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
let bridge_manager = create_shared_bridge_manager();
let temp_manager = create_shared_temp_manager().expect("Failed to create temp file manager");
tauri::Builder::default()
.plugin(tauri_plugin_dialog::init())
@@ -30,10 +33,20 @@ pub fn run() {
.plugin(tauri_plugin_notification::init())
.plugin(tauri_plugin_os::init())
.plugin(tauri_plugin_http::init())
.plugin(tauri_plugin_clipboard_manager::init())
.manage(bridge_manager.clone())
.manage(temp_manager.clone())
.setup(move |app| {
// Initialize the app handle in the bridge manager
bridge_manager.lock().set_app_handle(app.handle().clone());
// Clean up any orphaned temp files from previous sessions
if let Ok(count) = temp_manager.lock().cleanup_orphaned_files() {
if count > 0 {
println!("Cleaned up {} orphaned temp files", count);
}
}
Ok(())
})
.invoke_handler(tauri::generate_handler![
@@ -58,6 +71,13 @@ pub fn run() {
validate_directory,
list_skills,
check_for_updates,
save_temp_file,
register_temp_file,
get_temp_files,
cleanup_temp_files,
cleanup_all_temp_files,
cleanup_orphaned_temp_files,
get_file_size,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");