Skip to content

Commit

Permalink
feat: add animated busy indicator for loading balances
Browse files Browse the repository at this point in the history
  • Loading branch information
MishkaRogachev committed Sep 30, 2024
1 parent 046f3c1 commit f111d03
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 31 deletions.
35 changes: 19 additions & 16 deletions src/tui/screens/porfolio_accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use ratatui::{
crossterm::event::Event,
layout::{Alignment, Constraint, Direction, Layout, Rect},
style::{Color, Style},
widgets::Paragraph, Frame
widgets::{Paragraph, Widget}, Frame
};

use crate::service::{crypto:: Crypto, session::Session};
use crate::tui::{widgets::account, app::AppScreen};
use crate::tui::{widgets::{controls, account}, app::AppScreen};

const SUMMARY_HEIGHT: u16 = 2;
const SUMMARY_TEXT: &str = "Summary balance";
Expand All @@ -20,20 +20,23 @@ pub struct Screen {
last_update: Option<tokio::time::Instant>,

accounts: Vec<account::Account>,
busy: controls::Busy,
}

impl Screen {
pub fn new(session: Session, crypto: Arc<Mutex<Crypto>>) -> Self {
let accounts = vec![account::Account::new(session.account)];
let busy = controls::Busy::new("Loading..");

Self {
crypto,
last_update: None,
accounts,
busy,
}
}

fn get_summary_balance_str(&self) -> (String, bool) {
fn render_summary_balance_str(&mut self, frame: &mut Frame, area: Rect) {
let mut usd_summary = None;
let mut test_network = false;
for account in &self.accounts {
Expand All @@ -43,11 +46,17 @@ impl Screen {
}
}
match usd_summary {
Some(usd_summary) => (
format!("{} {:.2} USD", if test_network {"(Testnet) "} else { "" }, usd_summary),
test_network
),
None => (String::from("Loading.."), false),
Some(usd_summary) => {
let balances_str = format!("{} {:.2} USD", if test_network {"(Testnet) "} else { "" }, usd_summary);
let balances_color = if test_network { Color::Red } else { Color::Yellow };
Paragraph::new(balances_str)
.style(Style::default().fg(balances_color).add_modifier(ratatui::style::Modifier::BOLD))
.alignment(Alignment::Right)
.render(area, frame.buffer_mut());
},
None => {
self.busy.render(frame, area);
},
}
}
}
Expand Down Expand Up @@ -92,15 +101,9 @@ impl AppScreen for Screen {
let summary_label = Paragraph::new(SUMMARY_TEXT)
.style(Style::default().fg(Color::Yellow).add_modifier(ratatui::style::Modifier::BOLD))
.alignment(Alignment::Left);

let (summary_balance, from_test_network) = self.get_summary_balance_str();
let balance_color = if from_test_network { Color::Red } else { Color::Yellow };
let balances_label = Paragraph::new(summary_balance)
.style(Style::default().fg(balance_color).add_modifier(ratatui::style::Modifier::BOLD))
.alignment(Alignment::Right);

frame.render_widget(summary_label, summary[0]);
frame.render_widget(balances_label, summary[1]);

self.render_summary_balance_str(frame, summary[1]);

let accounts_layout = Layout::default()
.direction(Direction::Vertical)
Expand Down
33 changes: 19 additions & 14 deletions src/tui/widgets/account.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
use ratatui::{
layout::{Alignment, Constraint, Direction, Layout, Rect},
style::{Color, Style},
widgets::{Block, Borders, Paragraph},
widgets::{Block, Borders, Paragraph, Widget},
Frame
};

use crate::core::balance::Balances;

use super::controls;

pub struct Account {
pub name: String,
pub address: web3::types::Address,
pub balances: Option<Balances>,
busy: controls::Busy,
}

impl Account {
pub fn new(address: web3::types::Address) -> Self {
let busy = controls::Busy::new("Loading..");

Self {
name: "Master Keypair".to_string(), // TODO: account name
address,
balances: None,
busy,
}
}

Expand All @@ -38,11 +44,16 @@ impl Account {
format!("ETH ({})", self.address.to_string()) // TODO: different blockchain
}

fn get_account_balance_str(&self) -> (String, bool) {
fn render_total_balances(&mut self, frame: &mut Frame, area: Rect) {
if let Some((total_value, total_usd, from_test_network)) = self.get_total_balances() {
(format!("{:.6} ETH ({:.2} USD)", total_value, total_usd), from_test_network)
let balances_str = format!("{:.6} ETH ({:.2} USD)", total_value, total_usd);
let balances_color = if from_test_network { Color::Red } else { Color::Yellow };
Paragraph::new(balances_str)
.style(Style::default().fg(balances_color).add_modifier(ratatui::style::Modifier::BOLD))
.alignment(Alignment::Right)
.render(area, frame.buffer_mut());
} else {
("Loading...".to_string(), false)
self.busy.render(frame, area);
}
}

Expand Down Expand Up @@ -71,17 +82,11 @@ impl Account {
.split(tokens_layout[0]);

let eth_label = Paragraph::new(self.get_account_str())
.style(Style::default().fg(Color::Yellow).add_modifier(ratatui::style::Modifier::BOLD))
.alignment(Alignment::Left);

let (balance_str, from_test_network) = self.get_account_balance_str();
let balance_color = if from_test_network { Color::Red } else { Color::Yellow };
let balances_label = Paragraph::new(balance_str)
.style(Style::default().fg(balance_color).add_modifier(ratatui::style::Modifier::BOLD))
.alignment(Alignment::Right);

.style(Style::default().fg(Color::Yellow).add_modifier(ratatui::style::Modifier::BOLD))
.alignment(Alignment::Left);
frame.render_widget(eth_label, header_layout[1]);
frame.render_widget(balances_label, header_layout[2]);

self.render_total_balances(frame, header_layout[2]);

for i in 0..balances_cnt {
let token_layout = Layout::default()
Expand Down
31 changes: 30 additions & 1 deletion src/tui/widgets/controls.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::{borrow::BorrowMut, collections::HashMap};

use ratatui::{
crossterm::event::{Event, KeyCode, KeyEvent, MouseButton, MouseEventKind},
Expand All @@ -19,6 +19,9 @@ pub const CHECKBOX_WIDTH: u16 = 5;
const CHECKMARK_ON: &str = "x";
const CHECKMARK_OFF: &str = " ";

const BUSY_PERIOD: u128 = 250;
const BUSY_SYMBOLS: [char; 7] = ['▚', '▞', '▘', '▝', '▗', '▖', '▘'];

pub enum FocusableEvent {
FocusChanged,
FocusFinished,
Expand Down Expand Up @@ -91,6 +94,11 @@ pub struct CheckList<T> {
pub options: HashMap<T, CheckBox>
}

pub struct Busy {
label: String,
start_time: tokio::time::Instant,
}

impl Button {
pub fn new(label: &str, hotkey: Option<char>) -> Self {
Button {
Expand Down Expand Up @@ -665,3 +673,24 @@ where T: Eq + std::hash::Hash + Clone {
}
}
}

impl Busy {
pub fn new(label: &str) -> Self {
Self {
label: label.to_string(),
start_time: tokio::time::Instant::now(),
}
}

pub fn render(&mut self, frame: &mut Frame, area: Rect) {
let elapsed = self.start_time.elapsed().as_millis();
let index = (elapsed / BUSY_PERIOD as u128 % BUSY_SYMBOLS.len() as u128) as usize;
let symbol = BUSY_SYMBOLS[index];
let text = format!("{} {}", self.label, symbol);

Paragraph::new(text)
.style(Style::default().fg(Color::Yellow))
.alignment(Alignment::Right)
.render(area, frame.buffer_mut());
}
}

0 comments on commit f111d03

Please sign in to comment.