diff --git a/assets/icons/qr.svg b/assets/icons/qr.svg new file mode 100644 index 0000000..a887abe --- /dev/null +++ b/assets/icons/qr.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/components/caption_text.rs b/src/components/caption_text.rs new file mode 100644 index 0000000..347cc42 --- /dev/null +++ b/src/components/caption_text.rs @@ -0,0 +1,17 @@ +use iced::widget::text; +use iced::widget::text::Style; +use iced::{Element, Theme}; + +use crate::Message; + +use super::lighten; + +pub fn h_caption_text(string: &'static str) -> Element<'static, Message> { + text(string) + .size(18) + .style(|theme: &Theme| { + let gray = lighten(theme.palette().background, 0.5); + Style { color: Some(gray) } + }) + .into() +} diff --git a/src/components/icon.rs b/src/components/icon.rs index 38f35b4..3960839 100644 --- a/src/components/icon.rs +++ b/src/components/icon.rs @@ -12,6 +12,7 @@ pub enum SvgIcon { UpRight, Copy, Plus, + Qr, } pub fn map_icon(icon: SvgIcon) -> Svg<'static, Theme> { @@ -27,5 +28,6 @@ pub fn map_icon(icon: SvgIcon) -> Svg<'static, Theme> { SvgIcon::UpRight => Svg::from_path("assets/icons/up_right.svg"), SvgIcon::Copy => Svg::from_path("assets/icons/copy.svg"), SvgIcon::Plus => Svg::from_path("assets/icons/plus.svg"), + SvgIcon::Qr => Svg::from_path("assets/icons/qr.svg"), } } diff --git a/src/components/mod.rs b/src/components/mod.rs index 8823376..222cb86 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -24,3 +24,6 @@ pub use spinner::*; mod transaction_item; pub use transaction_item::*; + +mod caption_text; +pub use caption_text::*; diff --git a/src/main.rs b/src/main.rs index 94ada4e..239a5be 100644 --- a/src/main.rs +++ b/src/main.rs @@ -69,6 +69,13 @@ enum UnlockStatus { Unlocking, } +#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] +pub enum ReceiveMethod { + #[default] + Lightning, + OnChain, +} + #[derive(Debug, Clone)] pub enum Message { // Setup @@ -84,6 +91,7 @@ pub enum Message { MintInviteCodeInputChanged(String), DonateAmountChanged(String), CopyToClipboard(String), + ReceiveMethodChanged(ReceiveMethod), // Async commands we fire from the UI to core Noop, Send(String), @@ -118,6 +126,7 @@ pub struct HarborWallet { receive_invoice: Option, receive_address: Option
, receive_qr_data: Option, + receive_method: ReceiveMethod, mint_invite_code_str: String, add_federation_failure_reason: Option, donate_amount_str: String, @@ -245,6 +254,10 @@ impl HarborWallet { self.receive_status = ReceiveStatus::Idle; Command::none() } + Message::ReceiveMethodChanged(method) => { + self.receive_method = method; + Command::none() + } // Async commands we fire from the UI to core Message::Noop => Command::none(), Message::Send(invoice_str) => match self.send_status { diff --git a/src/routes/receive.rs b/src/routes/receive.rs index 03e129b..253cbb2 100644 --- a/src/routes/receive.rs +++ b/src/routes/receive.rs @@ -1,12 +1,42 @@ use iced::widget::container::Style; -use iced::widget::{column, container, qr_code, scrollable, text}; +use iced::widget::{column, container, qr_code, radio, scrollable, text}; use iced::{Border, Element, Font, Padding}; use iced::{Color, Length}; -use crate::components::{h_button, h_header, h_input, SvgIcon}; -use crate::{HarborWallet, Message, ReceiveStatus}; +use crate::components::{h_button, h_caption_text, h_header, h_input, SvgIcon}; +use crate::{HarborWallet, Message, ReceiveMethod, ReceiveStatus}; pub fn receive(harbor: &HarborWallet) -> Element { + let lightning_choice = radio( + "Lightning", + ReceiveMethod::Lightning, + Some(harbor.receive_method), + Message::ReceiveMethodChanged, + ) + .text_size(18); + + let lightning_caption = h_caption_text("Good for small amounts. Instant settlement, low fees."); + + let lightning = column![lightning_choice, lightning_caption,].spacing(8); + + let onchain_choice = radio( + "On-chain", + ReceiveMethod::OnChain, + Some(harbor.receive_method), + Message::ReceiveMethodChanged, + ) + .text_size(18); + + let onchain_caption = h_caption_text( + "Good for large amounts. Requires on-chain fees and 10 block confirmations.", + ); + + let onchain = column![onchain_choice, onchain_caption,].spacing(8); + + let method_choice_label = text("Receive method").size(24); + + let method_choice = column![method_choice_label, lightning, onchain].spacing(16); + let receive_string = harbor .receive_invoice .as_ref() @@ -70,21 +100,20 @@ pub fn receive(harbor: &HarborWallet) -> Element { Some("sats"), ); - // TODO how to separate lighting and onchain? let generating = harbor.receive_status == ReceiveStatus::Generating; - let generate_button = h_button("Generate Invoice", SvgIcon::DownLeft, generating) + let generate_button = h_button("Generate Invoice", SvgIcon::Qr, generating) .on_press(Message::GenerateInvoice); - let generate_address_button = h_button("Generate Address", SvgIcon::Squirrel, generating) + let generate_address_button = h_button("Generate Address", SvgIcon::Qr, generating) .on_press(Message::GenerateAddress); - column![ - header, - amount_input, - generate_button, - generate_address_button - ] + match harbor.receive_method { + ReceiveMethod::Lightning => { + column![header, method_choice, amount_input, generate_button] + } + ReceiveMethod::OnChain => column![header, method_choice, generate_address_button], + } }; container(scrollable(