ferrix_app/
subscription.rs

1/* subscription.rs
2 *
3 * Copyright 2025 Michail Krasnov <mskrasnov07@ya.ru>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 *
18 * SPDX-License-Identifier: GPL-3.0-or-later
19 */
20
21use crate::{
22    Ferrix,
23    load_state::LoadState,
24    messages::{DataReceiverMessage, Message},
25    pages::Page,
26};
27use iced::{Subscription, time};
28use std::time::Duration;
29
30type Script<T> = Subscription<T>;
31type OScript<T> = Option<Script<T>>;
32
33const START_UPERIOD: u64 = 10;
34
35trait PushMaybe<T> {
36    fn push_maybe(&mut self, data: Option<T>);
37}
38
39impl<T> PushMaybe<T> for Vec<T> {
40    fn push_maybe(&mut self, data: Option<T>) {
41        if let Some(data) = data {
42            self.push(data);
43        }
44    }
45}
46
47impl Ferrix {
48    pub fn subscription(&self) -> Script<Message> {
49        let u = self.settings.update_period as u64;
50        let mut scripts = vec![
51            // Charts
52            time::every(Duration::from_secs(u))
53                .map(|_| Message::DataReceiver(DataReceiverMessage::AddCPUCoreLineSeries)),
54            time::every(Duration::from_secs(u))
55                .map(|_| Message::DataReceiver(DataReceiverMessage::AddTotalRAMUsage)),
56            // Charts update
57            iced::window::frames()
58                .map(|inst| Message::DataReceiver(DataReceiverMessage::AnimationTick(inst))),
59        ];
60        let oscripts = [
61            self.cpu_basic_data(),
62            self.cpu_stat_data(),
63            self.ram_data(),
64            self.swap_data(),
65            self.cpu_freq_subscription(),
66            self.cpu_vuln_subscription(),
67            self.storage_subscription(),
68            self.dmi_subscription(),
69            self.battery_subscription(),
70            self.drm_subscription(),
71            self.osrel_subscription(),
72            self.users_subscription(),
73            self.groups_subscription(),
74            self.sysd_subscription(),
75            self.soft_subscription(),
76            self.env_and_sys_subscription(),
77            self.kernel_subscription(),
78            self.kmods_subscription(),
79        ];
80        for oscr in oscripts {
81            scripts.push_maybe(oscr);
82        }
83        Subscription::batch(scripts)
84    }
85
86    fn u(&self) -> u64 {
87        self.settings.update_period as u64
88    }
89
90    fn cpu_basic_data(&self) -> OScript<Message> {
91        if (self.current_page == Page::Dashboard || self.current_page == Page::Processors)
92            && self.proc_data.is_none()
93        {
94            Some(
95                time::every(Duration::from_millis(START_UPERIOD))
96                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetCPUData)),
97            )
98        } else {
99            Some(
100                time::every(Duration::from_secs(self.u()))
101                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetCPUData)),
102            )
103        }
104    }
105
106    fn cpu_stat_data(&self) -> OScript<Message> {
107        if (self.current_page == Page::Dashboard || self.current_page == Page::SystemMonitor)
108            && self.curr_proc_stat.is_none()
109        {
110            Some(
111                time::every(Duration::from_millis(START_UPERIOD))
112                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetProcStat)),
113            )
114        } else {
115            Some(
116                time::every(Duration::from_secs(self.u()))
117                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetProcStat)),
118            )
119        }
120    }
121
122    fn ram_data(&self) -> OScript<Message> {
123        if (self.current_page == Page::Dashboard || self.current_page == Page::Memory)
124            && self.ram_data.is_none()
125        {
126            Some(
127                time::every(Duration::from_millis(START_UPERIOD))
128                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetRAMData)),
129            )
130        } else {
131            Some(
132                time::every(Duration::from_secs(self.u()))
133                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetRAMData)),
134            )
135        }
136    }
137
138    fn swap_data(&self) -> OScript<Message> {
139        if (self.current_page == Page::Dashboard || self.current_page == Page::Memory)
140            && self.swap_data.is_none()
141        {
142            Some(
143                time::every(Duration::from_millis(START_UPERIOD))
144                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetSwapData)),
145            )
146        } else {
147            Some(
148                time::every(Duration::from_secs(self.u()))
149                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetSwapData)),
150            )
151        }
152    }
153
154    fn cpu_freq_subscription(&self) -> OScript<Message> {
155        if self.current_page == Page::CPUFrequency && self.cpu_freq.is_none() {
156            Some(
157                time::every(Duration::from_millis(START_UPERIOD))
158                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetCPUFrequency)),
159            )
160        } else if self.current_page == Page::CPUFrequency {
161            Some(
162                time::every(Duration::from_secs(self.u()))
163                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetCPUFrequency)),
164            )
165        } else {
166            None
167        }
168    }
169
170    fn cpu_vuln_subscription(&self) -> OScript<Message> {
171        if self.current_page == Page::CPUVulnerabilities && self.cpu_vulnerabilities.is_none() {
172            Some(
173                time::every(Duration::from_millis(START_UPERIOD))
174                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetCPUVulnerabilities)),
175            )
176        } else {
177            None
178        }
179    }
180
181    fn storage_subscription(&self) -> OScript<Message> {
182        if self.current_page == Page::FileSystems && self.storages.is_none() {
183            Some(
184                time::every(Duration::from_millis(START_UPERIOD))
185                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetStorageData)),
186            )
187        } else if self.current_page == Page::FileSystems {
188            Some(
189                time::every(Duration::from_secs(10))
190                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetStorageData)),
191            )
192        } else {
193            None
194        }
195    }
196
197    fn dmi_subscription(&self) -> OScript<Message> {
198        if self.current_page == Page::DMI && !self.is_polkit && self.dmi_data.is_none() {
199            Some(
200                time::every(Duration::from_millis(START_UPERIOD))
201                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetDMIData)),
202            )
203        } else {
204            None
205        }
206    }
207
208    fn battery_subscription(&self) -> OScript<Message> {
209        if self.current_page == Page::Dashboard || self.current_page == Page::Battery {
210            match self.bat_data {
211                LoadState::Loaded(_) => Some(
212                    time::every(Duration::from_secs(self.u()))
213                        .map(|_| Message::DataReceiver(DataReceiverMessage::GetBatInfo)),
214                ),
215                _ => Some(
216                    time::every(Duration::from_millis(START_UPERIOD))
217                        .map(|_| Message::DataReceiver(DataReceiverMessage::GetBatInfo)),
218                ),
219            }
220        } else {
221            None
222        }
223    }
224
225    fn drm_subscription(&self) -> OScript<Message> {
226        if self.current_page == Page::Screen && self.drm_data.is_none() {
227            Some(
228                time::every(Duration::from_millis(START_UPERIOD))
229                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetDRMData)),
230            )
231        } else if self.current_page == Page::Screen && self.drm_data.is_some() {
232            Some(
233                time::every(Duration::from_secs(self.u()))
234                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetDRMData)),
235            )
236        } else {
237            None
238        }
239    }
240
241    fn osrel_subscription(&self) -> OScript<Message> {
242        if (self.current_page == Page::Dashboard || self.current_page == Page::Distro)
243            && self.osrel_data.is_none()
244        {
245            Some(
246                time::every(Duration::from_millis(START_UPERIOD))
247                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetOsReleaseData)),
248            )
249        } else {
250            None
251        }
252    }
253
254    fn users_subscription(&self) -> OScript<Message> {
255        if self.current_page == Page::Users && self.users_list.is_none() {
256            Some(
257                time::every(Duration::from_millis(START_UPERIOD))
258                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetUsersData)),
259            )
260        } else {
261            None
262        }
263    }
264
265    fn groups_subscription(&self) -> OScript<Message> {
266        if self.current_page == Page::Groups && self.groups_list.is_none() {
267            Some(
268                time::every(Duration::from_millis(START_UPERIOD))
269                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetGroupsData)),
270            )
271        } else {
272            None
273        }
274    }
275
276    fn sysd_subscription(&self) -> OScript<Message> {
277        if self.current_page == Page::SystemManager && self.sysd_services_list.is_none() {
278            Some(
279                time::every(Duration::from_millis(START_UPERIOD))
280                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetSystemdServices)),
281            )
282        } else if self.current_page == Page::SystemManager && self.sysd_services_list.is_some() {
283            Some(
284                time::every(Duration::from_secs(self.u() * 10))
285                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetSystemdServices)),
286            )
287        } else {
288            None
289        }
290    }
291
292    fn soft_subscription(&self) -> OScript<Message> {
293        if self.current_page == Page::Software && self.installed_pkgs_list.is_none() {
294            Some(
295                time::every(Duration::from_millis(START_UPERIOD))
296                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetPackagesList)),
297            )
298        } else {
299            None
300        }
301    }
302
303    fn env_and_sys_subscription(&self) -> OScript<Message> {
304        if self.current_page == Page::Environment
305            || self.current_page == Page::SystemMisc
306            || self.current_page == Page::Dashboard
307        {
308            if self.system.is_none() {
309                Some(
310                    time::every(Duration::from_millis(START_UPERIOD))
311                        .map(|_| Message::DataReceiver(DataReceiverMessage::GetSystemData)),
312                )
313            } else {
314                match self.current_page {
315                    Page::SystemMisc => Some(
316                        time::every(Duration::from_secs(self.u()))
317                            .map(|_| Message::DataReceiver(DataReceiverMessage::GetSystemData)),
318                    ),
319                    _ => None,
320                }
321            }
322        } else {
323            None
324        }
325    }
326
327    fn kernel_subscription(&self) -> OScript<Message> {
328        if self.current_page == Page::Kernel && self.kernel_data.is_none() {
329            Some(
330                time::every(Duration::from_millis(START_UPERIOD))
331                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetKernelData)),
332            )
333        } else {
334            None
335        }
336    }
337
338    fn kmods_subscription(&self) -> OScript<Message> {
339        if self.current_page == Page::KModules && self.kmods_data.is_none() {
340            Some(
341                time::every(Duration::from_millis(START_UPERIOD))
342                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetKModsData)),
343            )
344        } else {
345            None
346        }
347    }
348}