add coins panel to gui

This commit is contained in:
edouard 2022-09-14 18:01:41 +02:00
parent 9bb20303e7
commit 86eddb28c6
10 changed files with 221 additions and 9 deletions

View File

@ -3,4 +3,5 @@ pub enum Menu {
Home,
Receive,
Settings,
Coins,
}

View File

@ -21,7 +21,7 @@ pub use minisafe::config::Config as DaemonConfig;
pub use config::Config;
pub use message::Message;
use state::{Home, ReceivePanel, State};
use state::{CoinsPanel, Home, ReceivePanel, State};
use crate::{
app::{cache::Cache, error::Error, menu::Menu},
@ -63,6 +63,7 @@ impl App {
.into()
}
menu::Menu::Home => Home::new(&self.cache.coins).into(),
menu::Menu::Coins => CoinsPanel::new(&self.cache.coins).into(),
menu::Menu::Receive => ReceivePanel::default().into(),
};
self.state.load(self.daemon.clone())

View File

@ -0,0 +1,79 @@
use std::sync::Arc;
use iced::pure::Element;
use iced::Command;
use crate::{
app::{cache::Cache, error::Error, menu::Menu, message::Message, state::State, view},
daemon::{model::Coin, Daemon},
};
pub struct CoinsPanel {
coins: Vec<Coin>,
selected_coin: Option<usize>,
warning: Option<Error>,
}
impl CoinsPanel {
pub fn new(coins: &[Coin]) -> Self {
Self {
coins: coins.to_owned(),
selected_coin: None,
warning: None,
}
}
}
impl State for CoinsPanel {
fn view<'a>(&'a self, _cache: &'a Cache) -> Element<'a, view::Message> {
view::dashboard(
&Menu::Coins,
self.warning.as_ref(),
view::coins::coins_view(&self.coins),
)
}
fn update(
&mut self,
_daemon: Arc<dyn Daemon + Sync + Send>,
_cache: &Cache,
message: Message,
) -> Command<Message> {
match message {
Message::Coins(res) => match res {
Err(e) => self.warning = Some(e),
Ok(coins) => {
self.warning = None;
self.coins = coins;
}
},
Message::View(view::Message::Close) => {
self.selected_coin = None;
}
Message::View(view::Message::Select(i)) => {
self.selected_coin = Some(i);
}
_ => {}
};
Command::none()
}
fn load(&self, daemon: Arc<dyn Daemon + Sync + Send>) -> Command<Message> {
let daemon = daemon.clone();
Command::perform(
async move {
daemon
.list_coins()
.map(|res| res.coins)
.map_err(|e| e.into())
},
Message::Coins,
)
}
}
impl From<CoinsPanel> for Box<dyn State> {
fn from(s: CoinsPanel) -> Box<dyn State> {
Box::new(s)
}
}

View File

