From 341e4467dbf727d78f31690b8dbc405995ab4088 Mon Sep 17 00:00:00 2001 From: Michael Mallan Date: Wed, 28 Aug 2024 14:37:54 +0100 Subject: [PATCH] gui(installer): allow for different node types --- gui/src/installer/message.rs | 8 +- gui/src/installer/step/node/mod.rs | 117 ++++++++++++++++++++++------- gui/src/installer/view.rs | 30 +++++++- gui/src/node/mod.rs | 5 ++ 4 files changed, 131 insertions(+), 29 deletions(-) diff --git a/gui/src/installer/message.rs b/gui/src/installer/message.rs index 4a171a19..fc4c919e 100644 --- a/gui/src/installer/message.rs +++ b/gui/src/installer/message.rs @@ -9,7 +9,10 @@ use crate::{ download::Progress, hw::HardwareWalletMessage, lianalite::client::{auth::AuthClient, backend::api}, - node::bitcoind::{Bitcoind, ConfigField, RpcAuthType}, + node::{ + bitcoind::{Bitcoind, ConfigField, RpcAuthType}, + NodeType, + }, }; use async_hwi::{DeviceKind, Version}; @@ -76,8 +79,9 @@ pub enum DefineBitcoind { #[derive(Debug, Clone)] pub enum DefineNode { + NodeTypeSelected(NodeType), DefineBitcoind(DefineBitcoind), - PingResult(Result<(), Error>), + PingResult((NodeType, Result<(), Error>)), Ping, } diff --git a/gui/src/installer/step/node/mod.rs b/gui/src/installer/step/node/mod.rs index f63f1004..b2b5e549 100644 --- a/gui/src/installer/step/node/mod.rs +++ b/gui/src/installer/step/node/mod.rs @@ -8,6 +8,7 @@ use crate::{ step::{node::bitcoind::DefineBitcoind, Step}, view, Error, }, + node::NodeType, }; use iced::Command; @@ -19,8 +20,16 @@ pub enum NodeDefinition { } impl NodeDefinition { - fn new() -> Self { - NodeDefinition::Bitcoind(DefineBitcoind::new()) + fn new(node_type: NodeType) -> Self { + match node_type { + NodeType::Bitcoind => NodeDefinition::Bitcoind(DefineBitcoind::new()), + } + } + + fn node_type(&self) -> NodeType { + match self { + NodeDefinition::Bitcoind(_) => NodeType::Bitcoind, + } } fn apply(&mut self, ctx: &mut Context) -> bool { @@ -66,16 +75,17 @@ pub struct Node { } impl Node { - fn new() -> Self { + fn new(node_type: NodeType) -> Self { Node { - definition: NodeDefinition::new(), + definition: NodeDefinition::new(node_type), is_running: None, } } } pub struct DefineNode { - node: Node, + nodes: Vec, + selected_node_type: NodeType, } impl From for Box { @@ -85,44 +95,97 @@ impl From for Box { } impl DefineNode { - pub fn new() -> Self { - Self { node: Node::new() } + pub fn new(selected_node_type: NodeType) -> Self { + let available_node_types = [ + // This is the order in which the available node types will be shown to the user. + NodeType::Bitcoind, + ]; + assert!(available_node_types.contains(&selected_node_type)); + + let nodes = available_node_types + .iter() + .copied() + .map(Node::new) + .collect(); + + Self { + nodes, + selected_node_type, + } } - fn ping(&self) -> Command { - let def = self.node.definition.clone(); - Command::perform(async move { def.ping() }, move |res| { - Message::DefineNode(message::DefineNode::PingResult(res)) + pub fn selected_mut(&mut self) -> &mut Node { + self.get_mut(self.selected_node_type) + .expect("selected type must be present") + } + + pub fn selected(&self) -> &Node { + self.get(self.selected_node_type) + .expect("selected type must be present") + } + + pub fn get_mut(&mut self, node_type: NodeType) -> Option<&mut Node> { + self.nodes + .iter_mut() + .find(|node| node.definition.node_type() == node_type) + } + + pub fn get(&self, node_type: NodeType) -> Option<&Node> { + self.nodes + .iter() + .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, message: message::DefineNode) -> Command { - self.node.is_running = None; - self.node.definition.update(message) + 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); + } + Command::none() } } impl Default for DefineNode { fn default() -> Self { - Self::new() + Self::new(NodeType::Bitcoind) } } impl Step for DefineNode { fn load_context(&mut self, ctx: &Context) { - self.node.definition.load_context(ctx); + for node in self.nodes.iter_mut() { + node.definition.load_context(ctx); + } } fn update(&mut self, _hws: &mut HardwareWallets, message: Message) -> Command { if let Message::DefineNode(msg) = message { match msg { - message::DefineNode::Ping => { - return self.ping(); + message::DefineNode::NodeTypeSelected(node_type) => { + self.selected_node_type = node_type; } - message::DefineNode::PingResult(res) => { - self.node.is_running = Some(res); + message::DefineNode::Ping => { + return self.ping_selected(); + } + 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); + } } msg @ message::DefineNode::DefineBitcoind(_) => { - return self.update_node(msg); + return self.update_node(NodeType::Bitcoind, msg); } } } @@ -130,7 +193,7 @@ impl Step for DefineNode { } fn apply(&mut self, ctx: &mut Context) -> bool { - self.node.definition.apply(ctx) + self.selected_mut().definition.apply(ctx) } fn view( @@ -141,14 +204,16 @@ impl Step for DefineNode { ) -> Element { view::define_bitcoin_node( progress, - self.node.definition.view(), - self.node.is_running.as_ref(), - self.node.definition.can_try_ping(), + self.nodes.iter().map(|node| node.definition.node_type()), + self.selected_node_type, + self.selected().definition.view(), + self.selected().is_running.as_ref(), + self.selected().definition.can_try_ping(), ) } fn load(&self) -> Command { - self.ping() + self.ping_selected() } fn skip(&self, ctx: &Context) -> bool { diff --git a/gui/src/installer/view.rs b/gui/src/installer/view.rs index bd86a2f7..ec5c4de4 100644 --- a/gui/src/installer/view.rs +++ b/gui/src/installer/view.rs @@ -39,7 +39,10 @@ use crate::{ step::{DownloadState, InstallState}, Error, }, - node::bitcoind::{ConfigField, RpcAuthType, RpcAuthValues, StartInternalBitcoindError}, + node::{ + bitcoind::{ConfigField, RpcAuthType, RpcAuthValues, StartInternalBitcoindError}, + NodeType, + }, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -1161,11 +1164,36 @@ pub fn help_backup<'a>() -> Element<'a, Message> { pub fn define_bitcoin_node<'a>( progress: (usize, usize), + available_node_types: impl Iterator, + selected_node_type: NodeType, node_view: Element<'a, Message>, is_running: Option<&Result<(), Error>>, can_try_ping: bool, ) -> Element<'a, Message> { let col = Column::new() + .push( + available_node_types.fold( + Row::new() + .push(text("Node type:").small().bold()) + .spacing(10), + |row, node_type| { + row.push(radio( + match node_type { + NodeType::Bitcoind => "Bitcoin Core", + }, + node_type, + Some(selected_node_type), + |new_selection| { + Message::DefineNode(message::DefineNode::NodeTypeSelected( + new_selection, + )) + }, + )) + .spacing(30) + .align_items(Alignment::Center) + }, + ), + ) .push(node_view) .push_maybe(if is_running.is_some() { is_running.map(|res| { diff --git a/gui/src/node/mod.rs b/gui/src/node/mod.rs index ac8d5325..9f91cba0 100644 --- a/gui/src/node/mod.rs +++ b/gui/src/node/mod.rs @@ -1 +1,6 @@ pub mod bitcoind; + +#[derive(Debug, Clone, PartialEq, Eq, Copy)] +pub enum NodeType { + Bitcoind, +}