gravityfile_ops/
progress.rs1use std::path::PathBuf;
4
5use serde::{Deserialize, Serialize};
6
7use crate::OperationError;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
11pub enum OperationType {
12 Copy,
13 Move,
14 Delete,
15 Rename,
16 CreateFile,
17 CreateDirectory,
18}
19
20impl std::fmt::Display for OperationType {
21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 match self {
23 Self::Copy => write!(f, "Copy"),
24 Self::Move => write!(f, "Move"),
25 Self::Delete => write!(f, "Delete"),
26 Self::Rename => write!(f, "Rename"),
27 Self::CreateFile => write!(f, "Create file"),
28 Self::CreateDirectory => write!(f, "Create directory"),
29 }
30 }
31}
32
33#[derive(Debug, Clone)]
35pub struct OperationProgress {
36 pub operation_type: OperationType,
38 pub files_completed: usize,
40 pub files_total: usize,
42 pub bytes_processed: u64,
44 pub bytes_total: u64,
46 pub current_file: Option<PathBuf>,
48 pub errors: Vec<OperationError>,
50}
51
52impl OperationProgress {
53 pub fn new(operation_type: OperationType, files_total: usize, bytes_total: u64) -> Self {
55 Self {
56 operation_type,
57 files_completed: 0,
58 files_total,
59 bytes_processed: 0,
60 bytes_total,
61 current_file: None,
62 errors: Vec::new(),
63 }
64 }
65
66 pub fn percentage(&self) -> f64 {
68 if self.bytes_total > 0 {
69 (self.bytes_processed as f64 / self.bytes_total as f64) * 100.0
70 } else if self.files_total > 0 {
71 (self.files_completed as f64 / self.files_total as f64) * 100.0
72 } else {
73 0.0
74 }
75 }
76
77 pub fn has_errors(&self) -> bool {
79 !self.errors.is_empty()
80 }
81
82 pub fn error_count(&self) -> usize {
84 self.errors.len()
85 }
86
87 pub fn add_error(&mut self, error: OperationError) {
89 self.errors.push(error);
90 }
91
92 pub fn set_current_file(&mut self, path: Option<PathBuf>) {
94 self.current_file = path;
95 }
96
97 pub fn complete_file(&mut self, bytes: u64) {
99 self.files_completed += 1;
100 self.bytes_processed += bytes;
101 }
102}
103
104#[derive(Debug, Clone)]
106pub struct OperationComplete {
107 pub operation_type: OperationType,
109 pub succeeded: usize,
111 pub failed: usize,
113 pub bytes_processed: u64,
115 pub errors: Vec<OperationError>,
117}
118
119impl OperationComplete {
120 pub fn is_success(&self) -> bool {
122 self.failed == 0
123 }
124
125 pub fn summary(&self) -> String {
127 let action = match self.operation_type {
128 OperationType::Copy => "Copied",
129 OperationType::Move => "Moved",
130 OperationType::Delete => "Deleted",
131 OperationType::Rename => "Renamed",
132 OperationType::CreateFile => "Created",
133 OperationType::CreateDirectory => "Created",
134 };
135
136 if self.failed == 0 {
137 format!("{} {} items", action, self.succeeded)
138 } else {
139 format!(
140 "{} {} items, {} failed",
141 action, self.succeeded, self.failed
142 )
143 }
144 }
145}