impala 0.7.3

TUI for managing wifi
Documentation
use crate::agent::AuthAgent;
use anyhow::Result;

use ratatui::{
    Frame,
    layout::{Constraint, Direction, Layout, Margin},
    style::{Color, Style, Stylize},
    text::{Line, Span, Text},
    widgets::{Block, BorderType, Borders, Clear, List},
};
use tui_input::Input;

#[derive(Debug)]
pub struct RequestPassword {
    pub password: Input,
    pub show_password: bool,
    network_name: String,
    user_name: Option<String>,
}

impl RequestPassword {
    pub fn new(network_name: String, user_name: Option<String>) -> Self {
        Self {
            password: Input::default(),
            show_password: true,
            network_name,
            user_name,
        }
    }
    pub async fn submit(&mut self, agent: &AuthAgent) -> Result<()> {
        let passkey: String = self.password.value().into();
        agent.tx_passphrase.send(passkey).await?;
        agent
            .password_required
            .store(false, std::sync::atomic::Ordering::Relaxed);
        self.password.reset();
        Ok(())
    }

    pub async fn cancel(&mut self, agent: &AuthAgent) -> Result<()> {
        agent.tx_cancel.send(()).await?;
        agent
            .password_required
            .store(false, std::sync::atomic::Ordering::Relaxed);
        self.password.reset();
        Ok(())
    }
    pub fn render(&self, frame: &mut Frame) {
        let popup_layout = Layout::default()
            .direction(Direction::Vertical)
            .constraints([
                Constraint::Fill(1),
                Constraint::Length(12),
                Constraint::Fill(1),
            ])
            .flex(ratatui::layout::Flex::SpaceBetween)
            .split(frame.area());

        let area = Layout::default()
            .direction(Direction::Horizontal)
            .constraints([
                Constraint::Fill(1),
                Constraint::Length(80),
                Constraint::Fill(1),
            ])
            .flex(ratatui::layout::Flex::SpaceBetween)
            .split(popup_layout[1])[1];

        let (title_area, form_area, show_password_area) = {
            let chunks = Layout::default()
                .direction(Direction::Vertical)
                .constraints([Constraint::Length(5), Constraint::Length(5)])
                .split(area);

            let area2 = Layout::default()
                .direction(Direction::Horizontal)
                .constraints([
                    Constraint::Percentage(20),
                    Constraint::Fill(1),
                    Constraint::Length(5),
                    Constraint::Percentage(20),
                ])
                .flex(ratatui::layout::Flex::Center)
                .split(chunks[1]);

            (chunks[0], area2[1], area2[2])
        };

        let title = Line::from(vec![
            Span::raw("Authentication Required for "),
            Span::from(&self.network_name).bold(),
        ])
        .centered();

        let items = vec![
            {
                if let Some(user_name) = &self.user_name {
                    Line::from(vec![
                        Span::raw(" Username ").bold().bg(Color::DarkGray),
                        Span::from("  "),
                        Span::from(user_name),
                    ])
                } else {
                    Line::from("")
                }
            },
            Line::from(""),
            Line::from(vec![
                Span::raw(" Password ").bold().bg(Color::DarkGray),
                Span::from("  "),
                Span::from({
                    if self.show_password {
                        self.password.value().to_string()
                    } else {
                        "*".repeat(self.password.value().len())
                    }
                }),
            ]),
        ];

        let form = List::new(items);

        let show_password_icon = if self.show_password {
            Text::from("\n\n").centered()
        } else {
            Text::from("\n\n").centered()
        };

        frame.render_widget(Clear, area);

        frame.render_widget(
            Block::new()
                .borders(Borders::ALL)
                .border_type(BorderType::Thick)
                .border_style(Style::default().fg(Color::Green)),
            area,
        );
        frame.render_widget(
            title,
            title_area.inner(Margin {
                horizontal: 1,
                vertical: 2,
            }),
        );
        frame.render_widget(
            form,
            form_area.inner(Margin {
                horizontal: 1,
                vertical: 1,
            }),
        );
        frame.render_widget(
            show_password_icon,
            show_password_area.inner(Margin {
                horizontal: 1,
                vertical: 1,
            }),
        );
    }
}