nettui 0.2.0

Unified TUI for Wi-Fi and Ethernet
Documentation
use super::*;

impl App {
    pub async fn poll_background_tasks(&mut self) {
        let now = Instant::now();
        if self.wifi_scan_pending
            && self.wifi_scan_started_at.is_some_and(|started| {
                now.duration_since(started) > Duration::from_millis(self.config.job_timeout_scan_ms)
            })
        {
            if let Some(handle) = self.wifi_scan_task.take() {
                handle.abort();
            }
            self.wifi_scan_pending = false;
            self.wifi_scan_started_at = None;
            self.set_toast(ToastKind::Error, "Wi-Fi scan timed out");
        }

        if self.wifi_connect_pending
            && self.wifi_connect_started_at.is_some_and(|started| {
                now.duration_since(started)
                    > Duration::from_millis(self.config.job_timeout_connect_ms)
            })
        {
            if let Some(handle) = self.wifi_connect_task.take() {
                handle.abort();
            }
            self.wifi_connect_pending = false;
            self.wifi_connect_started_at = None;
            self.wifi_connect_context = None;
            if !self.has_recent_toast_message("Couldn't talk to iwd.") {
                self.set_toast(ToastKind::Error, "Wi-Fi connect/disconnect timed out");
            }
        }

        if self.wifi_ap_pending
            && self.wifi_ap_started_at.is_some_and(|started| {
                now.duration_since(started)
                    > Duration::from_millis(self.config.job_timeout_connect_ms)
            })
        {
            if let Some(handle) = self.wifi_ap_task.take() {
                handle.abort();
            }
            self.wifi_ap_pending = false;
            self.wifi_ap_started_at = None;
            self.wifi_ap_context = None;
            self.set_toast(ToastKind::Error, "Access point change timed out");
        }

        if let Some(handle) = self.wifi_scan_task.take() {
            if handle.is_finished() {
                self.wifi_scan_pending = false;
                self.wifi_scan_started_at = None;
                match handle.await {
                    Ok(Ok(())) => {
                        self.last_action = Some("Wi-Fi scan completed".to_string());
                        self.set_toast(ToastKind::Success, "Wi-Fi scan completed");
                        self.notify("Wi-Fi", "Scan completed");
                        self.request_refresh();
                    }
                    Ok(Err(e)) => {
                        let msg = friendly_wifi_error("scan", &e);
                        self.set_toast(ToastKind::Error, msg);
                    }
                    Err(e) => {
                        let msg = format!("Scan task failed: {e}");
                        self.set_toast(ToastKind::Error, msg);
                    }
                }
            } else {
                self.wifi_scan_task = Some(handle);
            }
        }

        if let Some(handle) = self.wifi_connect_task.take() {
            if handle.is_finished() {
                self.wifi_connect_pending = false;
                self.wifi_connect_started_at = None;
                let ctx = self.wifi_connect_context.take();
                match handle.await {
                    Ok(Ok(())) => {
                        if let Some(ctx) = ctx {
                            if ctx.disconnect {
                                self.last_action = Some("Disconnected Wi-Fi".to_string());
                                self.set_toast(
                                    ToastKind::Success,
                                    format!("Disconnected from {}", ctx.ssid),
                                );
                                self.notify("Wi-Fi", &format!("Disconnected from {}", ctx.ssid));
                            } else {
                                self.last_action = Some(format!("Connected to {}", ctx.ssid));
                                self.set_toast(
                                    ToastKind::Success,
                                    format!("Connected to {}", ctx.ssid),
                                );
                                self.notify("Wi-Fi", &format!("Connected to {}", ctx.ssid));
                            }
                            self.request_refresh();
                        }
                    }
                    Ok(Err(e)) => {
                        let no_agent = is_no_agent_error(&e);
                        if let Some(ctx) = ctx
                            && no_agent
                            && !ctx.disconnect
                            && !ctx.used_passphrase
                        {
                            self.open_wifi_passphrase_prompt(ctx.ssid.clone());
                            self.set_toast(
                                ToastKind::Info,
                                format!("Passphrase required for {}", ctx.ssid),
                            );
                        } else {
                            let msg = friendly_wifi_error("connect/disconnect", &e);
                            self.set_toast(ToastKind::Error, msg);
                        }
                    }
                    Err(e) => {
                        let msg = format!("Connect task failed: {e}");
                        self.set_toast(ToastKind::Error, msg);
                    }
                }
            } else {
                self.wifi_connect_task = Some(handle);
            }
        }

        if let Some(handle) = self.wifi_ap_task.take() {
            if handle.is_finished() {
                self.wifi_ap_pending = false;
                self.wifi_ap_started_at = None;
                let ctx = self.wifi_ap_context.take();
                match handle.await {
                    Ok(Ok(())) => {
                        if let Some(ctx) = ctx {
                            if ctx.stopping {
                                self.last_action = Some("Stopped Wi-Fi access point".to_string());
                                self.set_toast(ToastKind::Success, "Access point stopped");
                                self.notify("Wi-Fi", "Access point stopped");
                            } else {
                                let ssid = ctx.ssid.unwrap_or_else(|| "hotspot".to_string());
                                self.last_action = Some(format!("Started access point {ssid}"));
                                self.set_toast(
                                    ToastKind::Success,
                                    format!("Access point {ssid} started"),
                                );
                                if !self.wifi_backend.network_configuration_enabled() {
                                    self.set_toast(
                                        ToastKind::Info,
                                        "iwd network configuration is disabled. AP clients may not get DHCP until /etc/iwd/main.conf enables [General] EnableNetworkConfiguration=true.",
                                    );
                                }
                                self.notify("Wi-Fi", &format!("Access point {ssid} started"));
                            }
                            self.request_refresh();
                        }
                    }
                    Ok(Err(e)) => {
                        let msg = friendly_wifi_error("change access point mode", &e);
                        self.set_toast(ToastKind::Error, msg);
                    }
                    Err(e) => {
                        self.set_toast(ToastKind::Error, format!("AP task failed: {e}"));
                    }
                }
            } else {
                self.wifi_ap_task = Some(handle);
            }
        }
    }
}