@ -1,3 +1,4 @@
mod coins;
mod settings;
use std::sync::Arc;
@ -8,6 +9,8 @@ use iced::{widget::qr_code, Command, Subscription};
use super::{cache::Cache, error::Error, menu::Menu, message::Message, view};
use crate::daemon::{model::Coin, Daemon};
pub use coins::CoinsPanel;
pub use settings::SettingsState;
pub trait State {

61
gui/src/app/view/coins.rs Normal file
View File

@ -0,0 +1,61 @@
use iced::{
pure::{button, column, container, row, Element},
Alignment, Length,
};
use crate::ui::component::{badge, button::Style, card, text::*};
use crate::{app::view::message::Message, daemon::model::Coin};
pub fn coins_view<'a>(coins: &[Coin]) -> Element<'a, Message> {
column()
.push(
container(
row()
.push(text(&format!(" {}", coins.len())).bold())
.push(text(" coins")),
)
.width(Length::Fill),
)
.push(
column().spacing(10).push(
coins
.iter()
.enumerate()
.fold(column().spacing(10), |col, (i, coin)| {
col.push(coin_list_view(i, coin))
}),
),
)
.align_items(Alignment::Center)
.spacing(20)
.into()
}
fn coin_list_view<'a>(i: usize, coin: &Coin) -> Element<'a, Message> {
container(
button(
row()
.push(
row()
.push(badge::coin())
.push(text(&format!("block: {}", coin.block_height.unwrap_or(0))).small())
.spacing(10)
.align_items(Alignment::Center)
.width(Length::Fill),
)
.push(
text(&format!("{} BTC", coin.amount.as_btc()))
.bold()
.width(Length::Shrink),
)
.align_items(Alignment::Center)
.spacing(20),
)
.padding(10)
.on_press(Message::Select(i))
.style(Style::TransparentBorder),
)
.style(card::SimpleCardStyle)
.into()
}

View File

@ -5,6 +5,8 @@ pub enum Message {
Reload,
Clipboard(String),
Menu(Menu),
Close,
Select(usize),
Settings(usize, SettingsMessage),
}

View File

@ -1,6 +1,7 @@
mod message;
mod warning;
pub mod coins;
pub mod home;
pub mod receive;
pub mod settings;
@ -16,7 +17,7 @@ use iced::{
use crate::ui::{
color,
component::{button, separation, text::*},
icon::{home_icon, receive_icon, settings_icon},
icon::{coin_icon, home_icon, receive_icon, settings_icon},
};
use crate::app::{error::Error, menu::Menu};
@ -32,6 +33,16 @@ pub fn sidebar(menu: &Menu) -> widget::Container<Message> {
.width(iced::Length::Units(200))
};
let coins_button = if *menu == Menu::Coins {
button::primary(Some(coin_icon()), "Coins")
.on_press(Message::Reload)
.width(iced::Length::Units(200))
} else {
button::transparent(Some(coin_icon()), "Coins")
.on_press(Message::Menu(Menu::Coins))
.width(iced::Length::Units(200))
};
let receive_button = if *menu == Menu::Receive {
button::primary(Some(receive_icon()), "Receive")
.on_press(Message::Reload)
@ -64,8 +75,9 @@ pub fn sidebar(menu: &Menu) -> widget::Container<Message> {
.spacing(10),
)
.push(home_button)
.push(coins_button)
.push(receive_button)
.spacing(20)
.spacing(15)
.height(Length::Fill),
)
.push(container(settings_button).height(Length::Shrink)),

View File

@ -3,7 +3,7 @@ use iced::{
Length,
};
use crate::ui::color;
use crate::ui::{color, icon};
pub enum Style {
Standard,
@ -68,3 +68,52 @@ impl<'a, Message: 'a, S: 'a + widget::container::StyleSheet> From<Badge<S>>
.into()
}
}
pub struct ReceiveStyle;
impl widget::container::StyleSheet for ReceiveStyle {
fn style(&self) -> widget::container::Style {
widget::container::Style {
border_radius: 40.0,
background: color::BACKGROUND.into(),
..widget::container::Style::default()
}
}
}
pub fn receive<T>() -> widget::container::Container<'static, T> {
container(icon::receive_icon().width(Length::Units(20)))
.width(Length::Units(40))
.height(Length::Units(40))
.style(ReceiveStyle)
.center_x()
.center_y()
}
pub struct SpendStyle;
impl widget::container::StyleSheet for SpendStyle {
fn style(&self) -> widget::container::Style {
widget::container::Style {
border_radius: 40.0,
background: color::BACKGROUND.into(),
..widget::container::Style::default()
}
}
}
pub fn spend<T>() -> widget::container::Container<'static, T> {
container(icon::send_icon().width(Length::Units(20)))
.width(Length::Units(40))
.height(Length::Units(40))
.style(ReceiveStyle)
.center_x()
.center_y()
}
pub fn coin<T>() -> widget::container::Container<'static, T> {
container(icon::coin_icon().width(Length::Units(20)))
.width(Length::Units(40))
.height(Length::Units(40))
.style(ReceiveStyle)
.center_x()
.center_y()
}

View File

@ -60,7 +60,7 @@ impl button::StyleSheet for Style {
border_radius: 10.0,
border_width: 0.0,
border_color: Color::TRANSPARENT,
text_color: color::DARK_GREY,
text_color: Color::BLACK,
},
}
}
@ -77,18 +77,18 @@ impl button::StyleSheet for Style {
},
Style::Transparent => button::Style {
shadow_offset: Vector::default(),
background: color::FOREGROUND.into(),
background: color::BACKGROUND.into(),
border_radius: 10.0,
border_width: 0.0,
border_color: Color::TRANSPARENT,
text_color: color::DARK_GREY,
text_color: Color::BLACK,
},
Style::TransparentBorder => button::Style {
shadow_offset: Vector::default(),
background: Color::TRANSPARENT.into(),
border_radius: 10.0,
border_width: 2.0,
border_color: Color::TRANSPARENT,
border_width: 1.0,
border_color: Color::BLACK,
text_color: Color::BLACK,
},
}

View File

@ -66,6 +66,10 @@ pub fn vaults_icon() -> Text {
icon('\u{F1C7}')
}
pub fn coin_icon() -> Text {
icon('\u{F567}')
}
pub fn settings_icon() -> Text {
icon('\u{F3E5}')
}