gm-tui 0.0.1

TUI-based Ethereum wallet
Documentation
use crate::disk::DiskInterface;
use crossterm::event::{KeyCode, KeyEventKind};
use ratatui::buffer::Buffer;
use ratatui::layout::Rect;
use ratatui::prelude::Widget;
use std::fmt::Display;
use std::sync::atomic::AtomicBool;
use std::sync::{mpsc, Arc};

use crate::network::{Network, NetworkStore};
use crate::tui::app::pages::network_create::NetworkCreatePage;
use crate::tui::app::pages::Page;
use crate::tui::app::widgets::select::Select;
use crate::tui::app::SharedState;
use crate::tui::traits::{Component, HandleResult};
use crate::tui::Event;
use crate::utils::cursor::Cursor;

enum NetworkSelect {
    Create,
    Existing(Box<Network>),
}
impl Display for NetworkSelect {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            NetworkSelect::Create => write!(f, "Create new network"),
            NetworkSelect::Existing(name) => write!(f, "{name}"),
        }
    }
}
pub struct NetworkPage {
    cursor: Cursor,
    focus: bool,
    list: Vec<NetworkSelect>,
}
impl NetworkPage {
    pub fn new() -> crate::Result<Self> {
        let mut list = vec![NetworkSelect::Create];
        list.extend(
            NetworkStore::load()?
                .networks
                .into_iter()
                .map(|network| NetworkSelect::Existing(Box::new(network)))
                .collect::<Vec<_>>(),
        );
        Ok(Self {
            cursor: Cursor::default(),
            focus: true,
            list,
        })
    }
}
impl Component for NetworkPage {
    fn set_focus(&mut self, focus: bool) {
        self.focus = focus;
    }

    fn reload(&mut self, _ss: &SharedState) -> crate::Result<()> {
        let fresh = Self::new()?;
        self.list = fresh.list;
        Ok(())
    }

    fn handle_event(
        &mut self,
        event: &Event,
        _area: Rect,
        _transmitter: &mpsc::Sender<Event>,
        _shutdown_signal: &Arc<AtomicBool>,
        _shared_state: &SharedState,
    ) -> crate::Result<HandleResult> {
        let cursor_max = self.list.len();
        self.cursor.handle(event, cursor_max);

        let mut result = HandleResult::default();
        let network_store = NetworkStore::load()?;
        if let Event::Input(key_event) = event {
            if key_event.kind == KeyEventKind::Press {
                #[allow(clippy::single_match)]
                match key_event.code {
                    KeyCode::Enter => {
                        match &self.list[self.cursor.current] {
                            NetworkSelect::Create => {
                                let network_index = network_store.networks.len();
                                result.page_inserts.push(Page::NetworkCreate(
                                    NetworkCreatePage::new(network_index, Network::default())?,
                                ));
                                result.reload = true;
                            }

                            NetworkSelect::Existing(name) => {
                                let network_index = network_store
                                    .networks
                                    .iter()
                                    .position(|n| n.name == name.name)
                                    .unwrap();
                                result.page_inserts.push(Page::NetworkCreate(
                                    NetworkCreatePage::new(network_index, *name.clone())?,
                                ));
                                result.reload = true;
                            }
                        }
                    }
                    _ => {}
                }
            }
        };

        Ok(result)
    }

    fn render_component(&self, area: Rect, buf: &mut Buffer, shared_state: &SharedState) -> Rect
    where
        Self: Sized,
    {
        Select {
            list: &self.list,
            cursor: &self.cursor,
            focus: self.focus,
            focus_style: shared_state.theme.select(),
        }
        .render(area, buf);
        area
    }
}