list of nominators targets ported to wallet tab
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
This commit is contained in:
		
							parent
							
								
									edd1b6d616
								
							
						
					
					
						commit
						756a1089f6
					
				@ -2,7 +2,7 @@
 | 
			
		||||
name = "ghost-eye"
 | 
			
		||||
authors = ["str3tch <stretch@ghostchain.io>"]
 | 
			
		||||
description = "Application for interacting with Casper/Ghost nodes that are exposing RPC only to the localhost"
 | 
			
		||||
version = "0.3.49"
 | 
			
		||||
version = "0.3.50"
 | 
			
		||||
edition = "2021"
 | 
			
		||||
homepage = "https://git.ghostchain.io/ghostchain"
 | 
			
		||||
repository = "https://git.ghostchain.io/ghostchain/ghost-eye"
 | 
			
		||||
 | 
			
		||||
@ -41,17 +41,6 @@
 | 
			
		||||
            "popup_style": "blue",
 | 
			
		||||
            "popup_title_style": "blue",
 | 
			
		||||
        },
 | 
			
		||||
        "Nominator": {
 | 
			
		||||
            "normal_style": "",
 | 
			
		||||
            "hover_style": "bold yellow italic on blue",
 | 
			
		||||
            "normal_border_style": "blue",
 | 
			
		||||
            "hover_border_style": "blue",
 | 
			
		||||
            "normal_title_style": "blue",
 | 
			
		||||
            "hover_title_style": "",
 | 
			
		||||
            "highlight_style": "yellow bold",
 | 
			
		||||
            "popup_style": "blue",
 | 
			
		||||
            "popup_title_style": "blue",
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    "keybindings": {
 | 
			
		||||
        "Menu": {
 | 
			
		||||
@ -77,12 +66,6 @@
 | 
			
		||||
            "<Ctrl-c>": "Quit",
 | 
			
		||||
            "<Ctrl-z>": "Suspend",
 | 
			
		||||
        },
 | 
			
		||||
        "Nominator": {
 | 
			
		||||
            "<q>": "Quit",
 | 
			
		||||
            "<Ctrl-d>": "Quit",
 | 
			
		||||
            "<Ctrl-c>": "Quit",
 | 
			
		||||
            "<Ctrl-z>": "Suspend",
 | 
			
		||||
        },
 | 
			
		||||
        "Empty": {
 | 
			
		||||
            "<q>": "Quit",
 | 
			
		||||
            "<Ctrl-d>": "Quit",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										13
									
								
								src/app.rs
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/app.rs
									
									
									
									
									
								
							@ -12,7 +12,7 @@ use crate::{
 | 
			
		||||
    tui::{Event, Tui},
 | 
			
		||||
    components::{
 | 
			
		||||
        menu::Menu, version::Version, explorer::Explorer, wallet::Wallet, 
 | 
			
		||||
        validator::Validator, nominator::Nominator, empty::Empty,
 | 
			
		||||
        validator::Validator, empty::Empty,
 | 
			
		||||
        health::Health, fps::FpsCounter, 
 | 
			
		||||
        Component,
 | 
			
		||||
    },
 | 
			
		||||
@ -24,7 +24,6 @@ pub enum Mode {
 | 
			
		||||
    Explorer,
 | 
			
		||||
    Wallet,
 | 
			
		||||
    Validator,
 | 
			
		||||
    Nominator,
 | 
			
		||||
    Empty,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -73,7 +72,6 @@ impl App {
 | 
			
		||||
                Box::new(Explorer::default()),
 | 
			
		||||
                Box::new(Wallet::default()),
 | 
			
		||||
                Box::new(Validator::default()),
 | 
			
		||||
                Box::new(Nominator::default()),
 | 
			
		||||
                Box::new(Empty::default()),
 | 
			
		||||
            ],
 | 
			
		||||
            should_quite: false,
 | 
			
		||||
@ -268,15 +266,6 @@ impl App {
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                Mode::Nominator => {
 | 
			
		||||
                    if let Some(component) = self.components.get_mut(7) {
 | 
			
		||||
                        if let Err(err) = component.draw(frame, frame.area()) {
 | 
			
		||||
                            let _ = self
 | 
			
		||||
                                .action_tx
 | 
			
		||||
                                .send(Action::Error(format!("failed to draw: {:?}", err)));
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                _ => {
 | 
			
		||||
                    if let Some(component) = self.components.last_mut() {
 | 
			
		||||
                        if let Err(err) = component.draw(frame, frame.area()) {
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,6 @@ impl Menu {
 | 
			
		||||
                String::from("Explorer"),
 | 
			
		||||
                String::from("Wallet"),
 | 
			
		||||
                String::from("Validator"),
 | 
			
		||||
                String::from("Nominator"),
 | 
			
		||||
                String::from("Prices"),
 | 
			
		||||
                String::from("Governance"),
 | 
			
		||||
                String::from("Operations"),
 | 
			
		||||
@ -59,7 +58,6 @@ impl Menu {
 | 
			
		||||
            0 => Ok(Some(Action::SetMode(Mode::Explorer))),
 | 
			
		||||
            1 => Ok(Some(Action::SetMode(Mode::Wallet))),
 | 
			
		||||
            2 => Ok(Some(Action::SetMode(Mode::Validator))),
 | 
			
		||||
            3 => Ok(Some(Action::SetMode(Mode::Nominator))),
 | 
			
		||||
            _ => Ok(Some(Action::SetMode(Mode::Empty))),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -80,7 +78,6 @@ impl Menu {
 | 
			
		||||
            0 => Ok(Some(Action::SetMode(Mode::Explorer))),
 | 
			
		||||
            1 => Ok(Some(Action::SetMode(Mode::Wallet))),
 | 
			
		||||
            2 => Ok(Some(Action::SetMode(Mode::Validator))),
 | 
			
		||||
            3 => Ok(Some(Action::SetMode(Mode::Nominator))),
 | 
			
		||||
            _ => Ok(Some(Action::SetMode(Mode::Empty))),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -121,7 +118,6 @@ impl Component for Menu {
 | 
			
		||||
                    Some(0) => Ok(Some(Action::SetActiveScreen(Mode::Explorer))),
 | 
			
		||||
                    Some(1) => Ok(Some(Action::SetActiveScreen(Mode::Wallet))),
 | 
			
		||||
                    Some(2) => Ok(Some(Action::SetActiveScreen(Mode::Validator))),
 | 
			
		||||
                    Some(3) => Ok(Some(Action::SetActiveScreen(Mode::Nominator))),
 | 
			
		||||
                    _ => Ok(Some(Action::SetActiveScreen(Mode::Empty))),
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
 | 
			
		||||
@ -16,7 +16,6 @@ pub mod version;
 | 
			
		||||
pub mod explorer;
 | 
			
		||||
pub mod wallet;
 | 
			
		||||
pub mod validator;
 | 
			
		||||
pub mod nominator;
 | 
			
		||||
pub mod empty;
 | 
			
		||||
 | 
			
		||||
pub trait Component {
 | 
			
		||||
 | 
			
		||||
@ -1,217 +0,0 @@
 | 
			
		||||
use color_eyre::Result;
 | 
			
		||||
use crossterm::event::{KeyCode, KeyEvent};
 | 
			
		||||
use ratatui::{
 | 
			
		||||
    layout::{Alignment, Constraint, Margin, Rect}, 
 | 
			
		||||
    style::{Color, Style}, 
 | 
			
		||||
    text::Text, 
 | 
			
		||||
    widgets::{
 | 
			
		||||
        Block, Padding, Cell, Row, Scrollbar, ScrollbarOrientation, 
 | 
			
		||||
        ScrollbarState, Table, TableState,
 | 
			
		||||
    }, 
 | 
			
		||||
    Frame
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use super::{Component, PartialComponent, CurrentTab};
 | 
			
		||||
use crate::{
 | 
			
		||||
    types::ActionLevel,
 | 
			
		||||
    action::Action, 
 | 
			
		||||
    config::Config, 
 | 
			
		||||
    palette::StylePalette, 
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Default)]
 | 
			
		||||
struct LogDetails {
 | 
			
		||||
    time: chrono::DateTime<chrono::Local>,
 | 
			
		||||
    level: ActionLevel,
 | 
			
		||||
    message: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct EventLogs {
 | 
			
		||||
    is_active: bool,
 | 
			
		||||
    scroll_state: ScrollbarState,
 | 
			
		||||
    table_state: TableState,
 | 
			
		||||
    logs: std::collections::VecDeque<LogDetails>,
 | 
			
		||||
    palette: StylePalette
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: remove later
 | 
			
		||||
impl Default for EventLogs {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        EventLogs {
 | 
			
		||||
            is_active: false,
 | 
			
		||||
            scroll_state: Default::default(),
 | 
			
		||||
            table_state: Default::default(),
 | 
			
		||||
            logs: std::collections::VecDeque::from(vec![
 | 
			
		||||
                LogDetails {
 | 
			
		||||
                    time: chrono::Local::now(),
 | 
			
		||||
                    level: ActionLevel::Warn,
 | 
			
		||||
                    message: "NOT FINALIZED PAGE! NEEDED IN ORDER TO SEE VALIDATORS POINTS".to_string(),
 | 
			
		||||
                },
 | 
			
		||||
            ]),
 | 
			
		||||
            palette: Default::default(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl EventLogs {
 | 
			
		||||
    //const MAX_LOGS: usize = 50;
 | 
			
		||||
 | 
			
		||||
    //fn add_new_log(&mut self, message: String, level: ActionLevel) {
 | 
			
		||||
    //    self.logs.push_front(LogDetails {
 | 
			
		||||
    //        time: chrono::Local::now(),
 | 
			
		||||
    //        level,
 | 
			
		||||
    //        message,
 | 
			
		||||
    //    });
 | 
			
		||||
 | 
			
		||||
    //    if self.logs.len() > Self::MAX_LOGS {
 | 
			
		||||
    //        let _ = self.logs.pop_back();
 | 
			
		||||
    //    }
 | 
			
		||||
    //}
 | 
			
		||||
 | 
			
		||||
    fn first_row(&mut self) {
 | 
			
		||||
        if self.logs.len() > 0 {
 | 
			
		||||
            self.table_state.select(Some(0));
 | 
			
		||||
            self.scroll_state = self.scroll_state.position(0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn next_row(&mut self) {
 | 
			
		||||
        let i = match self.table_state.selected() {
 | 
			
		||||
            Some(i) => {
 | 
			
		||||
                if i >= self.logs.len() - 1 {
 | 
			
		||||
                    i
 | 
			
		||||
                } else {
 | 
			
		||||
                    i + 1
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            None => 0,
 | 
			
		||||
        };
 | 
			
		||||
        self.table_state.select(Some(i));
 | 
			
		||||
        self.scroll_state = self.scroll_state.position(i);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn last_row(&mut self) {
 | 
			
		||||
        if self.logs.len() > 0 {
 | 
			
		||||
            let last = self.logs.len() - 1;
 | 
			
		||||
            self.table_state.select(Some(last));
 | 
			
		||||
            self.scroll_state = self.scroll_state.position(last);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn previous_row(&mut self) {
 | 
			
		||||
        let i = match self.table_state.selected() {
 | 
			
		||||
            Some(i) => {
 | 
			
		||||
                if i == 0 {
 | 
			
		||||
                    0
 | 
			
		||||
                } else {
 | 
			
		||||
                    i - 1
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            None => 0
 | 
			
		||||
        };
 | 
			
		||||
        self.table_state.select(Some(i));
 | 
			
		||||
        self.scroll_state = self.scroll_state.position(i);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl PartialComponent for EventLogs {
 | 
			
		||||
    fn set_active(&mut self, current_tab: CurrentTab) {
 | 
			
		||||
        match current_tab {
 | 
			
		||||
            CurrentTab::EventLogs => self.is_active = true,
 | 
			
		||||
            _ => {
 | 
			
		||||
                self.is_active = false;
 | 
			
		||||
                self.table_state.select(None);
 | 
			
		||||
                self.scroll_state = self.scroll_state.position(0);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Component for EventLogs {
 | 
			
		||||
    fn register_config_handler(&mut self, config: Config) -> Result<()> {
 | 
			
		||||
        if let Some(style) = config.styles.get(&crate::app::Mode::Nominator) {
 | 
			
		||||
            self.palette.with_normal_style(style.get("normal_style").copied());
 | 
			
		||||
            self.palette.with_hover_style(style.get("hover_style").copied());
 | 
			
		||||
            self.palette.with_normal_border_style(style.get("normal_border_style").copied());
 | 
			
		||||
            self.palette.with_hover_border_style(style.get("hover_border_style").copied());
 | 
			
		||||
            self.palette.with_normal_title_style(style.get("normal_title_style").copied());
 | 
			
		||||
            self.palette.with_hover_title_style(style.get("hover_title_style").copied());
 | 
			
		||||
            self.palette.with_highlight_style(style.get("highlight_style").copied());
 | 
			
		||||
            self.palette.with_scrollbar_style(style.get("scrollbar_style").copied());
 | 
			
		||||
        }
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn handle_key_event(&mut self, key: KeyEvent) -> Result<Option<Action>> {
 | 
			
		||||
        match key.code {
 | 
			
		||||
           KeyCode::Up | KeyCode::Char('k') if self.is_active => self.previous_row(), 
 | 
			
		||||
           KeyCode::Down | KeyCode::Char('j') if self.is_active => self.next_row(), 
 | 
			
		||||
           KeyCode::Char('g') if self.is_active => self.first_row(),
 | 
			
		||||
           KeyCode::Char('G') if self.is_active => self.last_row(),
 | 
			
		||||
           _ => {},
 | 
			
		||||
        };
 | 
			
		||||
        Ok(None)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn update(&mut self, _action: Action) -> Result<Option<Action>> {
 | 
			
		||||
        //match action {
 | 
			
		||||
        //    Action::EventLog(message, level, target) if target == ActionTarget::NominatorLog => 
 | 
			
		||||
        //    self.add_new_log(message, level),
 | 
			
		||||
        //    _ => {}
 | 
			
		||||
        //};
 | 
			
		||||
        Ok(None)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> {
 | 
			
		||||
        let [_, _, place] = super::nominator_layout(area);
 | 
			
		||||
 | 
			
		||||
        let (border_style, border_type) = self.palette.create_border_style(self.is_active);
 | 
			
		||||
        let error_style = Style::new().fg(Color::Red);
 | 
			
		||||
        let warn_style = Style::new().fg(Color::Yellow);
 | 
			
		||||
        let info_style = Style::new().fg(Color::Green);
 | 
			
		||||
 | 
			
		||||
        let table = Table::new(
 | 
			
		||||
            self.logs
 | 
			
		||||
                .iter()
 | 
			
		||||
                .map(|log| {
 | 
			
		||||
                    let style = match log.level {
 | 
			
		||||
                        ActionLevel::Info => info_style,
 | 
			
		||||
                        ActionLevel::Warn => warn_style,
 | 
			
		||||
                        ActionLevel::Error => error_style,
 | 
			
		||||
                    };
 | 
			
		||||
                    Row::new(vec![
 | 
			
		||||
                        Cell::from(Text::from(log.time.format("%H:%M:%S").to_string()).style(style).alignment(Alignment::Left)),
 | 
			
		||||
                        Cell::from(Text::from(log.message.clone()).style(style).alignment(Alignment::Left)),
 | 
			
		||||
                    ])
 | 
			
		||||
                }),
 | 
			
		||||
            [
 | 
			
		||||
                Constraint::Max(8),
 | 
			
		||||
                Constraint::Min(0),
 | 
			
		||||
            ],
 | 
			
		||||
        )
 | 
			
		||||
        .column_spacing(1)
 | 
			
		||||
        .highlight_style(self.palette.create_highlight_style())
 | 
			
		||||
        .block(Block::bordered()
 | 
			
		||||
            .border_style(border_style)
 | 
			
		||||
            .border_type(border_type)
 | 
			
		||||
            .padding(Padding::right(2))
 | 
			
		||||
            .title_alignment(Alignment::Right)
 | 
			
		||||
            .title_style(self.palette.create_title_style(false))
 | 
			
		||||
            .title("Action Logs"));
 | 
			
		||||
 | 
			
		||||
        let scrollbar = Scrollbar::default()
 | 
			
		||||
            .orientation(ScrollbarOrientation::VerticalRight)
 | 
			
		||||
            .begin_symbol(None)
 | 
			
		||||
            .end_symbol(None)
 | 
			
		||||
            .style(self.palette.create_scrollbar_style());
 | 
			
		||||
 | 
			
		||||
        frame.render_stateful_widget(table, place, &mut self.table_state);
 | 
			
		||||
        frame.render_stateful_widget(
 | 
			
		||||
            scrollbar,
 | 
			
		||||
            place.inner(Margin { vertical: 1, horizontal: 1 }),
 | 
			
		||||
            &mut self.scroll_state,
 | 
			
		||||
        );
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,185 +0,0 @@
 | 
			
		||||
use color_eyre::Result;
 | 
			
		||||
use crossterm::event::{KeyCode, KeyEvent};
 | 
			
		||||
use ratatui::{
 | 
			
		||||
    layout::{Constraint, Layout, Rect},
 | 
			
		||||
    Frame,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use std::sync::mpsc::Sender;
 | 
			
		||||
use tokio::sync::mpsc::UnboundedSender;
 | 
			
		||||
 | 
			
		||||
use super::Component;
 | 
			
		||||
use crate::{action::Action, app::Mode, config::Config};
 | 
			
		||||
 | 
			
		||||
mod event_log;
 | 
			
		||||
mod current_validators;
 | 
			
		||||
mod rename_known_validator;
 | 
			
		||||
mod current_validator_details;
 | 
			
		||||
 | 
			
		||||
use event_log::EventLogs;
 | 
			
		||||
use current_validators::CurrentValidators;
 | 
			
		||||
use current_validator_details::CurrentValidatorDetails;
 | 
			
		||||
use rename_known_validator::RenameKnownValidator;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
pub enum CurrentTab {
 | 
			
		||||
    Nothing,
 | 
			
		||||
    CurrentValidators,
 | 
			
		||||
    EventLogs,
 | 
			
		||||
    RenameKnownValidator,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub trait PartialComponent: Component {
 | 
			
		||||
    fn set_active(&mut self, current_tab: CurrentTab);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Nominator {
 | 
			
		||||
    is_active: bool,
 | 
			
		||||
    current_tab: CurrentTab,
 | 
			
		||||
    components: Vec<Box<dyn PartialComponent>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for Nominator {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            is_active: false,
 | 
			
		||||
            current_tab: CurrentTab::Nothing,
 | 
			
		||||
            components: vec![
 | 
			
		||||
                Box::new(CurrentValidators::default()),
 | 
			
		||||
                Box::new(CurrentValidatorDetails::default()),
 | 
			
		||||
                Box::new(EventLogs::default()),
 | 
			
		||||
                Box::new(RenameKnownValidator::default()),
 | 
			
		||||
            ],
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Nominator {
 | 
			
		||||
    fn move_left(&mut self) {
 | 
			
		||||
        match self.current_tab {
 | 
			
		||||
            CurrentTab::EventLogs => self.current_tab = CurrentTab::CurrentValidators,
 | 
			
		||||
            _ => {}
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn move_right(&mut self) {
 | 
			
		||||
        match self.current_tab {
 | 
			
		||||
            CurrentTab::CurrentValidators => self.current_tab = CurrentTab::EventLogs,
 | 
			
		||||
            _ => {}
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Component for Nominator {
 | 
			
		||||
    fn register_network_handler(&mut self, tx: Sender<Action>) -> Result<()> {
 | 
			
		||||
        for component in self.components.iter_mut() {
 | 
			
		||||
            component.register_network_handler(tx.clone())?;
 | 
			
		||||
        }
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn register_action_handler(&mut self, tx: UnboundedSender<Action>) -> Result<()> {
 | 
			
		||||
        for component in self.components.iter_mut() {
 | 
			
		||||
            component.register_action_handler(tx.clone())?;
 | 
			
		||||
        }
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn register_config_handler(&mut self, config: Config) -> Result<()> {
 | 
			
		||||
        for component in self.components.iter_mut() {
 | 
			
		||||
            component.register_config_handler(config.clone())?;
 | 
			
		||||
        }
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn handle_key_event(&mut self, key: KeyEvent) -> Result<Option<Action>> {
 | 
			
		||||
        if !self.is_active { return Ok(None) }
 | 
			
		||||
 | 
			
		||||
        match self.current_tab {
 | 
			
		||||
            CurrentTab::RenameKnownValidator => match key.code {
 | 
			
		||||
                KeyCode::Esc => {
 | 
			
		||||
                    self.current_tab = CurrentTab::CurrentValidators;
 | 
			
		||||
                    for component in self.components.iter_mut() {
 | 
			
		||||
                        component.set_active(self.current_tab.clone());
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                _ => {
 | 
			
		||||
                    for component in self.components.iter_mut() {
 | 
			
		||||
                        component.handle_key_event(key)?;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            _ => match key.code {
 | 
			
		||||
                KeyCode::Esc => {
 | 
			
		||||
                    self.is_active = false;
 | 
			
		||||
                    self.current_tab = CurrentTab::Nothing;
 | 
			
		||||
                    for component in self.components.iter_mut() {
 | 
			
		||||
                        component.set_active(self.current_tab.clone());
 | 
			
		||||
                    }
 | 
			
		||||
                    return Ok(Some(Action::SetActiveScreen(Mode::Menu)));
 | 
			
		||||
                },
 | 
			
		||||
                KeyCode::Char('l') | KeyCode::Right => {
 | 
			
		||||
                    self.move_right();
 | 
			
		||||
                    for component in self.components.iter_mut() {
 | 
			
		||||
                        component.set_active(self.current_tab.clone());
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                KeyCode::Char('h') | KeyCode::Left => {
 | 
			
		||||
                    self.move_left();
 | 
			
		||||
                    for component in self.components.iter_mut() {
 | 
			
		||||
                        component.set_active(self.current_tab.clone());
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                _ => {
 | 
			
		||||
                    for component in self.components.iter_mut() {
 | 
			
		||||
                        component.handle_key_event(key)?;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        Ok(None)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn update(&mut self, action: Action) -> Result<Option<Action>> {
 | 
			
		||||
        match action {
 | 
			
		||||
            Action::RenameKnownValidatorRecord => 
 | 
			
		||||
                self.current_tab = CurrentTab::RenameKnownValidator,
 | 
			
		||||
            Action::UpdateKnownValidator(_) =>
 | 
			
		||||
                self.current_tab = CurrentTab::CurrentValidators,
 | 
			
		||||
            Action::SetActiveScreen(Mode::Nominator) => {
 | 
			
		||||
                self.is_active = true;
 | 
			
		||||
                self.current_tab = CurrentTab::CurrentValidators;
 | 
			
		||||
            },
 | 
			
		||||
            _ => {},
 | 
			
		||||
        }
 | 
			
		||||
        for component in self.components.iter_mut() {
 | 
			
		||||
            component.set_active(self.current_tab.clone());
 | 
			
		||||
            component.update(action.clone())?;
 | 
			
		||||
        }
 | 
			
		||||
        Ok(None)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> {
 | 
			
		||||
        let screen = super::screen_layout(area);
 | 
			
		||||
        for component in self.components.iter_mut() {
 | 
			
		||||
            component.draw(frame, screen)?;
 | 
			
		||||
        }
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn nominator_layout(area: Rect) -> [Rect; 3] {
 | 
			
		||||
    Layout::vertical([
 | 
			
		||||
        Constraint::Percentage(25),
 | 
			
		||||
        Constraint::Percentage(50),
 | 
			
		||||
        Constraint::Percentage(25),
 | 
			
		||||
    ]).areas(area)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn validator_details_layout(area: Rect) -> [Rect; 2] {
 | 
			
		||||
    let [place, _, _] = nominator_layout(area);
 | 
			
		||||
    Layout::horizontal([
 | 
			
		||||
        Constraint::Percentage(60),
 | 
			
		||||
        Constraint::Percentage(40),
 | 
			
		||||
    ]).areas(place)
 | 
			
		||||
}
 | 
			
		||||
@ -113,7 +113,12 @@ impl CurrentValidatorDetails {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl PartialComponent for CurrentValidatorDetails {
 | 
			
		||||
    fn set_active(&mut self, _current_tab: CurrentTab) {}
 | 
			
		||||
    fn set_active(&mut self, current_tab: CurrentTab) {
 | 
			
		||||
        match current_tab {
 | 
			
		||||
            CurrentTab::CurrentValidatorsPopup => self.is_active = true,
 | 
			
		||||
            _ => self.is_active = false,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Component for CurrentValidatorDetails {
 | 
			
		||||
@ -123,7 +128,7 @@ impl Component for CurrentValidatorDetails {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn register_config_handler(&mut self, config: Config) -> Result<()> {
 | 
			
		||||
        if let Some(style) = config.styles.get(&crate::app::Mode::Nominator) {
 | 
			
		||||
        if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) {
 | 
			
		||||
            self.palette.with_normal_style(style.get("normal_style").copied());
 | 
			
		||||
            self.palette.with_hover_style(style.get("hover_style").copied());
 | 
			
		||||
            self.palette.with_normal_border_style(style.get("normal_border_style").copied());
 | 
			
		||||
@ -154,63 +159,65 @@ impl Component for CurrentValidatorDetails {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> {
 | 
			
		||||
        let [_, place] = super::validator_details_layout(area);
 | 
			
		||||
        let (border_style, border_type) = self.palette.create_border_style(self.is_active);
 | 
			
		||||
        if self.is_active {
 | 
			
		||||
            let (border_style, border_type) = self.palette.create_border_style(self.is_active);
 | 
			
		||||
            let [_, place] = super::nominator_layout(area);
 | 
			
		||||
            let table = Table::new(
 | 
			
		||||
                vec![
 | 
			
		||||
                    Row::new(vec![
 | 
			
		||||
                        Cell::from(Text::from("Forbidden".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                        Cell::from(Text::from(self.is_nomination_disabled.to_string()).alignment(Alignment::Right)), 
 | 
			
		||||
                    ]),
 | 
			
		||||
                    Row::new(vec![
 | 
			
		||||
                        Cell::from(Text::from("Nominators".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                        Cell::from(Text::from(self.others_len.to_string()).alignment(Alignment::Right)), 
 | 
			
		||||
                    ]),
 | 
			
		||||
                    Row::new(vec![
 | 
			
		||||
                        Cell::from(Text::from("Total staked".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                        Cell::from(Text::from(self.prepare_u128(self.total_balance)).alignment(Alignment::Right)), 
 | 
			
		||||
                    ]),
 | 
			
		||||
                    Row::new(vec![
 | 
			
		||||
                        Cell::from(Text::from("Own stake".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                        Cell::from(Text::from(self.prepare_u128(self.own_balance)).alignment(Alignment::Right)), 
 | 
			
		||||
                    ]),
 | 
			
		||||
                    Row::new(vec![
 | 
			
		||||
                        Cell::from(Text::from("Imbalance".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                        Cell::from(Text::from(self.prepare_stake_imbalance()).alignment(Alignment::Right)), 
 | 
			
		||||
                    ]),
 | 
			
		||||
                    Row::new(vec![
 | 
			
		||||
                        Cell::from(Text::from("Commission".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                        Cell::from(Text::from(format!("{:.4}%", self.commission)).alignment(Alignment::Right)), 
 | 
			
		||||
                    ]),
 | 
			
		||||
                    Row::new(vec![
 | 
			
		||||
                        Cell::from(Text::from("Points ratio".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                        Cell::from(Text::from(format!("{:.4}%", self.points_ratio)).alignment(Alignment::Right)), 
 | 
			
		||||
                    ]),
 | 
			
		||||
                    Row::new(vec![
 | 
			
		||||
                        Cell::from(Text::from("In next era".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                        Cell::from(Text::from(self.prepare_state_string()).alignment(Alignment::Right)), 
 | 
			
		||||
                    ]),
 | 
			
		||||
                    Row::new(vec![
 | 
			
		||||
                        Cell::from(Text::from("Last payout".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                        Cell::from(Text::from(format!("{} days ago", self.latest_era_claim)).alignment(Alignment::Right)), 
 | 
			
		||||
                    ]),
 | 
			
		||||
                ],
 | 
			
		||||
                [
 | 
			
		||||
                    Constraint::Max(12),
 | 
			
		||||
                    Constraint::Min(0),
 | 
			
		||||
                ],
 | 
			
		||||
            )
 | 
			
		||||
            .column_spacing(1)
 | 
			
		||||
            .highlight_style(self.palette.create_highlight_style())
 | 
			
		||||
            .block(Block::bordered()
 | 
			
		||||
                .border_style(border_style)
 | 
			
		||||
                .border_type(border_type)
 | 
			
		||||
                .title_alignment(Alignment::Right)
 | 
			
		||||
                .title_style(self.palette.create_title_style(false))
 | 
			
		||||
                .title("Validator details"));
 | 
			
		||||
 | 
			
		||||
        let table = Table::new(
 | 
			
		||||
            vec![
 | 
			
		||||
                Row::new(vec![
 | 
			
		||||
                    Cell::from(Text::from("Forbidden".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                    Cell::from(Text::from(self.is_nomination_disabled.to_string()).alignment(Alignment::Right)), 
 | 
			
		||||
                ]),
 | 
			
		||||
                Row::new(vec![
 | 
			
		||||
                    Cell::from(Text::from("Nominators".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                    Cell::from(Text::from(self.others_len.to_string()).alignment(Alignment::Right)), 
 | 
			
		||||
                ]),
 | 
			
		||||
                Row::new(vec![
 | 
			
		||||
                    Cell::from(Text::from("Total staked".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                    Cell::from(Text::from(self.prepare_u128(self.total_balance)).alignment(Alignment::Right)), 
 | 
			
		||||
                ]),
 | 
			
		||||
                Row::new(vec![
 | 
			
		||||
                    Cell::from(Text::from("Own stake".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                    Cell::from(Text::from(self.prepare_u128(self.own_balance)).alignment(Alignment::Right)), 
 | 
			
		||||
                ]),
 | 
			
		||||
                Row::new(vec![
 | 
			
		||||
                    Cell::from(Text::from("Imbalance".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                    Cell::from(Text::from(self.prepare_stake_imbalance()).alignment(Alignment::Right)), 
 | 
			
		||||
                ]),
 | 
			
		||||
                Row::new(vec![
 | 
			
		||||
                    Cell::from(Text::from("Commission".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                    Cell::from(Text::from(format!("{:.4}%", self.commission)).alignment(Alignment::Right)), 
 | 
			
		||||
                ]),
 | 
			
		||||
                Row::new(vec![
 | 
			
		||||
                    Cell::from(Text::from("Points ratio".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                    Cell::from(Text::from(format!("{:.4}%", self.points_ratio)).alignment(Alignment::Right)), 
 | 
			
		||||
                ]),
 | 
			
		||||
                Row::new(vec![
 | 
			
		||||
                    Cell::from(Text::from("In next era".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                    Cell::from(Text::from(self.prepare_state_string()).alignment(Alignment::Right)), 
 | 
			
		||||
                ]),
 | 
			
		||||
                Row::new(vec![
 | 
			
		||||
                    Cell::from(Text::from("Last payout".to_string()).alignment(Alignment::Left)),
 | 
			
		||||
                    Cell::from(Text::from(format!("{} days ago", self.latest_era_claim)).alignment(Alignment::Right)), 
 | 
			
		||||
                ]),
 | 
			
		||||
            ],
 | 
			
		||||
            [
 | 
			
		||||
                Constraint::Max(12),
 | 
			
		||||
                Constraint::Min(0),
 | 
			
		||||
            ],
 | 
			
		||||
        )
 | 
			
		||||
        .column_spacing(1)
 | 
			
		||||
        .highlight_style(self.palette.create_highlight_style())
 | 
			
		||||
        .block(Block::bordered()
 | 
			
		||||
            .border_style(border_style)
 | 
			
		||||
            .border_type(border_type)
 | 
			
		||||
            .title_alignment(Alignment::Right)
 | 
			
		||||
            .title_style(self.palette.create_title_style(false))
 | 
			
		||||
            .title("Validator details"));
 | 
			
		||||
            frame.render_widget(table, place);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        frame.render_widget(table, place);
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -6,6 +6,7 @@ use color_eyre::Result;
 | 
			
		||||
use crossterm::event::{KeyCode, KeyEvent};
 | 
			
		||||
use ratatui::layout::{Constraint, Margin};
 | 
			
		||||
use ratatui::style::{Stylize, Modifier};
 | 
			
		||||
use ratatui::widgets::Clear;
 | 
			
		||||
use ratatui::{
 | 
			
		||||
    text::Text,
 | 
			
		||||
    layout::{Alignment, Rect}, 
 | 
			
		||||
@ -38,6 +39,8 @@ pub struct CurrentValidators {
 | 
			
		||||
    total_points: u32,
 | 
			
		||||
    era_index: u32,
 | 
			
		||||
    my_stash_id: Option<[u8; 32]>,
 | 
			
		||||
    account_id: [u8; 32],
 | 
			
		||||
    account_secret_seed: [u8; 32],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for CurrentValidators {
 | 
			
		||||
@ -62,10 +65,37 @@ impl CurrentValidators {
 | 
			
		||||
            total_points: 0,
 | 
			
		||||
            era_index: 0,
 | 
			
		||||
            my_stash_id: None,
 | 
			
		||||
            account_id: [0u8; 32],
 | 
			
		||||
            account_secret_seed: [0u8; 32],
 | 
			
		||||
            palette: StylePalette::default(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn close_popup(&mut self) {
 | 
			
		||||
        self.is_active = false;
 | 
			
		||||
        if let Some(action_tx) = &self.action_tx {
 | 
			
		||||
            let _ = action_tx.send(Action::ClosePopup);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn move_selected(&mut self, index: usize) {
 | 
			
		||||
        if self.individual.len() > 0 {
 | 
			
		||||
            self.table_state.select(Some(index));
 | 
			
		||||
            self.scroll_state = self.scroll_state.position(index);
 | 
			
		||||
            self.update_choosen_details(index);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn update_used_account(&mut self, account_id: [u8; 32], secret_seed_str: String) {
 | 
			
		||||
        let secret_seed: [u8; 32] = hex::decode(secret_seed_str)
 | 
			
		||||
            .expect("stored seed is valid hex string; qed")
 | 
			
		||||
            .as_slice()
 | 
			
		||||
            .try_into()
 | 
			
		||||
            .expect("stored seed is valid length; qed");
 | 
			
		||||
        self.account_id = account_id;
 | 
			
		||||
        self.account_secret_seed = secret_seed;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn update_choosen_details(&self, index: usize) {
 | 
			
		||||
        if let Some(action_tx) = &self.action_tx {
 | 
			
		||||
            let (selected_account_id, selected_points) = self.individual
 | 
			
		||||
@ -143,9 +173,7 @@ impl CurrentValidators {
 | 
			
		||||
 | 
			
		||||
    fn first_row(&mut self) {
 | 
			
		||||
        if self.individual.len() > 0 {
 | 
			
		||||
            self.table_state.select(Some(0));
 | 
			
		||||
            self.scroll_state = self.scroll_state.position(0);
 | 
			
		||||
            self.update_choosen_details(0);
 | 
			
		||||
            self.move_selected(0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -160,17 +188,13 @@ impl CurrentValidators {
 | 
			
		||||
            },
 | 
			
		||||
            None => 0,
 | 
			
		||||
        };
 | 
			
		||||
        self.table_state.select(Some(i));
 | 
			
		||||
        self.scroll_state = self.scroll_state.position(i);
 | 
			
		||||
        self.update_choosen_details(i);
 | 
			
		||||
        self.move_selected(i);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn last_row(&mut self) {
 | 
			
		||||
        if self.individual.len() > 0 {
 | 
			
		||||
            let last = self.individual.len() - 1;
 | 
			
		||||
            self.table_state.select(Some(last));
 | 
			
		||||
            self.scroll_state = self.scroll_state.position(last);
 | 
			
		||||
            self.update_choosen_details(last);
 | 
			
		||||
            self.move_selected(last);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -185,9 +209,7 @@ impl CurrentValidators {
 | 
			
		||||
            },
 | 
			
		||||
            None => 0
 | 
			
		||||
        };
 | 
			
		||||
        self.table_state.select(Some(i));
 | 
			
		||||
        self.scroll_state = self.scroll_state.position(i);
 | 
			
		||||
        self.update_choosen_details(i);
 | 
			
		||||
        self.move_selected(i);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn update_era_rewards(
 | 
			
		||||
@ -207,11 +229,6 @@ impl CurrentValidators {
 | 
			
		||||
                    .position(|item| item.account_id == account_id) {
 | 
			
		||||
                        self.individual.swap(0, index);
 | 
			
		||||
                }
 | 
			
		||||
                let current_index = self.table_state
 | 
			
		||||
                    .selected()
 | 
			
		||||
                    .unwrap_or_default();
 | 
			
		||||
                self.table_state.select(Some(current_index));
 | 
			
		||||
                self.update_choosen_details(current_index);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -222,7 +239,7 @@ impl CurrentValidators {
 | 
			
		||||
impl PartialComponent for CurrentValidators {
 | 
			
		||||
    fn set_active(&mut self, current_tab: CurrentTab) {
 | 
			
		||||
        match current_tab {
 | 
			
		||||
            CurrentTab::CurrentValidators => self.is_active = true,
 | 
			
		||||
            CurrentTab::CurrentValidatorsPopup => self.is_active = true,
 | 
			
		||||
            _ => self.is_active = false,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -235,7 +252,7 @@ impl Component for CurrentValidators {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn register_config_handler(&mut self, config: Config) -> Result<()> {
 | 
			
		||||
        if let Some(style) = config.styles.get(&crate::app::Mode::Nominator) {
 | 
			
		||||
        if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) {
 | 
			
		||||
            self.palette.with_normal_style(style.get("normal_style").copied());
 | 
			
		||||
            self.palette.with_hover_style(style.get("hover_style").copied());
 | 
			
		||||
            self.palette.with_normal_border_style(style.get("normal_border_style").copied());
 | 
			
		||||
@ -255,6 +272,7 @@ impl Component for CurrentValidators {
 | 
			
		||||
    fn update(&mut self, action: Action) -> Result<Option<Action>> {
 | 
			
		||||
        match action {
 | 
			
		||||
            Action::UpdateKnownValidator(validator_name) => self.save_validator_name(validator_name),
 | 
			
		||||
            Action::UsedAccount(account_id, secret_seed) => self.update_used_account(account_id, secret_seed),
 | 
			
		||||
            Action::SetStashAccount(account_id) => self.my_stash_id = Some(account_id),
 | 
			
		||||
            Action::SetCurrentValidatorEraRewards(era_index, total_points, individual) => 
 | 
			
		||||
                self.update_era_rewards(era_index, total_points, &individual),
 | 
			
		||||
@ -273,6 +291,7 @@ impl Component for CurrentValidators {
 | 
			
		||||
                KeyCode::Char('R') => self.update_known_validator_record(),
 | 
			
		||||
                KeyCode::Char('C') => self.clear_choosen(),
 | 
			
		||||
                KeyCode::Enter => self.flip_validator_check(),
 | 
			
		||||
                KeyCode::Esc => self.close_popup(),
 | 
			
		||||
                _ => {},
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
@ -280,10 +299,11 @@ impl Component for CurrentValidators {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> {
 | 
			
		||||
        let [place, _] = super::validator_details_layout(area);
 | 
			
		||||
        let (border_style, border_type) = self.palette.create_border_style(self.is_active);
 | 
			
		||||
        let table = Table::new(
 | 
			
		||||
            self.individual
 | 
			
		||||
        if self.is_active {
 | 
			
		||||
            let (border_style, border_type) = self.palette.create_border_style(self.is_active);
 | 
			
		||||
            let [place, _] = super::nominator_layout(area);
 | 
			
		||||
            let table = Table::new(
 | 
			
		||||
                self.individual
 | 
			
		||||
                .iter()
 | 
			
		||||
                .enumerate()
 | 
			
		||||
                .map(|(index, info)| {
 | 
			
		||||
@ -337,30 +357,32 @@ impl Component for CurrentValidators {
 | 
			
		||||
                Constraint::Min(0),
 | 
			
		||||
                Constraint::Length(6),
 | 
			
		||||
            ],
 | 
			
		||||
        )
 | 
			
		||||
        .style(self.palette.create_basic_style(false))
 | 
			
		||||
        .highlight_style(self.palette.create_basic_style(true))
 | 
			
		||||
        .column_spacing(1)
 | 
			
		||||
        .block(Block::bordered()
 | 
			
		||||
            .border_style(border_style)
 | 
			
		||||
            .border_type(border_type)
 | 
			
		||||
            .padding(Padding::right(2))
 | 
			
		||||
            .title_alignment(Alignment::Right)
 | 
			
		||||
            .title_style(self.palette.create_title_style(false))
 | 
			
		||||
            .title(format!("Validators | Total points: {}", self.total_points)));
 | 
			
		||||
            )
 | 
			
		||||
                .style(self.palette.create_basic_style(false))
 | 
			
		||||
                .highlight_style(self.palette.create_basic_style(true))
 | 
			
		||||
                .column_spacing(1)
 | 
			
		||||
                .block(Block::bordered()
 | 
			
		||||
                    .border_style(border_style)
 | 
			
		||||
                    .border_type(border_type)
 | 
			
		||||
                    .padding(Padding::right(2))
 | 
			
		||||
                    .title_alignment(Alignment::Right)
 | 
			
		||||
                    .title_style(self.palette.create_title_style(false))
 | 
			
		||||
                    .title(format!("Validators {} | Total points: {}", self.individual.len(), self.total_points)));
 | 
			
		||||
 | 
			
		||||
        let scrollbar = Scrollbar::default()
 | 
			
		||||
            .orientation(ScrollbarOrientation::VerticalRight)
 | 
			
		||||
            .begin_symbol(None)
 | 
			
		||||
            .end_symbol(None)
 | 
			
		||||
            .style(self.palette.create_scrollbar_style());
 | 
			
		||||
            let scrollbar = Scrollbar::default()
 | 
			
		||||
                .orientation(ScrollbarOrientation::VerticalRight)
 | 
			
		||||
                .begin_symbol(None)
 | 
			
		||||
                .end_symbol(None)
 | 
			
		||||
                .style(self.palette.create_scrollbar_style());
 | 
			
		||||
 | 
			
		||||
        frame.render_stateful_widget(table, place, &mut self.table_state);
 | 
			
		||||
        frame.render_stateful_widget(
 | 
			
		||||
            scrollbar,
 | 
			
		||||
            place.inner(Margin { vertical: 1, horizontal: 1 }),
 | 
			
		||||
            &mut self.scroll_state,
 | 
			
		||||
        );
 | 
			
		||||
            frame.render_widget(Clear, place);
 | 
			
		||||
            frame.render_stateful_widget(table, place, &mut self.table_state);
 | 
			
		||||
            frame.render_stateful_widget(
 | 
			
		||||
                scrollbar,
 | 
			
		||||
                place.inner(Margin { vertical: 1, horizontal: 1 }),
 | 
			
		||||
                &mut self.scroll_state,
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
use color_eyre::Result;
 | 
			
		||||
use crossterm::event::{KeyCode, KeyEvent};
 | 
			
		||||
use ratatui::{
 | 
			
		||||
    layout::{Constraint, Layout, Rect},
 | 
			
		||||
    layout::{Constraint, Flex, Layout, Rect},
 | 
			
		||||
    Frame,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -18,10 +18,13 @@ mod accounts;
 | 
			
		||||
mod overview;
 | 
			
		||||
mod add_address_book_record;
 | 
			
		||||
mod rename_address_book_record;
 | 
			
		||||
mod details;
 | 
			
		||||
mod account_details;
 | 
			
		||||
mod staking_ledger;
 | 
			
		||||
mod bond_popup;
 | 
			
		||||
mod payee_popup;
 | 
			
		||||
mod current_validators;
 | 
			
		||||
mod current_validator_details;
 | 
			
		||||
mod rename_known_validator;
 | 
			
		||||
 | 
			
		||||
use balance::Balance;
 | 
			
		||||
use transfer::Transfer;
 | 
			
		||||
@ -33,10 +36,13 @@ use accounts::Accounts;
 | 
			
		||||
use overview::Overview;
 | 
			
		||||
use add_address_book_record::AddAddressBookRecord;
 | 
			
		||||
use rename_address_book_record::RenameAddressBookRecord;
 | 
			
		||||
use details::AccountDetails;
 | 
			
		||||
use account_details::AccountDetails;
 | 
			
		||||
use staking_ledger::StakingLedger;
 | 
			
		||||
use bond_popup::BondPopup;
 | 
			
		||||
use payee_popup::PayeePopup;
 | 
			
		||||
use current_validators::CurrentValidators;
 | 
			
		||||
use current_validator_details::CurrentValidatorDetails;
 | 
			
		||||
use rename_known_validator::RenameKnownValidator;
 | 
			
		||||
 | 
			
		||||
use super::Component;
 | 
			
		||||
use crate::{action::Action, app::Mode, config::Config};
 | 
			
		||||
@ -55,6 +61,7 @@ pub enum CurrentTab {
 | 
			
		||||
    AccountDetails,
 | 
			
		||||
    BondPopup,
 | 
			
		||||
    PayeePopup,
 | 
			
		||||
    CurrentValidatorsPopup,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub trait PartialComponent: Component {
 | 
			
		||||
@ -89,6 +96,9 @@ impl Default for Wallet {
 | 
			
		||||
                Box::new(AccountDetails::default()),
 | 
			
		||||
                Box::new(BondPopup::default()),
 | 
			
		||||
                Box::new(PayeePopup::default()),
 | 
			
		||||
                Box::new(CurrentValidators::default()),
 | 
			
		||||
                Box::new(CurrentValidatorDetails::default()),
 | 
			
		||||
                Box::new(RenameKnownValidator::default()),
 | 
			
		||||
            ],
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -147,6 +157,7 @@ impl Component for Wallet {
 | 
			
		||||
                CurrentTab::AccountDetails |
 | 
			
		||||
                CurrentTab::BondPopup |
 | 
			
		||||
                CurrentTab::PayeePopup |
 | 
			
		||||
                CurrentTab::CurrentValidatorsPopup |
 | 
			
		||||
                CurrentTab::AddAddressBookRecord => {
 | 
			
		||||
                    for component in self.components.iter_mut() {
 | 
			
		||||
                        component.handle_key_event(key)?;
 | 
			
		||||
@ -178,6 +189,10 @@ impl Component for Wallet {
 | 
			
		||||
                    self.previous_tab = self.current_tab;
 | 
			
		||||
                    self.current_tab = CurrentTab::PayeePopup;
 | 
			
		||||
                },
 | 
			
		||||
                KeyCode::Char('N') => {
 | 
			
		||||
                    self.previous_tab = self.current_tab;
 | 
			
		||||
                    self.current_tab = CurrentTab::CurrentValidatorsPopup;
 | 
			
		||||
                },
 | 
			
		||||
                KeyCode::Char('l') | KeyCode::Right => self.move_right(),
 | 
			
		||||
                KeyCode::Char('h') | KeyCode::Left => self.move_left(),
 | 
			
		||||
                _ => {
 | 
			
		||||
@ -256,3 +271,12 @@ pub fn account_layout(area: Rect) -> [Rect; 4] {
 | 
			
		||||
        Constraint::Max(6),
 | 
			
		||||
    ]).areas(place)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn nominator_layout(area: Rect) -> [Rect; 2] {
 | 
			
		||||
    let v = Layout::vertical([Constraint::Max(11)]).flex(Flex::Center);
 | 
			
		||||
    let [area] = v.areas(area);
 | 
			
		||||
    Layout::horizontal([
 | 
			
		||||
        Constraint::Percentage(60),
 | 
			
		||||
        Constraint::Percentage(40),
 | 
			
		||||
    ]).areas(area)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -38,14 +38,18 @@ impl RenameKnownValidator {
 | 
			
		||||
            palette: StylePalette::default(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl RenameKnownValidator {
 | 
			
		||||
    fn close_popup(&mut self) {
 | 
			
		||||
        self.is_active = false;
 | 
			
		||||
        self.name = Input::new(String::new());
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    fn submit_message(&mut self) {
 | 
			
		||||
        if let Some(action_tx) = &self.action_tx {
 | 
			
		||||
            let _ = action_tx.send(Action::UpdateKnownValidator(
 | 
			
		||||
                    self.name.value().to_string()));
 | 
			
		||||
        }
 | 
			
		||||
        self.close_popup();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn enter_char(&mut self, new_char: char) {
 | 
			
		||||
@ -66,15 +70,7 @@ impl RenameKnownValidator {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl PartialComponent for RenameKnownValidator {
 | 
			
		||||
    fn set_active(&mut self, current_tab: CurrentTab) {
 | 
			
		||||
        match current_tab {
 | 
			
		||||
            CurrentTab::RenameKnownValidator => self.is_active = true,
 | 
			
		||||
            _ => {
 | 
			
		||||
                self.is_active = false;
 | 
			
		||||
                self.name = Input::new(String::new());
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
    fn set_active(&mut self, _current_tab: CurrentTab) { }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Component for RenameKnownValidator {
 | 
			
		||||
@ -83,8 +79,16 @@ impl Component for RenameKnownValidator {
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn update(&mut self, action: Action) -> Result<Option<Action>> {
 | 
			
		||||
        match action {
 | 
			
		||||
            Action::RenameKnownValidatorRecord => self.is_active = true,
 | 
			
		||||
            _ => {}
 | 
			
		||||
        };
 | 
			
		||||
        Ok(None)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn register_config_handler(&mut self, config: Config) -> Result<()> {
 | 
			
		||||
        if let Some(style) = config.styles.get(&crate::app::Mode::Nominator) {
 | 
			
		||||
        if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) {
 | 
			
		||||
            self.palette.with_normal_style(style.get("normal_style").copied());
 | 
			
		||||
            self.palette.with_normal_border_style(style.get("normal_border_style").copied());
 | 
			
		||||
            self.palette.with_normal_title_style(style.get("normal_title_style").copied());
 | 
			
		||||
@ -102,7 +106,7 @@ impl Component for RenameKnownValidator {
 | 
			
		||||
                KeyCode::Backspace => self.delete_char(),
 | 
			
		||||
                KeyCode::Left => self.move_cursor_left(),
 | 
			
		||||
                KeyCode::Right => self.move_cursor_right(),
 | 
			
		||||
                KeyCode::Esc => self.is_active = false, 
 | 
			
		||||
                KeyCode::Esc => self.close_popup(), 
 | 
			
		||||
                _ => {},
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user