From d777ad66337e36199b8b142eef6a82c8381d55d8 Mon Sep 17 00:00:00 2001 From: kdletters Date: Sat, 20 Jun 2026 12:21:34 +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=E4=B8=8D=E5=8F=AF=E7=94=A8=E5=93=8D=E5=BA=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 桌面文件导出把系统写入和线程失败转为稳定 host_error 桌面文件导入把后台读取线程失败转为稳定 host_error 桌面文件单测覆盖不可用响应 code 和 message 桌面壳配置检查反查文件不可用响应边界 --- apps/desktop-shell/scripts/check-config.mjs | 5 ++ .../src-tauri/src/host_bridge/files.rs | 50 +++++++++++++++---- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/apps/desktop-shell/scripts/check-config.mjs b/apps/desktop-shell/scripts/check-config.mjs index 56a467e7e..f6433f93e 100644 --- a/apps/desktop-shell/scripts/check-config.mjs +++ b/apps/desktop-shell/scripts/check-config.mjs @@ -2235,9 +2235,14 @@ const requiredRustHostSnippets = [ '"copied_to_clipboard"', 'file_export_cancelled_response', 'file_import_cancelled_response', + 'file_export_unavailable_response', + 'file_import_unavailable_response', 'desktop_file_cancelled_responses_are_stable', + 'desktop_file_unavailable_responses_are_stable', '"file export cancelled"', '"file import cancelled"', + '"file export unavailable"', + '"file import unavailable"', 'BASE64_STANDARD.decode', 'blocking_pick_file', 'import_text_file_payload', 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 02c2b5785..c63f15273 100644 --- a/apps/desktop-shell/src-tauri/src/host_bridge/files.rs +++ b/apps/desktop-shell/src-tauri/src/host_bridge/files.rs @@ -15,6 +15,22 @@ fn file_import_cancelled_response(request: &HostBridgeRequest) -> HostBridgeResp failed(request.id.clone(), "cancelled", "file import cancelled") } +fn file_export_unavailable_response(request: &HostBridgeRequest) -> HostBridgeResponse { + failed( + request.id.clone(), + "host_error", + "file export unavailable", + ) +} + +fn file_import_unavailable_response(request: &HostBridgeRequest) -> HostBridgeResponse { + failed( + request.id.clone(), + "host_error", + "file import unavailable", + ) +} + pub(crate) async fn export_desktop_host_bridge_text_file( app: &tauri::AppHandle, request: &HostBridgeRequest, @@ -40,8 +56,7 @@ pub(crate) async fn export_desktop_host_bridge_text_file( tauri::async_runtime::spawn_blocking(move || write_export_text_file(path, content)).await; let bytes = match export_result { Ok(Ok(bytes)) => bytes, - Ok(Err(error)) => return failed(request.id.clone(), "host_error", error), - Err(error) => return failed(request.id.clone(), "host_error", error.to_string()), + Ok(Err(_)) | Err(_) => return file_export_unavailable_response(request), }; ok( @@ -75,7 +90,7 @@ pub(crate) async fn import_desktop_host_bridge_text_file( match import_result { Ok(Ok(payload)) => ok(request.id.clone(), payload), Ok(Err(error)) => failed(request.id.clone(), "invalid_request", error), - Err(error) => failed(request.id.clone(), "host_error", error.to_string()), + Err(_) => file_import_unavailable_response(request), } } @@ -103,7 +118,7 @@ pub(crate) async fn import_desktop_host_bridge_document_file( match import_result { Ok(Ok(payload)) => ok(request.id.clone(), payload), Ok(Err(error)) => failed(request.id.clone(), "invalid_request", error), - Err(error) => failed(request.id.clone(), "host_error", error.to_string()), + Err(_) => file_import_unavailable_response(request), } } @@ -132,8 +147,7 @@ pub(crate) async fn export_desktop_host_bridge_image_file( tauri::async_runtime::spawn_blocking(move || write_export_bytes_file(path, bytes)).await; let byte_count = match export_result { Ok(Ok(byte_count)) => byte_count, - Ok(Err(error)) => return failed(request.id.clone(), "host_error", error), - Err(error) => return failed(request.id.clone(), "host_error", error.to_string()), + Ok(Err(_)) | Err(_) => return file_export_unavailable_response(request), }; ok( request.id.clone(), @@ -168,7 +182,7 @@ pub(crate) async fn import_desktop_host_bridge_image_file( match import_result { Ok(Ok(payload)) => ok(request.id.clone(), payload), Ok(Err(error)) => failed(request.id.clone(), "invalid_request", error), - Err(error) => failed(request.id.clone(), "host_error", error.to_string()), + Err(_) => file_import_unavailable_response(request), } } @@ -193,7 +207,7 @@ pub(crate) async fn import_desktop_host_bridge_audio_file( match import_result { Ok(Ok(payload)) => ok(request.id.clone(), payload), Ok(Err(error)) => failed(request.id.clone(), "invalid_request", error), - Err(error) => failed(request.id.clone(), "host_error", error.to_string()), + Err(_) => file_import_unavailable_response(request), } } @@ -222,8 +236,7 @@ pub(crate) async fn export_desktop_host_bridge_audio_file( tauri::async_runtime::spawn_blocking(move || write_export_bytes_file(path, bytes)).await; let byte_count = match export_result { Ok(Ok(byte_count)) => byte_count, - Ok(Err(error)) => return failed(request.id.clone(), "host_error", error), - Err(error) => return failed(request.id.clone(), "host_error", error.to_string()), + Ok(Err(_)) | Err(_) => return file_export_unavailable_response(request), }; ok( request.id.clone(), @@ -256,4 +269,21 @@ mod tests { assert_eq!(import_error.code, "cancelled"); assert_eq!(import_error.message, "file import cancelled"); } + + #[test] + fn desktop_file_unavailable_responses_are_stable() { + let request = request("file.importText"); + + let export_error = file_export_unavailable_response(&request) + .error + .expect("export error"); + assert_eq!(export_error.code, "host_error"); + assert_eq!(export_error.message, "file export unavailable"); + + let import_error = file_import_unavailable_response(&request) + .error + .expect("import error"); + assert_eq!(import_error.code, "host_error"); + assert_eq!(import_error.message, "file import unavailable"); + } }