From a1ff692912df5dbb3754d1898cc540343179ad5c Mon Sep 17 00:00:00 2001 From: kdletters Date: Sat, 20 Jun 2026 12:17:05 +0800 Subject: [PATCH] =?UTF-8?q?=E9=94=81=E5=AE=9A=E6=A1=8C=E9=9D=A2=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=8F=96=E6=B6=88=E5=93=8D=E5=BA=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 桌面文件桥接收口导出取消响应构造 桌面文件桥接收口导入取消响应构造 桌面文件单测覆盖取消响应 code 和 message 桌面壳配置检查反查文件取消响应边界 --- apps/desktop-shell/scripts/check-config.mjs | 3 ++ .../src-tauri/src/host_bridge/files.rs | 45 ++++++++++++++++--- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/apps/desktop-shell/scripts/check-config.mjs b/apps/desktop-shell/scripts/check-config.mjs index 2a36d2ed5..56a467e7e 100644 --- a/apps/desktop-shell/scripts/check-config.mjs +++ b/apps/desktop-shell/scripts/check-config.mjs @@ -2233,6 +2233,9 @@ const requiredRustHostSnippets = [ 'PermissionState::Prompt | PermissionState::PromptWithRationale', '"notification permission denied"', '"copied_to_clipboard"', + 'file_export_cancelled_response', + 'file_import_cancelled_response', + 'desktop_file_cancelled_responses_are_stable', '"file export cancelled"', '"file import cancelled"', 'BASE64_STANDARD.decode', diff --git a/apps/desktop-shell/src-tauri/src/host_bridge/files.rs b/apps/desktop-shell/src-tauri/src/host_bridge/files.rs index 9e927ad00..02c2b5785 100644 --- a/apps/desktop-shell/src-tauri/src/host_bridge/files.rs +++ b/apps/desktop-shell/src-tauri/src/host_bridge/files.rs @@ -7,6 +7,14 @@ use crate::host_bridge::protocol::{failed, ok, HostBridgeRequest, HostBridgeResp use serde_json::json; use tauri_plugin_dialog::DialogExt; +fn file_export_cancelled_response(request: &HostBridgeRequest) -> HostBridgeResponse { + failed(request.id.clone(), "cancelled", "file export cancelled") +} + +fn file_import_cancelled_response(request: &HostBridgeRequest) -> HostBridgeResponse { + failed(request.id.clone(), "cancelled", "file import cancelled") +} + pub(crate) async fn export_desktop_host_bridge_text_file( app: &tauri::AppHandle, request: &HostBridgeRequest, @@ -22,7 +30,7 @@ pub(crate) async fn export_desktop_host_bridge_text_file( .set_file_name(file_name.clone()) .blocking_save_file(); let Some(file_path) = file_path else { - return failed(request.id.clone(), "cancelled", "file export cancelled"); + return file_export_cancelled_response(request); }; let path = match file_path.into_path() { Ok(path) => path, @@ -56,7 +64,7 @@ pub(crate) async fn import_desktop_host_bridge_text_file( .add_filter("Text", &["txt", "md", "markdown", "csv", "json"]) .blocking_pick_file(); let Some(file_path) = file_path else { - return failed(request.id.clone(), "cancelled", "file import cancelled"); + return file_import_cancelled_response(request); }; let path = match file_path.into_path() { Ok(path) => path, @@ -84,7 +92,7 @@ pub(crate) async fn import_desktop_host_bridge_document_file( ) .blocking_pick_file(); let Some(file_path) = file_path else { - return failed(request.id.clone(), "cancelled", "file import cancelled"); + return file_import_cancelled_response(request); }; let path = match file_path.into_path() { Ok(path) => path, @@ -114,7 +122,7 @@ pub(crate) async fn export_desktop_host_bridge_image_file( .set_file_name(file_name.clone()) .blocking_save_file(); let Some(file_path) = file_path else { - return failed(request.id.clone(), "cancelled", "file export cancelled"); + return file_export_cancelled_response(request); }; let path = match file_path.into_path() { Ok(path) => path, @@ -147,7 +155,7 @@ pub(crate) async fn import_desktop_host_bridge_image_file( .add_filter("Image", &["png", "jpg", "jpeg", "webp"]) .blocking_pick_file(); let Some(file_path) = file_path else { - return failed(request.id.clone(), "cancelled", "file import cancelled"); + return file_import_cancelled_response(request); }; let path = match file_path.into_path() { Ok(path) => path, @@ -174,7 +182,7 @@ pub(crate) async fn import_desktop_host_bridge_audio_file( .add_filter("Audio", &["mp3", "m4a", "mp4", "wav", "ogg", "webm"]) .blocking_pick_file(); let Some(file_path) = file_path else { - return failed(request.id.clone(), "cancelled", "file import cancelled"); + return file_import_cancelled_response(request); }; let path = match file_path.into_path() { Ok(path) => path, @@ -204,7 +212,7 @@ pub(crate) async fn export_desktop_host_bridge_audio_file( .set_file_name(file_name.clone()) .blocking_save_file(); let Some(file_path) = file_path else { - return failed(request.id.clone(), "cancelled", "file export cancelled"); + return file_export_cancelled_response(request); }; let path = match file_path.into_path() { Ok(path) => path, @@ -226,3 +234,26 @@ pub(crate) async fn export_desktop_host_bridge_audio_file( }), ) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::host_bridge::protocol::request; + + #[test] + fn desktop_file_cancelled_responses_are_stable() { + let request = request("file.importText"); + + let export_error = file_export_cancelled_response(&request) + .error + .expect("export error"); + assert_eq!(export_error.code, "cancelled"); + assert_eq!(export_error.message, "file export cancelled"); + + let import_error = file_import_cancelled_response(&request) + .error + .expect("import error"); + assert_eq!(import_error.code, "cancelled"); + assert_eq!(import_error.message, "file import cancelled"); + } +}