From 0f09be151ca3ba1353d23b170805c845fc8ab5cc Mon Sep 17 00:00:00 2001 From: Michael Mallan Date: Wed, 28 Aug 2024 16:18:20 +0100 Subject: [PATCH] gui(installer): don't change values while waiting for ping result --- gui/src/installer/step/node/mod.rs | 44 +++++++++++++++++++----------- gui/src/installer/view.rs | 12 ++++++-- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/gui/src/installer/step/node/mod.rs b/gui/src/installer/step/node/mod.rs index 984c0138..cb8b350d 100644 --- a/gui/src/installer/step/node/mod.rs +++ b/gui/src/installer/step/node/mod.rs @@ -87,6 +87,7 @@ impl NodeDefinition { pub struct Node { definition: NodeDefinition, is_running: Option>, + waiting_for_ping_result: bool, } impl Node { @@ -94,6 +95,7 @@ impl Node { Node { definition: NodeDefinition::new(node_type), is_running: None, + waiting_for_ping_result: false, } } } @@ -152,22 +154,18 @@ impl DefineNode { .find(|node| node.definition.node_type() == node_type) } - fn ping_selected(&self) -> Command { - let selected = self.selected().definition.clone(); - let node_type = selected.node_type(); - Command::perform(async move { selected.ping() }, move |res| { - Message::DefineNode(message::DefineNode::PingResult((node_type, res))) - }) - } - fn update_node( &mut self, node_type: NodeType, message: message::DefineNode, ) -> Command { if let Some(node) = self.get_mut(node_type) { - node.is_running = None; - return node.definition.update(message); + // Don't make changes while waiting for a ping result so that we + // know which values the ping result applies to. + if !node.waiting_for_ping_result { + node.is_running = None; + return node.definition.update(message); + } } Command::none() } @@ -192,12 +190,28 @@ impl Step for DefineNode { self.selected_node_type = node_type; } message::DefineNode::Ping => { - return self.ping_selected(); + let selected = self.selected_mut(); + // Make sure we don't send more than one ping request at a time + // so that we know which values the result applies to. + if !selected.waiting_for_ping_result { + selected.waiting_for_ping_result = true; + selected.is_running = None; + let def = selected.definition.clone(); + let node_type = def.node_type(); + return Command::perform(async move { def.ping() }, move |res| { + Message::DefineNode(message::DefineNode::PingResult((node_type, res))) + }); + } } message::DefineNode::PingResult((node_type, res)) => { // Result may not be for the selected node type. if let Some(node) = self.get_mut(node_type) { - node.is_running = Some(res); + // Make sure we're expecting the ping result. Otherwise, the user may have changed values + // and so the ping result may not apply to the current values. + if node.waiting_for_ping_result { + node.waiting_for_ping_result = false; + node.is_running = Some(res); + } } } msg @ message::DefineNode::DefineBitcoind(_) => { @@ -221,6 +235,7 @@ impl Step for DefineNode { progress: (usize, usize), _email: Option<&str>, ) -> Element { + // TODO: Make input fields read-only while waiting for a ping result. view::define_bitcoin_node( progress, self.nodes.iter().map(|node| node.definition.node_type()), @@ -228,13 +243,10 @@ impl Step for DefineNode { self.selected().definition.view(), self.selected().is_running.as_ref(), self.selected().definition.can_try_ping(), + self.selected().waiting_for_ping_result, ) } - fn load(&self) -> Command { - self.ping_selected() - } - fn skip(&self, ctx: &Context) -> bool { !ctx.bitcoind_is_external || ctx.remote_backend.is_some() } diff --git a/gui/src/installer/view.rs b/gui/src/installer/view.rs index 59ed48e4..da783daa 100644 --- a/gui/src/installer/view.rs +++ b/gui/src/installer/view.rs @@ -1169,6 +1169,7 @@ pub fn define_bitcoin_node<'a>( node_view: Element<'a, Message>, is_running: Option<&Result<(), Error>>, can_try_ping: bool, + waiting_for_ping_result: bool, ) -> Element<'a, Message> { let col = Column::new() .push( @@ -1196,7 +1197,14 @@ pub fn define_bitcoin_node<'a>( ), ) .push(node_view) - .push_maybe(if is_running.is_some() { + .push_maybe(if waiting_for_ping_result { + Some(Container::new( + Row::new() + .spacing(10) + .align_items(Alignment::Center) + .push(text("Checking connection...")), + )) + } else if is_running.is_some() { is_running.map(|res| { if res.is_ok() { Container::new( @@ -1224,7 +1232,7 @@ pub fn define_bitcoin_node<'a>( .spacing(10) .push(Container::new( button::secondary(None, "Check connection") - .on_press_maybe(if can_try_ping { + .on_press_maybe(if can_try_ping && !waiting_for_ping_result { Some(Message::DefineNode(DefineNode::Ping)) } else { None