diff --git a/gui/src/app/message.rs b/gui/src/app/message.rs index 9393c34e..8d2eb808 100644 --- a/gui/src/app/message.rs +++ b/gui/src/app/message.rs @@ -15,4 +15,5 @@ pub enum Message { BlockHeight(Result), ReceiveAddress(Result), Coins(Result, Error>), + SpendTxs(Result, Error>), } diff --git a/gui/src/app/mod.rs b/gui/src/app/mod.rs index a8593d4a..85663144 100644 --- a/gui/src/app/mod.rs +++ b/gui/src/app/mod.rs @@ -21,7 +21,7 @@ pub use minisafe::config::Config as DaemonConfig; pub use config::Config; pub use message::Message; -use state::{CoinsPanel, Home, ReceivePanel, State}; +use state::{CoinsPanel, Home, ReceivePanel, SpendPanel, State}; use crate::{ app::{cache::Cache, error::Error, menu::Menu}, @@ -65,7 +65,7 @@ impl App { menu::Menu::Home => Home::new(&self.cache.coins).into(), menu::Menu::Coins => CoinsPanel::new(&self.cache.coins).into(), menu::Menu::Receive => ReceivePanel::default().into(), - menu::Menu::Spend => ReceivePanel::default().into(), + menu::Menu::Spend => SpendPanel::new(&self.cache.coins, &self.cache.spend_txs).into(), }; self.state.load(self.daemon.clone()) } @@ -103,6 +103,9 @@ impl App { Message::Coins(Ok(coins)) => { self.cache.coins = coins.clone(); } + Message::SpendTxs(Ok(txs)) => { + self.cache.spend_txs = txs.clone(); + } Message::BlockHeight(Ok(blockheight)) => { self.cache.blockheight = *blockheight; } diff --git a/gui/src/app/state/mod.rs b/gui/src/app/state/mod.rs index 2a8f0b65..270b0f6d 100644 --- a/gui/src/app/state/mod.rs +++ b/gui/src/app/state/mod.rs @@ -1,5 +1,6 @@ mod coins; mod settings; +mod spend; use std::sync::Arc; @@ -12,6 +13,7 @@ use crate::daemon::{model::Coin, Daemon}; pub use coins::CoinsPanel; pub use settings::SettingsState; +pub use spend::SpendPanel; pub trait State { fn view<'a>(&'a self, cache: &'a Cache) -> Element<'a, view::Message>; diff --git a/gui/src/app/state/spend.rs b/gui/src/app/state/spend.rs new file mode 100644 index 00000000..1dc5ac92 --- /dev/null +++ b/gui/src/app/state/spend.rs @@ -0,0 +1,65 @@ +use std::sync::Arc; + +use iced::{pure::Element, Command}; + +use super::State; +use crate::{ + app::{cache::Cache, error::Error, menu::Menu, message::Message, view}, + daemon::{ + model::{Coin, SpendTx}, + Daemon, + }, +}; + +pub struct SpendPanel { + spend_txs: Vec, + warning: Option, +} + +impl SpendPanel { + pub fn new(_coins: &[Coin], spend_txs: &[SpendTx]) -> Self { + Self { + spend_txs: spend_txs.to_vec(), + warning: None, + } + } +} + +impl State for SpendPanel { + fn view<'a>(&'a self, cache: &'a Cache) -> Element<'a, view::Message> { + view::dashboard( + &Menu::Spend, + cache, + self.warning.as_ref(), + view::spend::spend_view(&self.spend_txs), + ) + } + + fn update( + &mut self, + _daemon: Arc, + _cache: &Cache, + _message: Message, + ) -> Command { + Command::none() + } + + fn load(&self, daemon: Arc) -> Command { + let daemon = daemon.clone(); + Command::perform( + async move { + daemon + .list_spend_txs() + .map(|res| res.spend_txs) + .map_err(|e| e.into()) + }, + Message::SpendTxs, + ) + } +} + +impl From for Box { + fn from(s: SpendPanel) -> Box { + Box::new(s) + } +} diff --git a/gui/src/app/view/mod.rs b/gui/src/app/view/mod.rs index 4627e1b1..701d7146 100644 --- a/gui/src/app/view/mod.rs +++ b/gui/src/app/view/mod.rs @@ -5,6 +5,7 @@ pub mod coins; pub mod home; pub mod receive; pub mod settings; +pub mod spend; pub use message::*; use warning::warn; @@ -131,7 +132,7 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa row() .push( row() - .push(coin_icon()) + .push(send_icon()) .push(text("Send")) .spacing(10) .width(iced::Length::Fill) diff --git a/gui/src/app/view/spend.rs b/gui/src/app/view/spend.rs new file mode 100644 index 00000000..c69ef48c --- /dev/null +++ b/gui/src/app/view/spend.rs @@ -0,0 +1,59 @@ +use iced::{ + pure::{button, column, container, row, Element}, + Alignment, Length, +}; + +use crate::{ + daemon::model::SpendTx, + ui::component::{badge, button::Style, card, text::*}, +}; + +use super::message::Message; + +pub fn spend_view<'a>(spend_txs: &[SpendTx]) -> Element<'a, Message> { + column() + .push( + container( + row() + .push(text(&format!(" {}", spend_txs.len())).bold()) + .push(text(" draft transactions")), + ) + .width(Length::Fill), + ) + .push( + column().spacing(10).push( + spend_txs + .iter() + .enumerate() + .fold(column().spacing(10), |col, (i, tx)| { + col.push(spend_tx_list_view(i, tx)) + }), + ), + ) + .align_items(Alignment::Center) + .spacing(20) + .into() +} + +fn spend_tx_list_view<'a>(i: usize, _tx: &SpendTx) -> Element<'a, Message> { + container( + button( + row() + .push( + row() + .push(badge::spend()) + .spacing(10) + .align_items(Alignment::Center) + .width(Length::Fill), + ) + .push(text(&format!("{} BTC", 0)).bold().width(Length::Shrink)) + .align_items(Alignment::Center) + .spacing(20), + ) + .padding(10) + .on_press(Message::Select(i)) + .style(Style::TransparentBorder), + ) + .style(card::SimpleCardStyle) + .into() +}