notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit c2fbcaa5eb3125381097099c6723c3a83cd5768a
parent 1ce530faec8d04625722d7586b4eb93093b64a7d
Author: kernelkind <kernelkind@gmail.com>
Date:   Sat, 15 Mar 2025 12:31:19 -0400

add wallet ui

Signed-off-by: kernelkind <kernelkind@gmail.com>

Diffstat:
Mcrates/notedeck_columns/src/ui/wallet.rs | 140++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 139 insertions(+), 1 deletion(-)

diff --git a/crates/notedeck_columns/src/ui/wallet.rs b/crates/notedeck_columns/src/ui/wallet.rs @@ -1,7 +1,10 @@ -use notedeck::{Accounts, GlobalWallet, Wallet, WalletError, WalletUIState}; +use egui::Layout; +use notedeck::{Accounts, GlobalWallet, Wallet, WalletError, WalletState, WalletUIState}; use crate::route::{Route, Router}; +use super::widgets::styled_button; + #[derive(Debug)] pub enum WalletAction { SaveURI, @@ -70,6 +73,36 @@ impl WalletAction { } } +pub struct WalletView<'a> { + state: WalletState<'a>, +} + +impl<'a> WalletView<'a> { + pub fn new(state: WalletState<'a>) -> Self { + Self { state } + } + + pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<WalletAction> { + egui::Frame::NONE + .inner_margin(egui::Margin::same(8)) + .show(ui, |ui| self.inner_ui(ui)) + .inner + } + + fn inner_ui(&mut self, ui: &mut egui::Ui) -> Option<WalletAction> { + match &mut self.state { + WalletState::Wallet { + wallet, + can_create_local_wallet, + } => show_with_wallet(ui, wallet, *can_create_local_wallet), + WalletState::NoWallet { + state, + show_local_only, + } => show_no_wallet(ui, state, *show_local_only), + } + } +} + fn try_create_wallet(state: &mut WalletUIState) -> Option<Wallet> { let uri = &state.buf; @@ -81,3 +114,108 @@ fn try_create_wallet(state: &mut WalletUIState) -> Option<Wallet> { *state = WalletUIState::default(); Some(wallet) } + +fn show_no_wallet( + ui: &mut egui::Ui, + state: &mut WalletUIState, + show_local_only: bool, +) -> Option<WalletAction> { + ui.horizontal_wrapped(|ui| 's: { + let text_edit = egui::TextEdit::singleline(&mut state.buf) + .hint_text( + egui::RichText::new("Paste your NWC URI here...") + .text_style(notedeck::NotedeckTextStyle::Body.text_style()), + ) + .vertical_align(egui::Align::Center) + .desired_width(f32::INFINITY) + .min_size(egui::Vec2::new(0.0, 40.0)) + .margin(egui::Margin::same(12)) + .password(true); + + ui.add(text_edit); + + let Some(error_msg) = &state.error_msg else { + break 's; + }; + + match error_msg { + WalletError::InvalidURI => { + ui.colored_label(ui.visuals().warn_fg_color, "Invalid NWC URI") + } + }; + }); + + ui.add_space(8.0); + + if show_local_only { + ui.checkbox( + &mut state.for_local_only, + "Use this wallet for the current account only", + ); + ui.add_space(8.0); + } + + ui.with_layout(Layout::top_down(egui::Align::Center), |ui| { + ui.add(styled_button("Add Wallet", crate::colors::PINK)) + .clicked() + .then_some(WalletAction::SaveURI) + }) + .inner +} + +fn show_with_wallet( + ui: &mut egui::Ui, + wallet: &mut Wallet, + can_create_local_wallet: bool, +) -> Option<WalletAction> { + ui.horizontal_wrapped(|ui| { + let balance = wallet.get_balance(); + + if let Some(balance) = balance { + match balance { + Ok(msats) => show_balance(ui, *msats), + Err(e) => ui.colored_label(egui::Color32::RED, format!("error: {e}")), + } + } else { + ui.with_layout(Layout::top_down(egui::Align::Center), |ui| { + ui.add(egui::Spinner::new().size(48.0)) + }) + .inner + } + }); + + ui.with_layout(Layout::bottom_up(egui::Align::Min), |ui| 's: { + if ui + .add(styled_button("Delete Wallet", ui.visuals().window_fill)) + .clicked() + { + break 's Some(WalletAction::Delete); + } + + ui.add_space(12.0); + if can_create_local_wallet + && ui + .checkbox( + &mut false, + "Add a different wallet that will only be used for this account", + ) + .clicked() + { + break 's Some(WalletAction::AddLocalOnly); + } + + None + }) + .inner +} + +fn show_balance(ui: &mut egui::Ui, msats: u64) -> egui::Response { + let sats = human_format::Formatter::new() + .with_decimals(2) + .format(msats as f64 / 1000.0); + + ui.with_layout(Layout::top_down(egui::Align::Center), |ui| { + ui.label(egui::RichText::new(format!("{sats} sats")).size(48.0)) + }) + .inner +}