diff --git a/gui/src/app/state/mod.rs b/gui/src/app/state/mod.rs index 753116f9..b35325f3 100644 --- a/gui/src/app/state/mod.rs +++ b/gui/src/app/state/mod.rs @@ -266,23 +266,19 @@ impl From for Box { #[derive(Default)] pub struct ReceivePanel { - address: Option
, + addresses: Vec
, qr_code: Option, warning: Option, } impl State for ReceivePanel { fn view<'a>(&'a self, cache: &'a Cache) -> Element<'a, view::Message> { - if let Some(address) = &self.address { - view::dashboard( - &Menu::Receive, - cache, - self.warning.as_ref(), - view::receive::receive(address, self.qr_code.as_ref().unwrap()), - ) - } else { - view::dashboard(&Menu::Receive, cache, self.warning.as_ref(), Column::new()) - } + view::dashboard( + &Menu::Receive, + cache, + self.warning.as_ref(), + view::receive::receive(&self.addresses, self.qr_code.as_ref()), + ) } fn update( &mut self, @@ -296,7 +292,7 @@ impl State for ReceivePanel { Ok(address) => { self.warning = None; self.qr_code = Some(qr_code::State::new(address.to_qr_uri()).unwrap()); - self.address = Some(address); + self.addresses.push(address); } Err(e) => self.warning = Some(e), } @@ -367,6 +363,6 @@ mod tests { let sandbox = sandbox.load(client, &Cache::default()).await; let panel = sandbox.state(); - assert_eq!(panel.address, Some(addr)); + assert_eq!(panel.addresses, vec![addr]); } } diff --git a/gui/src/app/view/receive.rs b/gui/src/app/view/receive.rs index 4ebced2d..eaed0259 100644 --- a/gui/src/app/view/receive.rs +++ b/gui/src/app/view/receive.rs @@ -1,11 +1,15 @@ use iced::{ - widget::qr_code::{self, QRCode}, + widget::{ + qr_code::{self, QRCode}, + scrollable, Space, + }, Alignment, Length, }; use liana::miniscript::bitcoin; use liana_ui::{ + color, component::{button, card, text::*}, icon, theme, widget::*, @@ -13,32 +17,68 @@ use liana_ui::{ use super::message::Message; -pub fn receive<'a>(address: &'a bitcoin::Address, qr: &'a qr_code::State) -> Element<'a, Message> { +pub fn receive<'a>( + addresses: &'a [bitcoin::Address], + qr: Option<&'a qr_code::State>, +) -> Element<'a, Message> { Column::new() - .push(card::simple( - Column::new() - .push(QRCode::new(qr).cell_size(10)) - .push( - Row::new() - .push(text(address.to_string()).small()) - .push( - Button::new(icon::clipboard_icon()) - .on_press(Message::Clipboard(address.to_string())) - .style(theme::Button::TransparentBorder), - ) - .align_items(Alignment::Center), - ) - .align_items(Alignment::Center) - .spacing(20), - )) .push( - Column::new().push( - button::primary(None, "Generate new") - .on_press(Message::Next) - .width(Length::Units(150)), - ), + Row::new() + .align_items(Alignment::Center) + .push(Container::new(h3("Receive")).width(Length::Fill)) + .push( + button::primary(Some(icon::plus_icon()), "Generate address") + .on_press(Message::Next), + ), + ) + .push(p1_bold("New and never used reception addresses")) + .push( + Row::new() + .spacing(10) + .push(addresses.iter().rev().fold( + Column::new().spacing(10).width(Length::Fill), + |col, address| { + col.push( + card::simple( + Row::new() + .push( + Container::new( + scrollable( + Column::new() + .push(Space::with_height(Length::Units(10))) + .push( + p2_regular(address.to_string()) + .small() + .style(color::GREY_3), + ) + // Space between the address and the scrollbar + .push(Space::with_height(Length::Units(10))), + ) + .horizontal_scroll( + scrollable::Properties::new().scroller_width(5), + ), + ) + .width(Length::Fill), + ) + .push( + Button::new(icon::clipboard_icon().style(color::GREY_3)) + .on_press(Message::Clipboard(address.to_string())) + .style(theme::Button::TransparentBorder), + ) + .align_items(Alignment::Center), + ) + .padding(20), + ) + }, + )) + .push(if let Some(qr) = qr { + Container::new(QRCode::new(qr).cell_size(5)) + .padding(10) + .style(theme::Container::QrCode) + } else { + Container::new(Space::with_width(Length::Fill)).width(Length::Units(200)) + }), ) .spacing(20) - .align_items(Alignment::Center) .into() } diff --git a/gui/ui/src/theme.rs b/gui/ui/src/theme.rs index f42c72cc..5c806362 100644 --- a/gui/ui/src/theme.rs +++ b/gui/ui/src/theme.rs @@ -93,6 +93,7 @@ pub enum Container { Badge(Badge), Pill(Pill), Custom(iced::Color), + QrCode, } impl container::StyleSheet for Theme { @@ -125,6 +126,11 @@ impl container::StyleSheet for Theme { background: (*c).into(), ..container::Appearance::default() }, + Container::QrCode => container::Appearance { + background: color::WHITE.into(), + border_radius: 25.0, + ..container::Appearance::default() + }, }, Theme::Dark => match style { Container::Transparent => container::Appearance { @@ -152,6 +158,11 @@ impl container::StyleSheet for Theme { background: (*c).into(), ..container::Appearance::default() }, + Container::QrCode => container::Appearance { + background: color::WHITE.into(), + border_radius: 25.0, + ..container::Appearance::default() + }, }, } }