Skip to main content

launcher/pages/troubleshoot/
types.rs

1use crate::{
2    pages::troubleshoot::tasks::LocalProfileInfo,
3    tasks::{TaskEvent, TaskHandle},
4};
5use serde::Serialize;
6use supreme_diagnostics::PathDiagnostics;
7
8#[derive(Clone)]
9pub enum TroubleshootData {
10    Profiles(Vec<LocalProfileInfo>),
11    Diagnostics(PathDiagnostics),
12    RefreshStatus(bool),
13}
14
15#[derive(Serialize)]
16pub struct PerformanceEntry {
17    pub timestamp: u64,
18    pub operation: String,
19    pub target: String,
20    pub duration_ms: u128,
21}
22
23pub struct TroubleshootPageState {
24    pub is_running: bool,
25    pub status: String,
26    pub logs: Vec<String>,
27    pub task_handle: Option<TaskHandle<TroubleshootData>>,
28
29    pub total_items: usize,
30    pub processed_items: usize,
31
32    // Profile management
33    pub snapshot_name: String,
34    pub snapshot_description: String,
35    pub snapshot_version: String,
36    pub snapshot_compression: u32,
37    pub available_profiles: Vec<LocalProfileInfo>,
38    pub selected_profile: Option<String>, // filename
39
40    // Path diagnostics
41    pub path_diagnostics_available: bool,
42    pub last_diagnostics: Option<PathDiagnostics>,
43    pub performance_entries: Vec<PerformanceEntry>,
44    pub profile_refresh_active: bool,
45    pub has_attempted_profile_refresh: bool,
46
47    // UI state
48    pub show_create_popup: bool,
49    pub show_restore_popup: bool,
50    pub snapshot_directory: Option<std::path::PathBuf>,
51    pub group_versions: std::collections::HashMap<String, String>, // name -> filename
52}
53
54impl Default for TroubleshootPageState {
55    fn default() -> Self {
56        Self {
57            is_running: false,
58            status: "Ready".to_string(),
59            logs: Vec::new(),
60            task_handle: None,
61            total_items: 0,
62            processed_items: 0,
63            snapshot_name: "snapshot".to_string(),
64            snapshot_description: String::new(),
65            snapshot_version: String::new(),
66            snapshot_compression: 0,
67            available_profiles: Vec::new(),
68            selected_profile: None,
69            path_diagnostics_available: false,
70            last_diagnostics: None,
71            performance_entries: Vec::new(),
72            profile_refresh_active: false,
73            has_attempted_profile_refresh: false,
74            show_create_popup: false,
75            show_restore_popup: false,
76            snapshot_directory: None,
77            group_versions: std::collections::HashMap::new(),
78        }
79    }
80}
81
82impl TroubleshootPageState {
83    pub fn update(&mut self, storage: &supreme_fs::GameStorage) {
84        let mut task_finished = false;
85        if let Some(handle) = &self.task_handle {
86            while let Ok(event) = handle.try_recv() {
87                match event {
88                    TaskEvent::Log(msg) => self.logs.push(msg),
89                    TaskEvent::SetStatus(msg) => self.status = msg,
90                    TaskEvent::InitProgress(total) => {
91                        self.total_items = total;
92                        self.processed_items = 0;
93                    }
94                    TaskEvent::IncrementProgress => {
95                        self.processed_items += 1;
96                    }
97                    TaskEvent::UpdateProgress(p) => {
98                        self.processed_items = p;
99                    }
100                    TaskEvent::Perf(op, target, ms) => {
101                        self.performance_entries.push(PerformanceEntry {
102                            timestamp: std::time::SystemTime::now()
103                                .duration_since(std::time::UNIX_EPOCH)
104                                .unwrap_or_default()
105                                .as_secs(),
106                            operation: op,
107                            target,
108                            duration_ms: ms,
109                        });
110                    }
111                    TaskEvent::PageData(data) => match data {
112                        TroubleshootData::Profiles(mut profiles) => {
113                            profiles.sort_by(|a, b| {
114                                let name_a = a.name.as_deref().unwrap_or(&a.filename);
115                                let name_b = b.name.as_deref().unwrap_or(&b.filename);
116                                name_a.cmp(name_b)
117                            });
118                            self.available_profiles = profiles;
119                        }
120                        TroubleshootData::Diagnostics(diagnostics) => {
121                            self.last_diagnostics = Some(diagnostics);
122                        }
123                        TroubleshootData::RefreshStatus(active) => {
124                            self.profile_refresh_active = active;
125                        }
126                    },
127                    TaskEvent::Finished(res) => {
128                        task_finished = true;
129                        self.is_running = false;
130                        if let Err(e) =
131                            storage.write_report("performance", &self.performance_entries)
132                        {
133                            eprintln!("Failed to write performance report: {e}");
134                        }
135                        match res {
136                            Ok(_) => {
137                                self.status = "Operation completed successfully.".to_string();
138                                self.processed_items = self.total_items;
139                            }
140                            Err(e) => {
141                                self.status = format!("Error: {e}");
142                                self.logs.push(format!("Error: {e}"));
143                            }
144                        }
145                    }
146                }
147            }
148        }
149        if task_finished {
150            self.task_handle = None;
151        }
152    }
153}