gui(installer): allow for different node types

This commit is contained in:
Michael Mallan 2024-08-28 14:37:54 +01:00
parent 83172c7bc5
commit 341e4467db
No known key found for this signature in database
GPG Key ID: 5177CDCEDB0EABEB
4 changed files with 131 additions and 29 deletions

View File

@ -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,
}

View File

@ -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<Node>,
selected_node_type: NodeType,
}
impl From<DefineNode> for Box<dyn Step> {
@ -85,44 +95,97 @@ impl From<DefineNode> for Box<dyn Step> {
}
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<Message> {
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<Message> {
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<Message> {
self.node.is_running = None;
self.node.definition.update(message)
fn update_node(
&mut self,
node_type: NodeType,
message: message::DefineNode,
) -> Command<Message> {
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<Message> {
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<Message> {
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<Message> {
self.ping()
self.ping_selected()
}
fn skip(&self, ctx: &Context) -> bool {

View File

@ -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<Item = NodeType>,
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| {

View File

@ -1 +1,6 @@
pub mod bitcoind;
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum NodeType {
Bitcoind,
}