From 1d1a28195527cc04ce99969e5c85d2632402d73e Mon Sep 17 00:00:00 2001 From: edouardparis Date: Fri, 23 May 2025 15:48:13 +0200 Subject: [PATCH 1/2] Revert "gui: store SignModal state and allow to open export modal after signing in PSBT panel" This reverts commit 7281e6352967009419a493ccd3825887001afa14. --- liana-gui/src/app/state/psbt.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/liana-gui/src/app/state/psbt.rs b/liana-gui/src/app/state/psbt.rs index ab1bdc2e..0245e160 100644 --- a/liana-gui/src/app/state/psbt.rs +++ b/liana-gui/src/app/state/psbt.rs @@ -92,9 +92,6 @@ pub struct PsbtState { pub warning: Option, pub labels_edited: LabelsEdited, pub modal: Option, - // NOTE: sign_modal is used to store state of SignModal - // when another modal is selected - pub sign_modal: Option, } impl PsbtState { @@ -105,7 +102,6 @@ impl PsbtState { labels_edited: LabelsEdited::default(), warning: None, modal: None, - sign_modal: None, tx, saved, } @@ -169,19 +165,19 @@ impl PsbtState { } } Message::View(view::Message::Spend(view::SpendTxMessage::Cancel)) => { - if matches!(self.modal, Some(PsbtModal::Sign(_))) { - // store SignModal state - self.sign_modal = self.modal.take(); + if let Some(PsbtModal::Sign(SignModal { display_modal, .. })) = &mut self.modal { + *display_modal = false; + return Task::none(); } + self.modal = None; } Message::View(view::Message::Spend(view::SpendTxMessage::Delete)) => { self.modal = Some(PsbtModal::Delete(DeleteModal::default())); } Message::View(view::Message::Spend(view::SpendTxMessage::Sign)) => { - if self.sign_modal.is_some() { - // restore SignModal state - self.modal = self.sign_modal.take(); + if let Some(PsbtModal::Sign(SignModal { display_modal, .. })) = &mut self.modal { + *display_modal = true; return Task::none(); } @@ -487,6 +483,7 @@ impl Modal for SignModal { .. }) = self.hws.list.get(i) { + self.display_modal = false; self.signing.insert(*fingerprint); let psbt = tx.psbt.clone(); let fingerprint = *fingerprint; @@ -561,7 +558,7 @@ impl Modal for SignModal { Task::none() } fn view<'a>(&'a self, content: Element<'a, view::Message>) -> Element<'a, view::Message> { - let content: Element<'a, view::Message> = toast::Manager::new( + let content = toast::Manager::new( content, view::psbt::sign_action_toasts(self.error.as_ref(), &self.hws.list, &self.signing), ) From 874d2d406804b853e399800435bb0ee223d5d769 Mon Sep 17 00:00:00 2001 From: edouardparis Date: Fri, 23 May 2025 16:56:20 +0200 Subject: [PATCH 2/2] Make user finish sign process before opening new modal --- liana-gui/src/app/state/psbt.rs | 33 +++++++++++++++++++++++---- liana-gui/src/app/state/spend/step.rs | 5 ++++ liana-gui/src/app/view/psbt.rs | 33 +++++++++++++++++++++++---- liana-gui/src/app/view/spend/mod.rs | 26 +++++++++++++++++---- 4 files changed, 84 insertions(+), 13 deletions(-) diff --git a/liana-gui/src/app/state/psbt.rs b/liana-gui/src/app/state/psbt.rs index 0245e160..83e3971f 100644 --- a/liana-gui/src/app/state/psbt.rs +++ b/liana-gui/src/app/state/psbt.rs @@ -165,9 +165,16 @@ impl PsbtState { } } Message::View(view::Message::Spend(view::SpendTxMessage::Cancel)) => { - if let Some(PsbtModal::Sign(SignModal { display_modal, .. })) = &mut self.modal { - *display_modal = false; - return Task::none(); + if let Some(PsbtModal::Sign(SignModal { + display_modal, + signing, + .. + })) = &mut self.modal + { + if !signing.is_empty() { + *display_modal = false; + return Task::none(); + } } self.modal = None; @@ -231,7 +238,15 @@ impl PsbtState { Message::Updated(Ok(_)) => { self.saved = true; if let Some(modal) = self.modal.as_mut() { - return modal.as_mut().update(daemon.clone(), message, &mut self.tx); + let cmd = modal.as_mut().update(daemon.clone(), message, &mut self.tx); + // if modal is only the pending notif then we remove it once the psbt was + // updated. + if let PsbtModal::Sign(SignModal { display_modal, .. }) = modal { + if !*display_modal { + self.modal = None; + } + } + return cmd; } } Message::BroadcastModal(res) => match res { @@ -271,6 +286,11 @@ impl PsbtState { &self.wallet.keys_aliases, self.labels_edited.cache(), cache.network, + if let Some(PsbtModal::Sign(m)) = &self.modal { + m.is_signing() + } else { + false + }, self.warning.as_ref(), ); if let Some(modal) = &self.modal { @@ -462,6 +482,10 @@ impl SignModal { recovery_timelock, } } + + pub fn is_signing(&self) -> bool { + !self.signing.is_empty() + } } impl Modal for SignModal { @@ -503,6 +527,7 @@ impl Modal for SignModal { self.signing.remove(&fingerprint); match res { Err(e) => { + self.display_modal = true; if !matches!(e, Error::HardwareWallet(async_hwi::Error::UserRefused)) { self.error = Some(e) } diff --git a/liana-gui/src/app/state/spend/step.rs b/liana-gui/src/app/state/spend/step.rs index 510a20e8..b34a4f6e 100644 --- a/liana-gui/src/app/state/spend/step.rs +++ b/liana-gui/src/app/state/spend/step.rs @@ -1018,6 +1018,11 @@ impl Step for SaveSpend { &psbt_state.wallet.keys_aliases, psbt_state.labels_edited.cache(), cache.network, + if let Some(psbt::PsbtModal::Sign(m)) = &psbt_state.modal { + m.is_signing() + } else { + false + }, psbt_state.warning.as_ref(), ); if let Some(modal) = &psbt_state.modal { diff --git a/liana-gui/src/app/view/psbt.rs b/liana-gui/src/app/view/psbt.rs index aaf34281..d3091395 100644 --- a/liana-gui/src/app/view/psbt.rs +++ b/liana-gui/src/app/view/psbt.rs @@ -46,6 +46,7 @@ pub fn psbt_view<'a>( key_aliases: &'a HashMap, labels_editing: &'a HashMap>, network: Network, + currently_signing: bool, warning: Option<&Error>, ) -> Element<'a, Message> { dashboard( @@ -72,7 +73,12 @@ pub fn psbt_view<'a>( }), ) .push(spend_header(tx, labels_editing)) - .push(spend_overview_view(tx, desc_info, key_aliases)) + .push(spend_overview_view( + tx, + desc_info, + key_aliases, + currently_signing, + )) .push( Column::new() .spacing(20) @@ -96,7 +102,11 @@ pub fn psbt_view<'a>( .push( button::secondary(None, "Delete") .width(Length::Fixed(200.0)) - .on_press(Message::Spend(SpendTxMessage::Delete)), + .on_press_maybe(if currently_signing { + None + } else { + Some(Message::Spend(SpendTxMessage::Delete)) + }), ) .width(Length::Fill) } else { @@ -105,7 +115,11 @@ pub fn psbt_view<'a>( .push( button::secondary(None, "Save") .width(Length::Fixed(150.0)) - .on_press(Message::Spend(SpendTxMessage::Save)), + .on_press_maybe(if currently_signing { + None + } else { + Some(Message::Spend(SpendTxMessage::Save)) + }), ) .width(Length::Fill) }) @@ -321,6 +335,7 @@ pub fn spend_overview_view<'a>( tx: &'a SpendTx, desc_info: &'a LianaPolicy, key_aliases: &'a HashMap, + currently_signing: bool, ) -> Element<'a, Message> { Column::new() .spacing(20) @@ -343,14 +358,22 @@ pub fn spend_overview_view<'a>( Some(icon::backup_icon()), "Export", ) - .on_press(Message::ExportPsbt), + .on_press_maybe(if currently_signing { + None + } else { + Some(Message::ExportPsbt) + }), ) .push( button::secondary( Some(icon::restore_icon()), "Import", ) - .on_press(Message::ImportPsbt), + .on_press_maybe(if currently_signing { + None + } else { + Some(Message::ImportPsbt) + }), ), ) .align_y(Alignment::Center), diff --git a/liana-gui/src/app/view/spend/mod.rs b/liana-gui/src/app/view/spend/mod.rs index 06b24ed4..93446284 100644 --- a/liana-gui/src/app/view/spend/mod.rs +++ b/liana-gui/src/app/view/spend/mod.rs @@ -37,6 +37,7 @@ pub fn spend_view<'a>( key_aliases: &'a HashMap, labels_editing: &'a HashMap>, network: Network, + currently_signing: bool, warning: Option<&Error>, ) -> Element<'a, Message> { let is_recovery = tx @@ -75,7 +76,12 @@ pub fn spend_view<'a>( }, )) }) - .push(psbt::spend_overview_view(tx, desc_info, key_aliases)) + .push(psbt::spend_overview_view( + tx, + desc_info, + key_aliases, + currently_signing, + )) .push( Column::new() .spacing(20) @@ -99,7 +105,11 @@ pub fn spend_view<'a>( .push( button::secondary(None, "Delete") .width(Length::Fixed(200.0)) - .on_press(Message::Spend(SpendTxMessage::Delete)), + .on_press_maybe(if currently_signing { + None + } else { + Some(Message::Spend(SpendTxMessage::Delete)) + }), ) .width(Length::Fill) } else { @@ -107,13 +117,21 @@ pub fn spend_view<'a>( .push( button::secondary(None, "< Previous") .width(Length::Fixed(150.0)) - .on_press(Message::Previous), + .on_press_maybe(if currently_signing { + None + } else { + Some(Message::Previous) + }), ) .push(Space::with_width(Length::Fill)) .push( button::secondary(None, "Save") .width(Length::Fixed(150.0)) - .on_press(Message::Spend(SpendTxMessage::Save)), + .on_press_maybe(if currently_signing { + None + } else { + Some(Message::Spend(SpendTxMessage::Save)) + }), ) .width(Length::Fill) }),