add coins panel to gui
This commit is contained in:
parent
9bb20303e7
commit
86eddb28c6
@ -3,4 +3,5 @@ pub enum Menu {
|
||||
Home,
|
||||
Receive,
|
||||
Settings,
|
||||
Coins,
|
||||
}
|
||||
|
||||
@ -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())
|
||||
|
||||
79
gui/src/app/state/coins.rs
Normal file
79
gui/src/app/state/coins.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
@ -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
61
gui/src/app/view/coins.rs
Normal 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()
|
||||
}
|
||||
@ -5,6 +5,8 @@ pub enum Message {
|
||||
Reload,
|
||||
Clipboard(String),
|
||||
Menu(Menu),
|
||||
Close,
|
||||
Select(usize),
|
||||
Settings(usize, SettingsMessage),
|
||||
}
|
||||
|
||||
|
||||
@ -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)),
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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,
|
||||
},
|
||||
}
|
||||
|
||||
@ -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}')
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user