diff --git a/liana-gui/src/app/message.rs b/liana-gui/src/app/message.rs index d0ae6af56..5bd1fa476 100644 --- a/liana-gui/src/app/message.rs +++ b/liana-gui/src/app/message.rs @@ -14,6 +14,8 @@ use crate::{ hw::HardwareWalletMessage, }; +use super::state::export::ExportMessage; + #[derive(Debug)] pub enum Message { Tick, @@ -43,4 +45,5 @@ pub enum Message { LabelsUpdated(Result>, Error>), BroadcastModal(Result, Error>), RbfModal(Box, bool, Result, Error>), + Export(ExportMessage), } diff --git a/liana-gui/src/app/mod.rs b/liana-gui/src/app/mod.rs index 3a0f553b8..6d6536fde 100644 --- a/liana-gui/src/app/mod.rs +++ b/liana-gui/src/app/mod.rs @@ -6,7 +6,6 @@ pub mod settings; pub mod state; pub mod view; pub mod wallet; -pub mod export; mod error; diff --git a/liana-gui/src/app/state/export.rs b/liana-gui/src/app/state/export.rs index 46ec1672a..65ac42781 100644 --- a/liana-gui/src/app/state/export.rs +++ b/liana-gui/src/app/state/export.rs @@ -135,8 +135,6 @@ impl ExportModal { if let Some(handle) = self.handle.take() { handle.lock().expect("poisoined").abort(); self.state = state; - } else { - log::warn!("no handle !!!!!!!!!!!!!!!!!!!!!!!!"); } } diff --git a/liana-gui/src/app/state/mod.rs b/liana-gui/src/app/state/mod.rs index cda029120..f5ce8619d 100644 --- a/liana-gui/src/app/state/mod.rs +++ b/liana-gui/src/app/state/mod.rs @@ -1,4 +1,5 @@ mod coins; +pub mod export; mod label; mod psbt; mod psbts; diff --git a/liana-gui/src/app/state/transactions.rs b/liana-gui/src/app/state/transactions.rs index 8a7c334af..34e102457 100644 --- a/liana-gui/src/app/state/transactions.rs +++ b/liana-gui/src/app/state/transactions.rs @@ -35,13 +35,22 @@ use crate::daemon::{ Daemon, }; +use super::export::{ExportMessage, ExportModal}; + +#[derive(Debug)] +pub enum TransactionsModal { + CreateRbf(CreateRbfModal), + Export(ExportModal), + None, +} + pub struct TransactionsPanel { wallet: Arc, txs: Vec, labels_edited: LabelsEdited, selected_tx: Option, warning: Option, - create_rbf_modal: Option, + modal: TransactionsModal, is_last_page: bool, processing: bool, } @@ -54,7 +63,7 @@ impl TransactionsPanel { txs: Vec::new(), labels_edited: LabelsEdited::default(), warning: None, - create_rbf_modal: None, + modal: TransactionsModal::None, is_last_page: false, processing: false, } @@ -63,7 +72,7 @@ impl TransactionsPanel { pub fn preselect(&mut self, tx: HistoryTransaction) { self.selected_tx = Some(tx); self.warning = None; - self.create_rbf_modal = None; + self.modal = TransactionsModal::None; } } @@ -76,19 +85,22 @@ impl State for TransactionsPanel { self.labels_edited.cache(), self.warning.as_ref(), ); - if let Some(modal) = &self.create_rbf_modal { - modal.view(content) - } else { - content + match &self.modal { + TransactionsModal::CreateRbf(rbf) => rbf.view(content), + _ => content, } } else { - view::transactions::transactions_view( + let content = view::transactions::transactions_view( cache, &self.txs, self.warning.as_ref(), self.is_last_page, self.processing, - ) + ); + match &self.modal { + TransactionsModal::Export(export) => export.view(content), + _ => content, + } } } @@ -134,7 +146,7 @@ impl State for TransactionsPanel { Message::RbfModal(tx, is_cancel, res) => match res { Ok(descendant_txids) => { let modal = CreateRbfModal::new(*tx, is_cancel, descendant_txids); - self.create_rbf_modal = Some(modal); + self.modal = TransactionsModal::CreateRbf(modal); } Err(e) => { self.warning = e.into(); @@ -146,16 +158,16 @@ impl State for TransactionsPanel { Message::View(view::Message::Select(i)) => { self.selected_tx = self.txs.get(i).cloned(); // Clear modal if it's for a different tx. - if let Some(modal) = &self.create_rbf_modal { + if let TransactionsModal::CreateRbf(modal) = &self.modal { if Some(modal.tx.tx.txid()) != self.selected_tx.as_ref().map(|selected| selected.tx.txid()) { - self.create_rbf_modal = None; + self.modal = TransactionsModal::None; } } } Message::View(view::Message::CreateRbf(view::CreateRbfMessage::Cancel)) => { - self.create_rbf_modal = None; + self.modal = TransactionsModal::None; } Message::View(view::Message::CreateRbf(view::CreateRbfMessage::New(is_cancel))) => { if let Some(tx) = &self.selected_tx { @@ -246,11 +258,27 @@ impl State for TransactionsPanel { ); } } - _ => { - if let Some(modal) = &mut self.create_rbf_modal { - return modal.update(daemon, _cache, message); + Message::View(view::Message::Export(ExportMessage::Open)) => { + if let TransactionsModal::None = &self.modal { + self.modal = TransactionsModal::Export(ExportModal::new(daemon)); + if let TransactionsModal::Export(m) = &mut self.modal { + return m.launch(); + } } } + Message::View(view::Message::Export(ExportMessage::Close)) => { + // Message::Export(ExportMessage::Close) => { + if let TransactionsModal::Export(_) = &self.modal { + self.modal = TransactionsModal::None; + } + } + _ => { + return match &mut self.modal { + TransactionsModal::CreateRbf(modal) => modal.update(daemon, _cache, message), + TransactionsModal::Export(modal) => modal.update(message), + TransactionsModal::None => Command::none(), + }; + } }; Command::none() } @@ -281,6 +309,17 @@ impl State for TransactionsPanel { Message::HistoryTransactions, )]) } + + fn subscription(&self) -> iced::Subscription { + if let TransactionsModal::Export(modal) = &self.modal { + if let Some(sub) = modal.subscription() { + return sub.map(|m| { + Message::View(view::Message::Export(ExportMessage::ExportProgress(m))) + }); + } + } + iced::Subscription::none() + } } impl From for Box { @@ -289,6 +328,7 @@ impl From for Box { } } +#[derive(Debug)] pub struct CreateRbfModal { /// Transaction to replace. tx: model::HistoryTransaction, diff --git a/liana-gui/src/app/view/message.rs b/liana-gui/src/app/view/message.rs index c726b5fc5..9cb033185 100644 --- a/liana-gui/src/app/view/message.rs +++ b/liana-gui/src/app/view/message.rs @@ -1,4 +1,7 @@ -use crate::{app::menu::Menu, node::bitcoind::RpcAuthType}; +use crate::{ + app::{menu::Menu, state::export::ExportMessage}, + node::bitcoind::RpcAuthType, +}; use liana::miniscript::bitcoin::bip32::Fingerprint; #[derive(Debug, Clone)] @@ -19,6 +22,7 @@ pub enum Message { SelectHardwareWallet(usize), CreateRbf(CreateRbfMessage), ShowQrCode(usize), + Export(ExportMessage), } #[derive(Debug, Clone)] diff --git a/liana-gui/src/app/view/mod.rs b/liana-gui/src/app/view/mod.rs index 66e25af41..d6ba29ee7 100644 --- a/liana-gui/src/app/view/mod.rs +++ b/liana-gui/src/app/view/mod.rs @@ -3,6 +3,7 @@ mod message; mod warning; pub mod coins; +pub mod export; pub mod home; pub mod hw; pub mod psbt; diff --git a/liana-gui/src/app/view/transactions.rs b/liana-gui/src/app/view/transactions.rs index dc51f9193..032f6cb95 100644 --- a/liana-gui/src/app/view/transactions.rs +++ b/liana-gui/src/app/view/transactions.rs @@ -1,7 +1,11 @@ use std::collections::{HashMap, HashSet}; use chrono::{DateTime, Local, Utc}; -use iced::{alignment, widget::tooltip, Alignment, Length}; +use iced::{ + alignment, + widget::{tooltip, Space}, + Alignment, Length, +}; use liana_ui::{ color, @@ -15,7 +19,12 @@ use crate::{ cache::Cache, error::Error, menu::Menu, - view::{dashboard, label, message::CreateRbfMessage, message::Message, warning::warn}, + state::export::ExportMessage, + view::{ + dashboard, label, + message::{CreateRbfMessage, Message}, + warning::warn, + }, }, daemon::model::{HistoryTransaction, Txid}, }; @@ -32,7 +41,16 @@ pub fn transactions_view<'a>( cache, warning, Column::new() - .push(Container::new(h3("Transactions")).width(Length::Fill)) + .push( + Row::new() + .push(Container::new(h3("Transactions"))) + .push(Space::with_width(Length::Fill)) + .push( + Button::new("Export") + .on_press(ExportMessage::Open.into()) + .style(theme::Button::Secondary), + ), + ) .push( Column::new() .spacing(10)