1- use crate :: dto:: { CleanConfigDto , CleanProgressDto , CleanSummaryDto } ;
1+ use crate :: dto:: { CleanConfigDto , CleanFailureDto , CleanProgressDto , CleanSummaryDto } ;
22use crate :: state:: AppState ;
3+ use null_e_core:: error:: NullEError ;
34use null_e_core:: trash:: { delete_path, DeleteMethod } ;
45use std:: path:: PathBuf ;
56use tauri:: { AppHandle , Emitter } ;
@@ -29,6 +30,7 @@ pub async fn start_clean(
2930 let mut succeeded = 0usize ;
3031 let mut failed = 0usize ;
3132 let mut bytes_freed = 0u64 ;
33+ let mut failures = Vec :: new ( ) ;
3234
3335 for ( i, target) in targets. iter ( ) . enumerate ( ) {
3436 let path = PathBuf :: from ( target) ;
@@ -46,8 +48,14 @@ pub async fn start_clean(
4648 succeeded += 1 ;
4749 bytes_freed += freed;
4850 }
49- Err ( _ ) => {
51+ Err ( err ) => {
5052 failed += 1 ;
53+ let ( reason, is_tcc) = classify_delete_error ( & err) ;
54+ failures. push ( CleanFailureDto {
55+ path : target. clone ( ) ,
56+ reason,
57+ is_tcc,
58+ } ) ;
5159 }
5260 }
5361 }
@@ -58,6 +66,11 @@ pub async fn start_clean(
5866 failed,
5967 bytes_freed,
6068 used_trash : method == DeleteMethod :: Trash ,
69+ method_label : match method {
70+ DeleteMethod :: Trash => "Trash" . to_string ( ) ,
71+ DeleteMethod :: Permanent | DeleteMethod :: DryRun => "Deleted" . to_string ( ) ,
72+ } ,
73+ failures,
6174 } ;
6275 let _ = app_handle. emit ( "clean:complete" , & summary) ;
6376 } ) ;
@@ -72,3 +85,23 @@ pub async fn cancel_clean(state: tauri::State<'_, AppState>) -> Result<(), Strin
7285 }
7386 Ok ( ( ) )
7487}
88+
89+ fn classify_delete_error ( err : & NullEError ) -> ( String , bool ) {
90+ match err {
91+ NullEError :: Io ( io_err) => {
92+ let is_tcc = io_err. raw_os_error ( ) == Some ( 1 ) ;
93+ ( io_err. to_string ( ) , is_tcc)
94+ }
95+ NullEError :: PermissionDenied ( path) => {
96+ ( format ! ( "Permission denied: {}" , path. display( ) ) , false )
97+ }
98+ NullEError :: Trash ( message) => {
99+ let lower = message. to_lowercase ( ) ;
100+ let is_tcc = lower. contains ( "operation not permitted" )
101+ || lower. contains ( "eperm" )
102+ || lower. contains ( "os error 1" ) ;
103+ ( message. clone ( ) , is_tcc)
104+ }
105+ _ => ( err. to_string ( ) , false ) ,
106+ }
107+ }
0 commit comments