From 541aa199db27c86d713ba1ee18401e1ffeef10f0 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 14 May 2024 15:14:52 -0500 Subject: [PATCH] add mint screen --- assets/icons/heart.svg | 2 +- assets/icons/plus.svg | 4 ++++ src/bridge.rs | 8 ++++++- src/components/icon.rs | 2 ++ src/core.rs | 2 ++ src/main.rs | 44 +++++++++++++++++++++++++++++++----- src/routes/mints.rs | 51 +++++++++++++++++++++++++++++++----------- 7 files changed, 93 insertions(+), 20 deletions(-) create mode 100644 assets/icons/plus.svg diff --git a/assets/icons/heart.svg b/assets/icons/heart.svg index 34bc29a..5e162ca 100644 --- a/assets/icons/heart.svg +++ b/assets/icons/heart.svg @@ -1,3 +1,3 @@ - + diff --git a/assets/icons/plus.svg b/assets/icons/plus.svg new file mode 100644 index 0000000..5a913db --- /dev/null +++ b/assets/icons/plus.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/bridge.rs b/src/bridge.rs index 746ab59..5036c2b 100644 --- a/src/bridge.rs +++ b/src/bridge.rs @@ -35,6 +35,7 @@ pub enum CoreUIMsg { ReceiveFailed(String), BalanceUpdated(Amount), AddFederationFailed(String), + AddFederationSuccess, Unlocking, UnlockSuccess, UnlockFailed(String), @@ -61,12 +62,17 @@ impl UIHandle { } pub async fn receive(&self, amount: u64) { - self.msg_send(UICoreMsg::ReceiveLightning(Amount::from_sats(amount))).await; + self.msg_send(UICoreMsg::ReceiveLightning(Amount::from_sats(amount))) + .await; } pub async fn unlock(&self, password: String) { self.msg_send(UICoreMsg::Unlock(password)).await; } + + pub async fn add_federation(&self, invite: InviteCode) { + self.msg_send(UICoreMsg::AddFederation(invite)).await; + } } impl CoreHandle { diff --git a/src/components/icon.rs b/src/components/icon.rs index a75ced3..38f35b4 100644 --- a/src/components/icon.rs +++ b/src/components/icon.rs @@ -11,6 +11,7 @@ pub enum SvgIcon { Squirrel, UpRight, Copy, + Plus, } pub fn map_icon(icon: SvgIcon) -> Svg<'static, Theme> { @@ -25,5 +26,6 @@ pub fn map_icon(icon: SvgIcon) -> Svg<'static, Theme> { SvgIcon::Squirrel => Svg::from_path("assets/icons/squirrel.svg"), 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"), } } diff --git a/src/core.rs b/src/core.rs index 3bb4fba..7baa9f1 100644 --- a/src/core.rs +++ b/src/core.rs @@ -263,6 +263,8 @@ pub fn run_core() -> Subscription { error!("Error adding federation: {e}"); core.msg(CoreUIMsg::AddFederationFailed(e.to_string())) .await; + } else { + core.msg(CoreUIMsg::AddFederationSuccess).await; } } // TODO: actually use this to unlock diff --git a/src/main.rs b/src/main.rs index 08aae99..4e61ff8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ use core::run_core; +use fedimint_core::api::InviteCode; use fedimint_core::Amount; use fedimint_ln_common::lightning_invoice::Bolt11Invoice; use iced::widget::qr_code::Data; @@ -63,6 +64,8 @@ pub struct HarborWallet { receive_amount_str: String, receive_invoice: Option, receive_qr_data: Option, + mint_invite_code_str: String, + add_federation_failure_reason: Option, } impl Default for HarborWallet { @@ -105,6 +108,7 @@ pub enum Message { SendDestInputChanged(String), SendAmountInputChanged(String), PasswordInputChanged(String), + MintInviteCodeInputChanged(String), CopyToClipboard(String), // Async commands we fire from the UI to core Noop, @@ -112,6 +116,7 @@ pub enum Message { Receive(u64), GenerateInvoice, Unlock(String), + AddFederation(String), // Core messages we get from core CoreMessage(CoreUIMsg), } @@ -135,6 +140,8 @@ impl HarborWallet { receive_status: ReceiveStatus::Idle, receive_invoice: None, receive_qr_data: None, + mint_invite_code_str: String::new(), + add_federation_failure_reason: None, } } @@ -143,9 +150,7 @@ impl HarborWallet { } async fn async_send(ui_handle: Option>, invoice: Bolt11Invoice) { - println!("Got to async_send"); if let Some(ui_handle) = ui_handle { - println!("Have a ui_handle, sending the invoice over"); ui_handle.clone().send(invoice).await; } else { panic!("UI handle is None"); @@ -168,6 +173,14 @@ impl HarborWallet { } } + async fn async_add_federation(ui_handle: Option>, invite: InviteCode) { + if let Some(ui_handle) = ui_handle { + ui_handle.clone().add_federation(invite).await; + } else { + panic!("UI handle is None"); + } + } + fn update(&mut self, message: Message) -> Command { match message { // Setup @@ -205,6 +218,10 @@ impl HarborWallet { self.password_input_str = input; Command::none() } + Message::MintInviteCodeInputChanged(input) => { + self.mint_invite_code_str = input; + Command::none() + } // Async commands we fire from the UI to core Message::Noop => Command::none(), Message::Send(invoice_str) => match self.send_status { @@ -257,6 +274,18 @@ impl HarborWallet { }) } }, + Message::AddFederation(invite_code) => { + let invite = InviteCode::from_str(&invite_code); + if let Ok(invite) = invite { + Command::perform( + Self::async_add_federation(self.ui_handle.clone(), invite), + |_| Message::Noop, + ) + } else { + self.add_federation_failure_reason = Some("Invalid invite code".to_string()); + Command::none() + } + } Message::CopyToClipboard(s) => { println!("Copying to clipboard: {s}"); clipboard::write(s) @@ -281,7 +310,7 @@ impl HarborWallet { info!("Receive success: {params:?}"); self.receive_status = ReceiveStatus::Idle; Command::none() - }, + } CoreUIMsg::ReceiveFailed(reason) => { self.receive_status = ReceiveStatus::Idle; self.receive_failure_reason = Some(reason); @@ -308,8 +337,12 @@ impl HarborWallet { self.receive_invoice = Some(invoice); Command::none() } - CoreUIMsg::AddFederationFailed(_) => { - // todo show error + CoreUIMsg::AddFederationFailed(reason) => { + self.add_federation_failure_reason = Some(reason); + Command::none() + } + CoreUIMsg::AddFederationSuccess => { + self.mint_invite_code_str = String::new(); Command::none() } CoreUIMsg::Unlocking => { @@ -338,6 +371,7 @@ impl HarborWallet { Route::Home => row![sidebar, crate::routes::home(self)].into(), Route::Receive => row![sidebar, crate::routes::receive(self)].into(), Route::Send => row![sidebar, crate::routes::send(self)].into(), + Route::Mints => row![sidebar, crate::routes::mints(self)].into(), _ => row![sidebar, crate::routes::home(self)].into(), }; diff --git a/src/routes/mints.rs b/src/routes/mints.rs index 56c7a12..b09cb4c 100644 --- a/src/routes/mints.rs +++ b/src/routes/mints.rs @@ -1,18 +1,43 @@ -use iced::widget::{column, container, scrollable}; -use iced::Length; -use iced::{Alignment, Element}; +use iced::widget::{column, container, scrollable, text}; +use iced::{Color, Element}; +use iced::{Length, Padding}; +use crate::components::{h_button, h_header, h_input, SvgIcon}; use crate::{HarborWallet, Message}; -pub fn mints(_harbor: &HarborWallet) -> Element { - container( - scrollable( - column!["These are the mints!",] - .spacing(32) - .align_items(Alignment::Center) - .width(Length::Fill), - ) - .height(Length::Fill), - ) +pub fn mints(harbor: &HarborWallet) -> Element { + let header = h_header("Mints", "Manage your mints here."); + + let mint_input = h_input( + "Mint Invite Code", + "", + &harbor.mint_invite_code_str, + Message::MintInviteCodeInputChanged, + Message::Noop, + false, + None, + None, + ); + + let add_mint_button = h_button("Add Mint", SvgIcon::Plus) + .on_press(Message::AddFederation(harbor.mint_invite_code_str.clone())); + + let column = column![header, mint_input, add_mint_button].spacing(48); + + // TODO: better error styling + let column = column.push_maybe( + harbor + .add_federation_failure_reason + .as_ref() + .map(|r| text(r).size(18).color(Color::from_rgb8(255, 0, 0))), + ); + + container(scrollable( + column + .spacing(48) + .width(Length::Fill) + .max_width(512) + .padding(Padding::new(48.)), + )) .into() }