1use ferrix_lib::{
24 battery::BatInfo,
25 cpu::{Processors, Stat},
26 drm::Video,
27 init::{Connection, SystemdServices},
28 ram::RAM,
29 sys::{Groups, OsRelease, Users},
30 traits::ToJson,
31};
32use iced::Task;
33
34use crate::{
35 DataLoadingState, Ferrix, KernelData, Page, SETTINGS_PATH, Style, System,
36 dmi::DMIResult,
37 export::{ExportData, ExportFormat, ExportMode},
38 utils::get_home,
39};
40
41#[derive(Debug, Clone)]
42pub enum Message {
43 DataReceiver(DataReceiverMessage),
44 ExportManager(ExportManagerMessage),
45 Settings(SettingsMessage),
46 Buttons(ButtonsMessage),
47
48 SelectPage(Page),
49 Dummy,
50}
51
52impl Message {
53 pub fn update<'a>(self, state: &'a mut Ferrix) -> Task<Message> {
54 match self {
55 Self::DataReceiver(data) => data.update(state),
56 Self::ExportManager(export) => export.update(state),
57 Self::Settings(settings) => settings.update(state),
58 Self::Buttons(buttons) => buttons.update(state),
59
60 Self::SelectPage(page) => state.select_page(page),
61 Self::Dummy => Task::none(),
62 }
63 }
64}
65
66impl Ferrix {
67 fn select_page(&mut self, page: Page) -> Task<Message> {
68 self.current_page = page;
69 Task::none()
70 }
71}
72
73#[derive(Debug, Clone)]
74pub enum DataReceiverMessage {
75 GetCPUData,
76 CPUDataReceived(DataLoadingState<Processors>),
77
78 GetProcStat,
79 ProcStatReceived(DataLoadingState<Stat>),
80
81 GetRAMData,
82 RAMDataReceived(DataLoadingState<RAM>),
83
84 GetDMIData,
85 DMIDataReceived(DataLoadingState<DMIResult>),
86
87 GetBatInfo,
88 BatInfoReceived(DataLoadingState<BatInfo>),
89
90 GetDRMData,
91 DRMDataReceived(DataLoadingState<Video>),
92
93 GetOsReleaseData,
94 OsReleaseDataReceived(DataLoadingState<OsRelease>),
95
96 GetKernelData,
97 KernelDataReceived(DataLoadingState<KernelData>),
98
99 GetUsersData,
100 UsersDataReceived(DataLoadingState<Users>),
101
102 GetGroupsData,
103 GroupsDataReceived(DataLoadingState<Groups>),
104
105 GetSystemdServices,
106 SystemdServicesReceived(DataLoadingState<SystemdServices>),
107
108 GetSystemData,
109 SystemDataReceived(DataLoadingState<System>),
110}
111
112impl DataReceiverMessage {
113 pub fn update<'a>(self, fx: &'a mut Ferrix) -> Task<Message> {
114 match self {
115 Self::CPUDataReceived(state) => {
116 fx.proc_data = state;
117 Task::none()
118 }
119 Self::GetCPUData => Task::perform(
120 async move {
121 let proc = Processors::new();
122 match proc {
123 Ok(proc) => DataLoadingState::Loaded(proc),
124 Err(why) => DataLoadingState::Error(why.to_string()),
125 }
126 },
127 |val| Message::DataReceiver(Self::CPUDataReceived(val)),
128 ),
129 Self::ProcStatReceived(state) => {
130 if fx.curr_proc_stat.is_some() {
131 fx.prev_proc_stat = fx.curr_proc_stat.clone();
132 } else if fx.curr_proc_stat.is_none() && fx.prev_proc_stat.is_none() {
133 fx.prev_proc_stat = state.clone();
134 }
135 fx.curr_proc_stat = state;
136 Task::none()
137 }
138 Self::GetProcStat => Task::perform(
139 async move {
140 let stat = Stat::new();
141 match stat {
142 Ok(stat) => DataLoadingState::Loaded(stat),
143 Err(why) => DataLoadingState::Error(why.to_string()),
144 }
145 },
146 |val| Message::DataReceiver(Self::ProcStatReceived(val)),
147 ),
148 Self::DMIDataReceived(state) => {
149 fx.is_polkit = true;
150 if state.is_some() && fx.is_polkit {
151 fx.dmi_data = state;
152 } else if !fx.is_polkit {
153 fx.dmi_data = state;
154 }
155 Task::none()
156 }
157 Self::GetDMIData => {
158 if fx.dmi_data.is_none() && fx.current_page == Page::DMI && !fx.is_polkit {
159 Task::perform(async move { crate::dmi::get_dmi_data().await }, |val| {
160 Message::DataReceiver(Self::DMIDataReceived(val))
161 })
162 } else {
163 Task::none()
164 }
165 }
166 Self::BatInfoReceived(state) => {
167 fx.bat_data = state;
168 Task::none()
169 }
170 Self::GetBatInfo => Task::perform(
171 async move {
172 let bat = BatInfo::new();
173 match bat {
174 Ok(bat) => DataLoadingState::Loaded(bat),
175 Err(why) => DataLoadingState::Error(why.to_string()),
176 }
177 },
178 |val| Message::DataReceiver(Self::BatInfoReceived(val)),
179 ),
180 Self::DRMDataReceived(state) => {
181 fx.drm_data = state;
182 Task::none()
183 }
184 Self::GetDRMData => Task::perform(
185 async move {
186 let drm = Video::new();
187 match drm {
188 Ok(drm) => DataLoadingState::Loaded(drm),
189 Err(why) => DataLoadingState::Error(why.to_string()),
190 }
191 },
192 |val| Message::DataReceiver(Self::DRMDataReceived(val)),
193 ),
194 Self::RAMDataReceived(state) => {
195 fx.ram_data = state;
196 Task::none()
197 }
198 Self::GetRAMData => Task::perform(
199 async move {
200 let ram = RAM::new();
201 match ram {
202 Ok(ram) => DataLoadingState::Loaded(ram),
203 Err(why) => DataLoadingState::Error(why.to_string()),
204 }
205 },
206 |val| Message::DataReceiver(Self::RAMDataReceived(val)),
207 ),
208 Self::OsReleaseDataReceived(state) => {
209 fx.osrel_data = state;
210 Task::none()
211 }
212 Self::GetOsReleaseData => Task::perform(
213 async move {
214 let osrel = OsRelease::new();
215 match osrel {
216 Ok(osrel) => DataLoadingState::Loaded(osrel),
217 Err(why) => DataLoadingState::Error(why.to_string()),
218 }
219 },
220 |val| Message::DataReceiver(Self::OsReleaseDataReceived(val)),
221 ),
222 Self::KernelDataReceived(state) => {
223 fx.info_kernel = state;
224 Task::none()
225 }
226 Self::GetKernelData => Task::perform(
227 async move {
228 let kern = KernelData::new();
229 match kern {
230 Ok(mut kern) => {
231 kern.mods.modules.sort_by_key(|md| md.name.clone());
232 DataLoadingState::Loaded(kern)
233 }
234 Err(why) => DataLoadingState::Error(why.to_string()),
235 }
236 },
237 |val| Message::DataReceiver(Self::KernelDataReceived(val)),
238 ),
239 Self::UsersDataReceived(state) => {
240 fx.users_list = state;
241 Task::none()
242 }
243 Self::GetUsersData => Task::perform(
244 async move {
245 let users = Users::new();
246 match users {
247 Ok(mut users) => {
248 users.users.sort_by_key(|usr| usr.uid);
249 DataLoadingState::Loaded(users)
250 }
251 Err(why) => DataLoadingState::Error(why.to_string()),
252 }
253 },
254 |val| Message::DataReceiver(Self::UsersDataReceived(val)),
255 ),
256 Self::GroupsDataReceived(state) => {
257 fx.groups_list = state;
258 Task::none()
259 }
260 Self::GetGroupsData => Task::perform(
261 async move {
262 let groups = Groups::new();
263 match groups {
264 Ok(mut groups) => {
265 groups.groups.sort_by_key(|grp| grp.gid);
266 DataLoadingState::Loaded(groups)
267 }
268 Err(why) => DataLoadingState::Error(why.to_string()),
269 }
270 },
271 |val| Message::DataReceiver(Self::GroupsDataReceived(val)),
272 ),
273 Self::SystemdServicesReceived(state) => {
274 fx.sysd_services_list = state;
275 Task::none()
276 }
277 Self::GetSystemdServices => Task::perform(
278 async move {
279 let conn = Connection::session().await;
280 if let Err(why) = conn {
281 return DataLoadingState::Error(why.to_string());
282 }
283 let conn = conn.unwrap();
284
285 let srv_list = SystemdServices::new_from_connection(&conn).await;
286 match srv_list {
287 Ok(srv_list) => DataLoadingState::Loaded(srv_list),
288 Err(why) => DataLoadingState::Error(why.to_string()),
289 }
290 },
291 |val| Message::DataReceiver(Self::SystemdServicesReceived(val)),
292 ),
293 Self::SystemDataReceived(state) => {
294 fx.system = state;
295 Task::none()
296 }
297 Self::GetSystemData => Task::perform(
298 async move {
299 let sys = System::new();
300 match sys {
301 Ok(sys) => DataLoadingState::Loaded(sys),
302 Err(why) => DataLoadingState::Error(why.to_string()),
303 }
304 },
305 |val| Message::DataReceiver(Self::SystemDataReceived(val)),
306 ),
307 }
308 }
309}
310
311pub type ExportToFilePath = String;
312
313#[derive(Debug, Clone)]
314pub enum ExportManagerMessage {
315 ExportData(ExportToFilePath),
316 ExportFormatSelected(ExportFormat),
317 ExportModeSelected(ExportMode),
318}
319
320impl ExportManagerMessage {
321 pub fn update<'a>(self, fx: &'a mut Ferrix) -> Task<Message> {
322 match self {
323 Self::ExportData(path) => fx.export_data(&path),
324 _ => Task::none(),
325 }
326 }
327}
328
329impl Ferrix {
330 fn export_data(&mut self, path: &str) -> Task<Message> {
331 let json = ExportData::from(self)
332 .to_json()
333 .unwrap_or("{error}".to_string());
334 let _ = std::fs::write(path, json);
335 Task::none()
336 }
337}
338
339#[derive(Debug, Clone)]
340pub enum SettingsMessage {
341 ChangeStyle(Style),
342 ChangeUpdatePeriod(u8),
343}
344
345impl SettingsMessage {
346 pub fn update<'a>(self, fx: &'a mut Ferrix) -> Task<Message> {
347 match self {
348 Self::ChangeStyle(style) => fx.change_style(style),
349 Self::ChangeUpdatePeriod(secs) => fx.change_update_period(secs),
350 }
351 }
352}
353
354impl Ferrix {
355 fn change_style(&mut self, style: Style) -> Task<Message> {
356 self.settings.style = style;
357 Task::none()
358 }
359
360 fn change_update_period(&mut self, per: u8) -> Task<Message> {
361 self.settings.update_period = per;
362 Task::none()
363 }
364}
365
366#[derive(Debug, Clone)]
367pub enum ButtonsMessage {
368 LinkButtonPressed(String),
369 SaveSettingsButtonPressed,
370}
371
372impl ButtonsMessage {
373 pub fn update<'a>(self, fx: &'a mut Ferrix) -> Task<Message> {
374 match self {
375 Self::LinkButtonPressed(url) => fx.go_to_url(&url),
376 Self::SaveSettingsButtonPressed => fx.save_settings(),
377 }
378 }
379}
380
381impl Ferrix {
382 fn go_to_url(&self, url: &str) -> Task<Message> {
383 let _ = crate::utils::xdg_open(url);
385 Task::none()
386 }
387
388 fn save_settings(&mut self) -> Task<Message> {
389 let _ = self
391 .settings
392 .write(get_home().join(".config").join(SETTINGS_PATH));
393 Task::none()
394 }
395}