@@ -11,9 +11,9 @@ use super::helpers::{is_same_filesystem, remove_dir_all_in_background, resolve_c
1111use super :: scan:: { SourceItemTracker , handle_dry_run, scan_sources} ;
1212use super :: state:: { CopyTransaction , OperationIntent , WriteOperationState , load_intent, update_operation_status} ;
1313use super :: types:: {
14- ConflictResolution , IoResultExt , TauriEventSink , WriteCancelledEvent , WriteCompleteEvent , WriteErrorEvent ,
15- WriteOperationConfig , WriteOperationError , WriteOperationPhase , WriteOperationType , WriteProgressEvent ,
16- WriteSourceItemDoneEvent ,
14+ ConflictResolution , IoResultExt , OperationEventSink , TauriEventSink , WriteCancelledEvent , WriteCompleteEvent ,
15+ WriteErrorEvent , WriteOperationConfig , WriteOperationError , WriteOperationPhase , WriteOperationType ,
16+ WriteProgressEvent , WriteSourceItemDoneEvent ,
1717} ;
1818
1919// ============================================================================
@@ -64,14 +64,24 @@ pub(super) fn move_files_with_progress(
6464 config : & WriteOperationConfig ,
6565) -> Result < ( ) , WriteOperationError > {
6666 let events = TauriEventSink :: new ( app. clone ( ) ) ;
67+ move_files_with_progress_inner ( & events, operation_id, state, sources, destination, config)
68+ }
6769
70+ pub ( super ) fn move_files_with_progress_inner (
71+ events : & dyn OperationEventSink ,
72+ operation_id : & str ,
73+ state : & Arc < WriteOperationState > ,
74+ sources : & [ PathBuf ] ,
75+ destination : & Path ,
76+ config : & WriteOperationConfig ,
77+ ) -> Result < ( ) , WriteOperationError > {
6878 // Handle dry-run mode
6979 if handle_dry_run (
7080 config. dry_run ,
7181 sources,
7282 destination,
7383 state,
74- & events,
84+ events,
7585 operation_id,
7686 WriteOperationType :: Move ,
7787 state. progress_interval ,
@@ -87,24 +97,21 @@ pub(super) fn move_files_with_progress(
8797
8898 if same_fs {
8999 // Use instant rename for each source
90- move_with_rename ( app , operation_id, state, sources, destination, config)
100+ move_with_rename ( events , operation_id, state, sources, destination, config)
91101 } else {
92102 // Use atomic staging pattern for cross-filesystem move
93- move_with_staging ( app , operation_id, state, sources, destination, config)
103+ move_with_staging ( events , operation_id, state, sources, destination, config)
94104 }
95105}
96106
97107fn move_with_rename (
98- app : & tauri :: AppHandle ,
108+ events : & dyn OperationEventSink ,
99109 operation_id : & str ,
100110 state : & Arc < WriteOperationState > ,
101111 sources : & [ PathBuf ] ,
102112 destination : & Path ,
103113 config : & WriteOperationConfig ,
104114) -> Result < ( ) , WriteOperationError > {
105- use tauri:: Emitter ;
106-
107- let events = TauriEventSink :: new ( app. clone ( ) ) ;
108115 let mut files_done = 0 ;
109116 let mut apply_to_all_resolution: Option < ConflictResolution > = None ;
110117 let mut move_tx = MoveTransaction :: new ( ) ;
@@ -131,7 +138,7 @@ fn move_with_rename(
131138 source,
132139 & dest_path,
133140 config,
134- & events,
141+ events,
135142 operation_id,
136143 state,
137144 & mut apply_to_all_resolution,
@@ -143,7 +150,7 @@ fn move_with_rename(
143150 source,
144151 & dest_path,
145152 config,
146- & events,
153+ events,
147154 operation_id,
148155 state,
149156 & mut apply_to_all_resolution,
@@ -165,13 +172,10 @@ fn move_with_rename(
165172
166173 files_done += 1 ;
167174
168- let _ = app. emit (
169- "write-source-item-done" ,
170- WriteSourceItemDoneEvent {
171- operation_id : operation_id. to_string ( ) ,
172- source_path : source. display ( ) . to_string ( ) ,
173- } ,
174- ) ;
175+ events. emit_source_item_done ( WriteSourceItemDoneEvent {
176+ operation_id : operation_id. to_string ( ) ,
177+ source_path : source. display ( ) . to_string ( ) ,
178+ } ) ;
175179 }
176180 Ok ( ( ) )
177181 } ) ( ) ;
@@ -188,15 +192,12 @@ fn move_with_rename(
188192 _ => false ,
189193 } ;
190194
191- let _ = app. emit (
192- "write-cancelled" ,
193- WriteCancelledEvent {
194- operation_id : operation_id. to_string ( ) ,
195- operation_type : WriteOperationType :: Move ,
196- files_processed : files_done,
197- rolled_back,
198- } ,
199- ) ;
195+ events. emit_cancelled ( WriteCancelledEvent {
196+ operation_id : operation_id. to_string ( ) ,
197+ operation_type : WriteOperationType :: Move ,
198+ files_processed : files_done,
199+ rolled_back,
200+ } ) ;
200201 return result;
201202 }
202203
@@ -206,15 +207,12 @@ fn move_with_rename(
206207 spawn_async_sync ( ) ;
207208
208209 // Emit completion (instant, no progress needed)
209- let _ = app. emit (
210- "write-complete" ,
211- WriteCompleteEvent {
212- operation_id : operation_id. to_string ( ) ,
213- operation_type : WriteOperationType :: Move ,
214- files_processed : files_done,
215- bytes_processed : 0 , // Rename doesn't track bytes
216- } ,
217- ) ;
210+ events. emit_complete ( WriteCompleteEvent {
211+ operation_id : operation_id. to_string ( ) ,
212+ operation_type : WriteOperationType :: Move ,
213+ files_processed : files_done,
214+ bytes_processed : 0 , // Rename doesn't track bytes
215+ } ) ;
218216
219217 Ok ( ( ) )
220218}
@@ -232,7 +230,7 @@ fn merge_move_directory(
232230 source_dir : & Path ,
233231 dest_dir : & Path ,
234232 config : & WriteOperationConfig ,
235- events : & dyn super :: types :: OperationEventSink ,
233+ events : & dyn OperationEventSink ,
236234 operation_id : & str ,
237235 state : & Arc < WriteOperationState > ,
238236 apply_to_all_resolution : & mut Option < ConflictResolution > ,
@@ -309,22 +307,18 @@ fn merge_move_directory(
309307/// Performs cross-filesystem move using atomic staging pattern.
310308/// This ensures source files remain intact if the operation fails.
311309fn move_with_staging (
312- app : & tauri :: AppHandle ,
310+ events : & dyn OperationEventSink ,
313311 operation_id : & str ,
314312 state : & Arc < WriteOperationState > ,
315313 sources : & [ PathBuf ] ,
316314 destination : & Path ,
317315 config : & WriteOperationConfig ,
318316) -> Result < ( ) , WriteOperationError > {
319- use tauri:: Emitter ;
320-
321- let events = TauriEventSink :: new ( app. clone ( ) ) ;
322-
323317 // Phase 1: Scan (move uses default sorting - order doesn't matter much for move)
324318 let scan_result = scan_sources (
325319 sources,
326320 state,
327- & events,
321+ events,
328322 operation_id,
329323 WriteOperationType :: Move ,
330324 config. sort_column ,
@@ -347,8 +341,8 @@ fn move_with_staging(
347341 let mut created_dirs: HashSet < PathBuf > = HashSet :: new ( ) ;
348342
349343 // Emit initial copying phase event
350- state. emit_progress_via_app (
351- app ,
344+ state. emit_progress_via_sink (
345+ events ,
352346 WriteProgressEvent :: new (
353347 operation_id. to_string ( ) ,
354348 WriteOperationType :: Move ,
@@ -395,7 +389,7 @@ fn move_with_staging(
395389 scan_result. file_count ,
396390 scan_result. total_bytes ,
397391 state,
398- & events,
392+ events,
399393 operation_id,
400394 WriteOperationType :: Move ,
401395 & state. progress_interval ,
@@ -407,13 +401,10 @@ fn move_with_staging(
407401 ) ?;
408402
409403 if let Some ( source_path) = tracker. record ( file_info) {
410- let _ = app. emit (
411- "write-source-item-done" ,
412- WriteSourceItemDoneEvent {
413- operation_id : operation_id. to_string ( ) ,
414- source_path : source_path. display ( ) . to_string ( ) ,
415- } ,
416- ) ;
404+ events. emit_source_item_done ( WriteSourceItemDoneEvent {
405+ operation_id : operation_id. to_string ( ) ,
406+ source_path : source_path. display ( ) . to_string ( ) ,
407+ } ) ;
417408 }
418409 }
419410 Ok ( ( ) )
@@ -422,10 +413,11 @@ fn move_with_staging(
422413 if let Err ( e) = copy_result {
423414 // Cleanup staging directory in background (may block on network mounts)
424415 remove_dir_all_in_background ( staging_dir. clone ( ) ) ;
425- let _ = app. emit (
426- "write-error" ,
427- WriteErrorEvent :: new ( operation_id. to_string ( ) , WriteOperationType :: Move , e. clone ( ) ) ,
428- ) ;
416+ events. emit_error ( WriteErrorEvent :: new (
417+ operation_id. to_string ( ) ,
418+ WriteOperationType :: Move ,
419+ e. clone ( ) ,
420+ ) ) ;
429421 return Err ( e) ;
430422 }
431423
@@ -448,7 +440,7 @@ fn move_with_staging(
448440 & staged_path,
449441 & final_path,
450442 config,
451- & events,
443+ events,
452444 operation_id,
453445 state,
454446 & mut apply_to_all_resolution,
@@ -460,7 +452,7 @@ fn move_with_staging(
460452 source,
461453 & final_path,
462454 config,
463- & events,
455+ events,
464456 operation_id,
465457 state,
466458 & mut apply_to_all_resolution,
@@ -495,15 +487,16 @@ fn move_with_staging(
495487 if let Err ( e) = rename_result {
496488 // Cleanup staging directory in background (may block on network mounts)
497489 remove_dir_all_in_background ( staging_dir) ;
498- let _ = app. emit (
499- "write-error" ,
500- WriteErrorEvent :: new ( operation_id. to_string ( ) , WriteOperationType :: Move , e. clone ( ) ) ,
501- ) ;
490+ events. emit_error ( WriteErrorEvent :: new (
491+ operation_id. to_string ( ) ,
492+ WriteOperationType :: Move ,
493+ e. clone ( ) ,
494+ ) ) ;
502495 return Err ( e) ;
503496 }
504497
505498 // Phase 4: Delete source files (only after successful copy+rename)
506- delete_sources_after_move ( app , operation_id, state, sources, files_done) ?;
499+ delete_sources_after_move ( events , operation_id, state, sources, files_done) ?;
507500
508501 // Phase 5: Remove empty staging directory
509502 let _ = fs:: remove_dir ( & staging_dir) ;
@@ -512,40 +505,32 @@ fn move_with_staging(
512505 spawn_async_sync ( ) ;
513506
514507 // Emit completion
515- let _ = app. emit (
516- "write-complete" ,
517- WriteCompleteEvent {
518- operation_id : operation_id. to_string ( ) ,
519- operation_type : WriteOperationType :: Move ,
520- files_processed : files_done,
521- bytes_processed : bytes_done,
522- } ,
523- ) ;
508+ events. emit_complete ( WriteCompleteEvent {
509+ operation_id : operation_id. to_string ( ) ,
510+ operation_type : WriteOperationType :: Move ,
511+ files_processed : files_done,
512+ bytes_processed : bytes_done,
513+ } ) ;
524514
525515 Ok ( ( ) )
526516}
527517
528518fn delete_sources_after_move (
529- app : & tauri :: AppHandle ,
519+ events : & dyn OperationEventSink ,
530520 operation_id : & str ,
531521 state : & Arc < WriteOperationState > ,
532522 sources : & [ PathBuf ] ,
533523 files_done : usize ,
534524) -> Result < ( ) , WriteOperationError > {
535- use tauri:: Emitter ;
536-
537525 for source in sources {
538526 // Check cancellation
539527 if super :: state:: is_cancelled ( & state. intent ) {
540- let _ = app. emit (
541- "write-cancelled" ,
542- WriteCancelledEvent {
543- operation_id : operation_id. to_string ( ) ,
544- operation_type : WriteOperationType :: Move ,
545- files_processed : files_done,
546- rolled_back : false , // Source deletion phase - nothing to rollback
547- } ,
548- ) ;
528+ events. emit_cancelled ( WriteCancelledEvent {
529+ operation_id : operation_id. to_string ( ) ,
530+ operation_type : WriteOperationType :: Move ,
531+ files_processed : files_done,
532+ rolled_back : false , // Source deletion phase - nothing to rollback
533+ } ) ;
549534 return Err ( WriteOperationError :: Cancelled {
550535 message : "Operation cancelled by user" . to_string ( ) ,
551536 } ) ;
@@ -559,13 +544,10 @@ fn delete_sources_after_move(
559544 fs:: remove_file ( source) . with_path ( source) ?;
560545 }
561546
562- let _ = app. emit (
563- "write-source-item-done" ,
564- WriteSourceItemDoneEvent {
565- operation_id : operation_id. to_string ( ) ,
566- source_path : source. display ( ) . to_string ( ) ,
567- } ,
568- ) ;
547+ events. emit_source_item_done ( WriteSourceItemDoneEvent {
548+ operation_id : operation_id. to_string ( ) ,
549+ source_path : source. display ( ) . to_string ( ) ,
550+ } ) ;
569551 }
570552 }
571553
0 commit comments