Skip to main content

ferrix_app/
subscription.rs

1/* subscription.rs
2 *
3 * Copyright 2025-2026 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::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 mut scripts = vec![
50            // Charts
51            time::every(Duration::from_secs_f32(0.5))
52                .map(|_| Message::DataReceiver(DataReceiverMessage::AddCPUCoreLineSeries)),
53            time::every(Duration::from_secs_f32(0.5))
54                .map(|_| Message::DataReceiver(DataReceiverMessage::AddTotalRAMUsage)),
55        ];
56        let oscripts = [
57            self.cpu_basic_data(),
58            self.cpu_stat_data(),
59            self.ram_data(),
60            self.swap_data(),
61            self.cpu_freq_subscription(),
62            self.cpu_vuln_subscription(),
63            self.storage_subscription(),
64            self.dmi_subscription(),
65            self.battery_subscription(),
66            self.drm_subscription(),
67            self.osrel_subscription(),
68            self.users_subscription(),
69            self.groups_subscription(),
70            self.sysd_subscription(),
71            self.soft_subscription(),
72            self.env_and_sys_subscription(),
73            self.kernel_subscription(),
74            self.kmods_subscription(),
75        ];
76        for oscr in oscripts {
77            scripts.push_maybe(oscr);
78        }
79        Subscription::batch(scripts)
80    }
81
82    fn u(&self) -> u64 {
83        self.settings.update_period as u64
84    }
85
86    fn cpu_basic_data(&self) -> OScript<Message> {
87        if (self.current_page == Page::Dashboard || self.current_page == Page::Processors)
88            && self.data.proc_data.is_none()
89        {
90            Some(
91                time::every(Duration::from_millis(START_UPERIOD))
92                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetCPUData)),
93            )
94        } else {
95            Some(
96                time::every(Duration::from_secs(self.u()))
97                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetCPUData)),
98            )
99        }
100    }
101
102    fn cpu_stat_data(&self) -> OScript<Message> {
103        if (self.current_page == Page::Dashboard || self.current_page == Page::SystemMonitor)
104            && self.data.curr_proc_stat.is_none()
105        {
106            Some(
107                time::every(Duration::from_millis(START_UPERIOD))
108                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetProcStat)),
109            )
110        } else {
111            Some(
112                time::every(Duration::from_secs(self.u()))
113                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetProcStat)),
114            )
115        }
116    }
117
118    fn ram_data(&self) -> OScript<Message> {
119        if (self.current_page == Page::Dashboard || self.current_page == Page::Memory)
120            && self.data.ram_data.is_none()
121        {
122            Some(
123                time::every(Duration::from_millis(START_UPERIOD))
124                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetRAMData)),
125            )
126        } else {
127            Some(
128                time::every(Duration::from_secs(self.u()))
129                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetRAMData)),
130            )
131        }
132    }
133
134    fn swap_data(&self) -> OScript<Message> {
135        if (self.current_page == Page::Dashboard || self.current_page == Page::Memory)
136            && self.data.swap_data.is_none()
137        {
138            Some(
139                time::every(Duration::from_millis(START_UPERIOD))
140                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetSwapData)),
141            )
142        } else {
143            Some(
144                time::every(Duration::from_secs(self.u()))
145                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetSwapData)),
146            )
147        }
148    }
149
150    fn cpu_freq_subscription(&self) -> OScript<Message> {
151        if self.current_page == Page::CPUFrequency && self.data.cpu_freq.is_none() {
152            Some(
153                time::every(Duration::from_millis(START_UPERIOD))
154                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetCPUFrequency)),
155            )
156        } else if self.current_page == Page::CPUFrequency {
157            Some(
158                time::every(Duration::from_secs(self.u()))
159                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetCPUFrequency)),
160            )
161        } else {
162            None
163        }
164    }
165
166    fn cpu_vuln_subscription(&self) -> OScript<Message> {
167        if self.current_page == Page::CPUVulnerabilities && self.data.cpu_vulnerabilities.is_none()
168        {
169            Some(
170                time::every(Duration::from_millis(START_UPERIOD))
171                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetCPUVulnerabilities)),
172            )
173        } else {
174            None
175        }
176    }
177
178    fn storage_subscription(&self) -> OScript<Message> {
179        if (self.current_page == Page::Dashboard || self.current_page == Page::FileSystems)
180            && self.data.storages.is_none()
181        {
182            Some(
183                time::every(Duration::from_millis(START_UPERIOD))
184                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetStorageData)),
185            )
186        } else if self.current_page == Page::FileSystems {
187            Some(
188                time::every(Duration::from_secs(10))
189                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetStorageData)),
190            )
191        } else {
192            None
193        }
194    }
195
196    fn dmi_subscription(&self) -> OScript<Message> {
197        if self.current_page == Page::DMI && !self.data.is_polkit && self.data.dmi_data.is_none() {
198            Some(
199                time::every(Duration::from_millis(START_UPERIOD))
200                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetDMIData)),
201            )
202        } else {
203            None
204        }
205    }
206
207    fn battery_subscription(&self) -> OScript<Message> {
208        if self.current_page == Page::Dashboard || self.current_page == Page::Battery {
209            match self.data.bat_data {
210                LoadState::Loaded(_) => Some(
211                    time::every(Duration::from_secs(self.u()))
212                        .map(|_| Message::DataReceiver(DataReceiverMessage::GetBatInfo)),
213                ),
214                _ => Some(
215                    time::every(Duration::from_millis(START_UPERIOD))
216                        .map(|_| Message::DataReceiver(DataReceiverMessage::GetBatInfo)),
217                ),
218            }
219        } else {
220            None
221        }
222    }
223
224    fn drm_subscription(&self) -> OScript<Message> {
225        if self.current_page == Page::Screen && self.data.drm_data.is_none() {
226            Some(
227                time::every(Duration::from_millis(START_UPERIOD))
228                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetDRMData)),
229            )
230        } else if self.current_page == Page::Screen && self.data.drm_data.is_some() {
231            Some(
232                time::every(Duration::from_secs(self.u()))
233                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetDRMData)),
234            )
235        } else {
236            None
237        }
238    }
239
240    fn osrel_subscription(&self) -> OScript<Message> {
241        if (self.current_page == Page::Dashboard || self.current_page == Page::Distro)
242            && self.data.osrel_data.is_none()
243        {
244            Some(
245                time::every(Duration::from_millis(START_UPERIOD))
246                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetOsReleaseData)),
247            )
248        } else {
249            None
250        }
251    }
252
253    fn users_subscription(&self) -> OScript<Message> {
254        if self.current_page == Page::Users && self.data.users_list.is_none() {
255            Some(
256                time::every(Duration::from_millis(START_UPERIOD))
257                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetUsersData)),
258            )
259        } else {
260            None
261        }
262    }
263
264    fn groups_subscription(&self) -> OScript<Message> {
265        if self.current_page == Page::Groups && self.data.groups_list.is_none() {
266            Some(
267                time::every(Duration::from_millis(START_UPERIOD))
268                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetGroupsData)),
269            )
270        } else {
271            None
272        }
273    }
274
275    fn sysd_subscription(&self) -> OScript<Message> {
276        if self.current_page == Page::SystemManager && self.data.sysd_services_list.is_none() {
277            Some(
278                time::every(Duration::from_millis(START_UPERIOD))
279                    .map(|_| Message::DataReceiver(DataReceiverMessage::GetSystemdServices)),
280            )
281        } else if self.current_page == Page::SystemManager && self.data.sysd_services_list.is_some()
282        {
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.data.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.data.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.data.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.data.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}