Edit key name in installer
This commit is contained in:
parent
bcd223f3fb
commit
689f19a4f2
@ -44,6 +44,7 @@ pub enum DefineDescriptor {
|
||||
Key(bool, usize, DefineKey),
|
||||
HWXpubImported(Result<DescriptorPublicKey, Error>),
|
||||
XPubEdited(String),
|
||||
NameEdited(String),
|
||||
SequenceEdited(String),
|
||||
ThresholdEdited(bool, usize),
|
||||
ConfirmXpub,
|
||||
@ -52,8 +53,7 @@ pub enum DefineDescriptor {
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DefineKey {
|
||||
Delete,
|
||||
ImportFromHardware,
|
||||
ImportFromClipboard,
|
||||
Edit,
|
||||
Clipboard(String),
|
||||
Imported(DescriptorPublicKey),
|
||||
Edited(String, DescriptorPublicKey),
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ use liana::{
|
||||
descriptors::{LianaDescKeys, MultipathDescriptor},
|
||||
miniscript::{
|
||||
bitcoin::{
|
||||
util::bip32::{DerivationPath, ExtendedPubKey, Fingerprint},
|
||||
util::bip32::{DerivationPath, Fingerprint},
|
||||
Network,
|
||||
},
|
||||
descriptor::{DerivPaths, DescriptorMultiXKey, DescriptorPublicKey, Wildcard},
|
||||
@ -48,6 +48,8 @@ pub struct DefineDescriptor {
|
||||
sequence: form::Value<String>,
|
||||
modal: Option<Box<dyn DescriptorKeyModal>>,
|
||||
|
||||
name_indexes: (usize, usize),
|
||||
|
||||
error: Option<String>,
|
||||
}
|
||||
|
||||
@ -61,6 +63,7 @@ impl DefineDescriptor {
|
||||
spending_threshold: 1,
|
||||
recovery_keys: vec![DescriptorKey::new("Recovery key 1".to_string())],
|
||||
recovery_threshold: 1,
|
||||
name_indexes: (1, 1),
|
||||
sequence: form::Value::default(),
|
||||
modal: None,
|
||||
error: None,
|
||||
@ -112,12 +115,12 @@ impl DefineDescriptor {
|
||||
for spending_key in self.spending_keys.iter_mut() {
|
||||
spending_key.duplicate_name = duplicate_names.contains(&spending_key.name);
|
||||
if let Some(key) = &spending_key.key {
|
||||
spending_key.duplicate_key = duplicate_keys.contains(&key);
|
||||
spending_key.duplicate_key = duplicate_keys.contains(key);
|
||||
}
|
||||
}
|
||||
for recovery_key in self.recovery_keys.iter_mut() {
|
||||
if let Some(key) = &recovery_key.key {
|
||||
recovery_key.duplicate_key = duplicate_keys.contains(&key);
|
||||
recovery_key.duplicate_key = duplicate_keys.contains(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -161,16 +164,16 @@ impl Step for DefineDescriptor {
|
||||
}
|
||||
message::DefineDescriptor::AddKey(is_recovery) => {
|
||||
if is_recovery {
|
||||
self.name_indexes.0 += 1;
|
||||
self.recovery_keys.push(DescriptorKey::new(format!(
|
||||
"Recovery key {}",
|
||||
self.recovery_keys.len() + 1
|
||||
self.name_indexes.0,
|
||||
)));
|
||||
self.recovery_threshold += 1;
|
||||
} else {
|
||||
self.spending_keys.push(DescriptorKey::new(format!(
|
||||
"Key {}",
|
||||
self.spending_keys.len() + 1
|
||||
)));
|
||||
self.name_indexes.1 += 1;
|
||||
self.spending_keys
|
||||
.push(DescriptorKey::new(format!("Key {}", self.name_indexes.1,)));
|
||||
self.spending_threshold += 1;
|
||||
}
|
||||
}
|
||||
@ -178,28 +181,51 @@ impl Step for DefineDescriptor {
|
||||
message::DefineKey::Clipboard(key) => {
|
||||
return Command::perform(async move { key }, Message::Clibpboard);
|
||||
}
|
||||
message::DefineKey::Imported(imported_key) => {
|
||||
message::DefineKey::Edited(name, imported_key) => {
|
||||
if is_recovery {
|
||||
if let Some(recovery_key) = self.recovery_keys.get_mut(i) {
|
||||
recovery_key.name = name;
|
||||
recovery_key.key = Some(imported_key);
|
||||
recovery_key.check_network(self.network);
|
||||
}
|
||||
} else if let Some(spending_key) = self.spending_keys.get_mut(i) {
|
||||
spending_key.name = name;
|
||||
spending_key.key = Some(imported_key);
|
||||
spending_key.check_network(self.network);
|
||||
}
|
||||
self.modal = None;
|
||||
self.check_for_duplicate();
|
||||
}
|
||||
message::DefineKey::ImportFromClipboard => {
|
||||
let modal = ImportXpubModal::new(i, is_recovery, self.network);
|
||||
self.modal = Some(Box::new(modal));
|
||||
}
|
||||
message::DefineKey::ImportFromHardware => {
|
||||
let modal = HardwareXpubModal::new(i, is_recovery, self.network);
|
||||
let cmd = modal.load();
|
||||
self.modal = Some(Box::new(modal));
|
||||
return cmd;
|
||||
message::DefineKey::Edit => {
|
||||
if is_recovery {
|
||||
if let Some(recovery_key) = self.recovery_keys.get(i) {
|
||||
let name = recovery_key.name.clone();
|
||||
let key = recovery_key
|
||||
.key
|
||||
.as_ref()
|
||||
.map(|k| {
|
||||
k.to_string().trim_end_matches("/<0;1>/*").to_string()
|
||||
})
|
||||
.unwrap_or_else(|| "".to_string());
|
||||
let modal =
|
||||
EditXpubModal::new(name, key, i, is_recovery, self.network);
|
||||
let cmd = modal.load();
|
||||
self.modal = Some(Box::new(modal));
|
||||
return cmd;
|
||||
}
|
||||
} else if let Some(spending_key) = self.spending_keys.get(i) {
|
||||
let name = spending_key.name.clone();
|
||||
let key = spending_key
|
||||
.key
|
||||
.as_ref()
|
||||
.map(|k| k.to_string().trim_end_matches("/<0;1>/*").to_string())
|
||||
.unwrap_or_else(|| "".to_string());
|
||||
let modal =
|
||||
EditXpubModal::new(name, key, i, is_recovery, self.network);
|
||||
let cmd = modal.load();
|
||||
self.modal = Some(Box::new(modal));
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
message::DefineKey::Delete => {
|
||||
if is_recovery {
|
||||
@ -371,10 +397,13 @@ impl DescriptorKey {
|
||||
|
||||
pub fn view(&self) -> Element<message::DefineKey> {
|
||||
match &self.key {
|
||||
None => view::undefined_descriptor_key(),
|
||||
Some(key) => {
|
||||
view::defined_descriptor_key(key.to_string(), self.valid, self.duplicate_key)
|
||||
}
|
||||
None => view::undefined_descriptor_key(&self.name),
|
||||
Some(_) => view::defined_descriptor_key(
|
||||
&self.name,
|
||||
self.valid,
|
||||
self.duplicate_key,
|
||||
self.duplicate_name,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -411,20 +440,37 @@ impl From<DefineDescriptor> for Box<dyn Step> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HardwareXpubModal {
|
||||
pub struct EditXpubModal {
|
||||
is_recovery: bool,
|
||||
key_index: usize,
|
||||
network: Network,
|
||||
error: Option<Error>,
|
||||
processing: bool,
|
||||
|
||||
form_name: form::Value<String>,
|
||||
form_xpub: form::Value<String>,
|
||||
|
||||
chosen_hw: Option<usize>,
|
||||
hws: Vec<HardwareWallet>,
|
||||
}
|
||||
|
||||
impl HardwareXpubModal {
|
||||
fn new(key_index: usize, is_recovery: bool, network: Network) -> Self {
|
||||
impl EditXpubModal {
|
||||
fn new(
|
||||
name: String,
|
||||
key: String,
|
||||
key_index: usize,
|
||||
is_recovery: bool,
|
||||
network: Network,
|
||||
) -> Self {
|
||||
Self {
|
||||
form_name: form::Value {
|
||||
valid: true,
|
||||
value: name,
|
||||
},
|
||||
form_xpub: form::Value {
|
||||
valid: true,
|
||||
value: key,
|
||||
},
|
||||
is_recovery,
|
||||
key_index,
|
||||
chosen_hw: None,
|
||||
@ -442,7 +488,7 @@ impl HardwareXpubModal {
|
||||
}
|
||||
}
|
||||
|
||||
impl DescriptorKeyModal for HardwareXpubModal {
|
||||
impl DescriptorKeyModal for EditXpubModal {
|
||||
fn processing(&self) -> bool {
|
||||
self.processing
|
||||
}
|
||||
@ -474,61 +520,18 @@ impl DescriptorKeyModal for HardwareXpubModal {
|
||||
self.processing = false;
|
||||
match res {
|
||||
Ok(key) => {
|
||||
let key_index = self.key_index;
|
||||
let is_recovery = self.is_recovery;
|
||||
return Command::perform(
|
||||
async move { (is_recovery, key_index, key) },
|
||||
|(is_recovery, key_index, key)| {
|
||||
message::DefineDescriptor::Key(
|
||||
is_recovery,
|
||||
key_index,
|
||||
message::DefineKey::Imported(key),
|
||||
)
|
||||
},
|
||||
)
|
||||
.map(Message::DefineDescriptor);
|
||||
self.form_xpub.value =
|
||||
key.to_string().trim_end_matches("/<0;1>/*").to_string();
|
||||
}
|
||||
Err(e) => {
|
||||
self.error = Some(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
Command::none()
|
||||
}
|
||||
fn view(&self) -> Element<Message> {
|
||||
view::hardware_wallet_xpubs_modal(
|
||||
self.is_recovery,
|
||||
&self.hws,
|
||||
self.error.as_ref(),
|
||||
self.processing,
|
||||
self.chosen_hw,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ImportXpubModal {
|
||||
is_recovery: bool,
|
||||
key_index: usize,
|
||||
form_xpub: form::Value<String>,
|
||||
network: Network,
|
||||
}
|
||||
|
||||
impl ImportXpubModal {
|
||||
fn new(key_index: usize, is_recovery: bool, network: Network) -> Self {
|
||||
Self {
|
||||
form_xpub: form::Value::default(),
|
||||
is_recovery,
|
||||
key_index,
|
||||
network,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DescriptorKeyModal for ImportXpubModal {
|
||||
fn update(&mut self, message: Message) -> Command<Message> {
|
||||
match message {
|
||||
Message::DefineDescriptor(message::DefineDescriptor::NameEdited(name)) => {
|
||||
self.form_name.valid = true;
|
||||
self.form_name.value = name;
|
||||
}
|
||||
Message::DefineDescriptor(message::DefineDescriptor::XPubEdited(s)) => {
|
||||
self.form_xpub.valid =
|
||||
DescriptorPublicKey::from_str(&format!("{}/<0;1>/*", s)).is_ok();
|
||||
@ -540,13 +543,14 @@ impl DescriptorKeyModal for ImportXpubModal {
|
||||
{
|
||||
let key_index = self.key_index;
|
||||
let is_recovery = self.is_recovery;
|
||||
let name = self.form_name.value.clone();
|
||||
return Command::perform(
|
||||
async move { (is_recovery, key_index, key) },
|
||||
|(is_recovery, key_index, key)| {
|
||||
message::DefineDescriptor::Key(
|
||||
is_recovery,
|
||||
key_index,
|
||||
message::DefineKey::Imported(key),
|
||||
message::DefineKey::Edited(name, key),
|
||||
)
|
||||
},
|
||||
)
|
||||
@ -558,29 +562,15 @@ impl DescriptorKeyModal for ImportXpubModal {
|
||||
Command::none()
|
||||
}
|
||||
fn view(&self) -> Element<Message> {
|
||||
view::clipboard_xpub_modal(&self.form_xpub, self.network)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct XKey {
|
||||
origin: Option<(Fingerprint, DerivationPath)>,
|
||||
key: ExtendedPubKey,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for XKey {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
if let Some((ref master_id, ref master_deriv)) = self.origin {
|
||||
std::fmt::Formatter::write_str(f, "[")?;
|
||||
for byte in master_id.into_bytes().iter() {
|
||||
write!(f, "{:02x}", byte)?;
|
||||
}
|
||||
for child in master_deriv {
|
||||
write!(f, "/{}", child)?;
|
||||
}
|
||||
std::fmt::Formatter::write_str(f, "]")?;
|
||||
}
|
||||
self.key.fmt(f)?;
|
||||
Ok(())
|
||||
view::edit_key_modal(
|
||||
self.network,
|
||||
&self.hws,
|
||||
self.error.as_ref(),
|
||||
self.processing,
|
||||
self.chosen_hw,
|
||||
&self.form_xpub,
|
||||
&self.form_name,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -162,12 +162,14 @@ pub fn define_descriptor<'a>(
|
||||
Some(card::warning(
|
||||
"A data directory already exists for this network".to_string(),
|
||||
))
|
||||
});
|
||||
})
|
||||
.padding(50);
|
||||
|
||||
let col_spending_keys = Column::new()
|
||||
.push(
|
||||
Row::new()
|
||||
.spacing(10)
|
||||
.push(Space::with_width(Length::Units(40)))
|
||||
.push(text("Primary path:").bold())
|
||||
.push(tooltip(
|
||||
super::prompt::DEFINE_DESCRIPTOR_PRIMATRY_PATH_TOOLTIP,
|
||||
@ -200,13 +202,13 @@ pub fn define_descriptor<'a>(
|
||||
.push(
|
||||
Button::new(
|
||||
Container::new(icon::plus_icon().size(50))
|
||||
.width(Length::Units(250))
|
||||
.height(Length::Units(250))
|
||||
.width(Length::Units(200))
|
||||
.height(Length::Units(200))
|
||||
.align_y(alignment::Vertical::Center)
|
||||
.align_x(alignment::Horizontal::Center),
|
||||
)
|
||||
.width(Length::Units(250))
|
||||
.height(Length::Units(250))
|
||||
.width(Length::Units(200))
|
||||
.height(Length::Units(200))
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.on_press(
|
||||
Message::DefineDescriptor(
|
||||
@ -225,7 +227,11 @@ pub fn define_descriptor<'a>(
|
||||
.spacing(10);
|
||||
|
||||
let col_recovery_keys = Column::new()
|
||||
.push(text("Recovery path:").bold())
|
||||
.push(
|
||||
Row::new()
|
||||
.push(Space::with_width(Length::Units(50)))
|
||||
.push(text("Recovery path:").bold()),
|
||||
)
|
||||
.push(separation().width(Length::Fill))
|
||||
.push(
|
||||
Container::new(
|
||||
@ -253,13 +259,13 @@ pub fn define_descriptor<'a>(
|
||||
.push(
|
||||
Button::new(
|
||||
Container::new(icon::plus_icon().size(50))
|
||||
.width(Length::Units(250))
|
||||
.height(Length::Units(250))
|
||||
.width(Length::Units(200))
|
||||
.height(Length::Units(200))
|
||||
.align_y(alignment::Vertical::Center)
|
||||
.align_x(alignment::Horizontal::Center),
|
||||
)
|
||||
.width(Length::Units(250))
|
||||
.height(Length::Units(250))
|
||||
.width(Length::Units(200))
|
||||
.height(Length::Units(200))
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.on_press(
|
||||
Message::DefineDescriptor(
|
||||
@ -292,7 +298,7 @@ pub fn define_descriptor<'a>(
|
||||
)
|
||||
.push(
|
||||
Container::new(
|
||||
form::Form::new("Number of block", sequence, |msg| {
|
||||
form::Form::new("Number of blocks", sequence, |msg| {
|
||||
Message::DefineDescriptor(
|
||||
message::DefineDescriptor::SequenceEdited(msg),
|
||||
)
|
||||
@ -313,6 +319,7 @@ pub fn define_descriptor<'a>(
|
||||
layout(
|
||||
progress,
|
||||
Column::new()
|
||||
.push(Space::with_height(Length::Units(50)))
|
||||
.push(text("Create the wallet").bold().size(50))
|
||||
.push(
|
||||
Column::new()
|
||||
@ -330,9 +337,9 @@ pub fn define_descriptor<'a>(
|
||||
.on_press(Message::Next)
|
||||
})
|
||||
.push_maybe(error.map(|e| card::error("Failed to create descriptor", e.to_string())))
|
||||
.push(Space::with_height(Length::Units(20)))
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.padding(100)
|
||||
.spacing(50)
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
@ -451,10 +458,8 @@ pub fn participate_xpub<'a>(
|
||||
.spacing(10)
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Container::new(
|
||||
text(format!("Select your hardware wallet:")).bold(),
|
||||
)
|
||||
.width(Length::Fill),
|
||||
Container::new(text("Select your hardware wallet:").bold())
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
button::border(Some(icon::reload_icon()), "Refresh")
|
||||
@ -849,7 +854,7 @@ pub fn install<'a>(
|
||||
layout(progress, col)
|
||||
}
|
||||
|
||||
pub fn undefined_descriptor_key<'a>() -> Element<'a, message::DefineKey> {
|
||||
pub fn undefined_descriptor_key(name: &str) -> Element<message::DefineKey> {
|
||||
card::simple(
|
||||
Column::new()
|
||||
.width(Length::Fill)
|
||||
@ -857,7 +862,6 @@ pub fn undefined_descriptor_key<'a>() -> Element<'a, message::DefineKey> {
|
||||
.push(
|
||||
Row::new()
|
||||
.align_items(Alignment::Center)
|
||||
.push(icon::key_icon())
|
||||
.push(Space::with_width(Length::Fill))
|
||||
.push(
|
||||
Button::new(icon::cross_icon())
|
||||
@ -868,39 +872,41 @@ pub fn undefined_descriptor_key<'a>() -> Element<'a, message::DefineKey> {
|
||||
.push(
|
||||
Container::new(
|
||||
Column::new()
|
||||
.spacing(5)
|
||||
.spacing(15)
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
button::border(Some(icon::import_icon()), "from text input")
|
||||
.on_press(message::DefineKey::ImportFromClipboard),
|
||||
Scrollable::new(text(name).bold())
|
||||
.horizontal_scroll(Properties::new().width(2).scroller_width(2)),
|
||||
)
|
||||
.push(
|
||||
button::border(Some(icon::chip_icon()), "from hardware")
|
||||
.on_press(message::DefineKey::ImportFromHardware),
|
||||
),
|
||||
.push(icon::circle_check_icon().style(color::FOREGROUND).size(50)),
|
||||
)
|
||||
.height(Length::Fill)
|
||||
.align_y(alignment::Vertical::Center),
|
||||
),
|
||||
)
|
||||
.push(
|
||||
button::border(Some(icon::pencil_icon()), "Edit")
|
||||
.on_press(message::DefineKey::Edit),
|
||||
)
|
||||
.push(Space::with_height(Length::Units(5))),
|
||||
)
|
||||
.padding(5)
|
||||
.height(Length::Units(250))
|
||||
.width(Length::Units(250))
|
||||
.height(Length::Units(200))
|
||||
.width(Length::Units(200))
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn defined_descriptor_key<'a>(
|
||||
key: String,
|
||||
pub fn defined_descriptor_key(
|
||||
name: &str,
|
||||
valid: bool,
|
||||
duplicate: bool,
|
||||
) -> Element<'a, message::DefineKey> {
|
||||
duplicate_key: bool,
|
||||
duplicate_name: bool,
|
||||
) -> Element<message::DefineKey> {
|
||||
let col = Column::new()
|
||||
.spacing(40)
|
||||
.width(Length::Fill)
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Row::new()
|
||||
.align_items(Alignment::Center)
|
||||
.push(icon::key_icon())
|
||||
.push(Space::with_width(Length::Fill))
|
||||
.push(
|
||||
Button::new(icon::cross_icon())
|
||||
@ -914,18 +920,28 @@ pub fn defined_descriptor_key<'a>(
|
||||
.spacing(5)
|
||||
.push(
|
||||
Container::new(
|
||||
Scrollable::new(Container::new(text(key.clone())))
|
||||
.height(Length::Units(50))
|
||||
.horizontal_scroll(Properties::new().width(2).scroller_width(2)),
|
||||
Column::new()
|
||||
.spacing(15)
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Scrollable::new(text(name).bold()).horizontal_scroll(
|
||||
Properties::new().width(2).scroller_width(2),
|
||||
),
|
||||
)
|
||||
.push(
|
||||
icon::circle_check_icon()
|
||||
.style(color::SUCCESS)
|
||||
.size(40)
|
||||
.width(Length::Units(50)),
|
||||
),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill),
|
||||
.height(Length::Fill)
|
||||
.align_y(alignment::Vertical::Center),
|
||||
)
|
||||
.push(
|
||||
button::transparent_border(Some(icon::clipboard_icon()), "Copy")
|
||||
.on_press(message::DefineKey::Clipboard(key)),
|
||||
),
|
||||
);
|
||||
.height(Length::Fill),
|
||||
)
|
||||
.push(button::border(Some(icon::pencil_icon()), "Edit").on_press(message::DefineKey::Edit))
|
||||
.push(Space::with_height(Length::Units(5)));
|
||||
|
||||
if !valid {
|
||||
Column::new()
|
||||
@ -933,8 +949,8 @@ pub fn defined_descriptor_key<'a>(
|
||||
.push(
|
||||
card::invalid(col)
|
||||
.padding(5)
|
||||
.height(Length::Units(250))
|
||||
.width(Length::Units(250)),
|
||||
.height(Length::Units(200))
|
||||
.width(Length::Units(200)),
|
||||
)
|
||||
.push(
|
||||
text("Key is for a different network")
|
||||
@ -942,134 +958,164 @@ pub fn defined_descriptor_key<'a>(
|
||||
.style(color::ALERT),
|
||||
)
|
||||
.into()
|
||||
} else if duplicate {
|
||||
} else if duplicate_key {
|
||||
Column::new()
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
card::invalid(col)
|
||||
.padding(5)
|
||||
.height(Length::Units(250))
|
||||
.width(Length::Units(250)),
|
||||
.height(Length::Units(200))
|
||||
.width(Length::Units(200)),
|
||||
)
|
||||
.push(text("Key is a duplicate").small().style(color::ALERT))
|
||||
.into()
|
||||
} else if duplicate_name {
|
||||
Column::new()
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
card::invalid(col)
|
||||
.padding(5)
|
||||
.height(Length::Units(200))
|
||||
.width(Length::Units(200)),
|
||||
)
|
||||
.push(text("Name is a duplicate").small().style(color::ALERT))
|
||||
.into()
|
||||
} else {
|
||||
card::simple(col)
|
||||
.padding(5)
|
||||
.height(Length::Units(250))
|
||||
.width(Length::Units(250))
|
||||
.height(Length::Units(200))
|
||||
.width(Length::Units(200))
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hardware_wallet_xpubs_modal<'a>(
|
||||
is_heir: bool,
|
||||
pub fn edit_key_modal<'a>(
|
||||
network: bitcoin::Network,
|
||||
hws: &[HardwareWallet],
|
||||
error: Option<&Error>,
|
||||
processing: bool,
|
||||
chosen_hw: Option<usize>,
|
||||
form_xpub: &form::Value<String>,
|
||||
form_name: &form::Value<String>,
|
||||
) -> Element<'a, Message> {
|
||||
card::simple(
|
||||
Column::new()
|
||||
.spacing(20)
|
||||
.push(
|
||||
text(if is_heir {
|
||||
"Import the recovery public key:"
|
||||
} else {
|
||||
"Import the user public key:"
|
||||
})
|
||||
.bold(),
|
||||
)
|
||||
.push(separation().width(Length::Fill))
|
||||
.push_maybe(error.map(|e| card::error("Failed to import xpub", e.to_string())))
|
||||
.push(if !hws.is_empty() {
|
||||
Column::new()
|
||||
.push(
|
||||
Column::new()
|
||||
.push_maybe(error.map(|e| card::error("Failed to import xpub", e.to_string())))
|
||||
.push(card::simple(
|
||||
Column::new()
|
||||
.spacing(25)
|
||||
.push(
|
||||
Container::new(
|
||||
Row::new()
|
||||
.spacing(10)
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Container::new(
|
||||
text(format!("{} hardware wallets connected", hws.len()))
|
||||
.bold(),
|
||||
)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
button::border(Some(icon::reload_icon()), "Refresh")
|
||||
.on_press(Message::Reload),
|
||||
),
|
||||
.spacing(5)
|
||||
.push(icon::pencil_icon())
|
||||
.push(text("Edit")),
|
||||
)
|
||||
.spacing(10)
|
||||
.push(
|
||||
hws.iter()
|
||||
.enumerate()
|
||||
.fold(Column::new().spacing(10), |col, (i, hw)| {
|
||||
.width(Length::Fill)
|
||||
.align_x(alignment::Horizontal::Center),
|
||||
)
|
||||
.push(
|
||||
Column::new()
|
||||
.spacing(5)
|
||||
.push(text("Edit name:").bold())
|
||||
.push(
|
||||
form::Form::new("Name", form_name, |msg| {
|
||||
Message::DefineDescriptor(message::DefineDescriptor::NameEdited(
|
||||
msg,
|
||||
))
|
||||
})
|
||||
.warning("Please enter correct name")
|
||||
.size(20)
|
||||
.padding(10),
|
||||
),
|
||||
)
|
||||
.push(
|
||||
Column::new()
|
||||
.spacing(5)
|
||||
.push(text("Enter an extended public key:").bold())
|
||||
.push(
|
||||
Row::new()
|
||||
.push(
|
||||
form::Form::new("Extended public key", form_xpub, |msg| {
|
||||
Message::DefineDescriptor(
|
||||
message::DefineDescriptor::XPubEdited(msg),
|
||||
)
|
||||
})
|
||||
.warning(if network == bitcoin::Network::Bitcoin {
|
||||
"Please enter correct xpub"
|
||||
} else {
|
||||
"Please enter correct tpub"
|
||||
})
|
||||
.size(20)
|
||||
.padding(10),
|
||||
)
|
||||
.spacing(10)
|
||||
.push(Container::new(text("/<0;1>/*")).padding(5)),
|
||||
),
|
||||
)
|
||||
.push(if !hws.is_empty() {
|
||||
Column::new()
|
||||
.push(
|
||||
Row::new()
|
||||
.spacing(10)
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Container::new(text("Or select a hardware wallet:").bold())
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
button::border(Some(icon::reload_icon()), "Refresh")
|
||||
.on_press(Message::Reload),
|
||||
),
|
||||
)
|
||||
.spacing(10)
|
||||
.push(hws.iter().enumerate().fold(
|
||||
Column::new().spacing(10),
|
||||
|col, (i, hw)| {
|
||||
col.push(hw_list_view(
|
||||
i,
|
||||
hw,
|
||||
Some(i) == chosen_hw,
|
||||
processing,
|
||||
false,
|
||||
!processing
|
||||
&& Some(i) == chosen_hw
|
||||
&& form_xpub.valid
|
||||
&& !form_xpub.value.is_empty(),
|
||||
))
|
||||
}),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
} else {
|
||||
Column::new()
|
||||
.push(
|
||||
Column::new()
|
||||
.spacing(15)
|
||||
.width(Length::Fill)
|
||||
.push("Please connect a hardware wallet")
|
||||
.push(button::border(None, "Refresh").on_press(Message::Reload))
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
})
|
||||
.width(Length::Units(600)),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
pub fn clipboard_xpub_modal<'a>(
|
||||
form_xpub: &form::Value<String>,
|
||||
network: bitcoin::Network,
|
||||
) -> Element<'a, Message> {
|
||||
card::simple(
|
||||
Column::new()
|
||||
.spacing(10)
|
||||
.push(text("Input extended public key:").bold())
|
||||
.push(
|
||||
Row::new()
|
||||
.push(
|
||||
form::Form::new("Extended public key", form_xpub, |msg| {
|
||||
Message::DefineDescriptor(message::DefineDescriptor::XPubEdited(msg))
|
||||
})
|
||||
.warning(if network == bitcoin::Network::Bitcoin {
|
||||
"Please enter correct xpub"
|
||||
} else {
|
||||
"Please enter correct tpub"
|
||||
})
|
||||
.size(20)
|
||||
.padding(10),
|
||||
)
|
||||
.spacing(10)
|
||||
.push(Container::new(text("/<0;1>/*")).padding(5)),
|
||||
)
|
||||
.push(
|
||||
Row::new()
|
||||
.push(Space::with_width(Length::Fill))
|
||||
.push(if form_xpub.valid {
|
||||
button::primary(None, "Apply").on_press(Message::DefineDescriptor(
|
||||
message::DefineDescriptor::ConfirmXpub,
|
||||
},
|
||||
))
|
||||
} else {
|
||||
.width(Length::Fill)
|
||||
} else {
|
||||
Column::new()
|
||||
.push(
|
||||
Row::new()
|
||||
.spacing(15)
|
||||
.width(Length::Fill)
|
||||
.push(
|
||||
text("Or connect a hardware wallet")
|
||||
.bold()
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(button::border(None, "Refresh").on_press(Message::Reload))
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
})
|
||||
.push(
|
||||
if form_xpub.valid && !form_xpub.value.is_empty() && !form_name.value.is_empty()
|
||||
{
|
||||
button::primary(None, "Apply")
|
||||
}),
|
||||
),
|
||||
)
|
||||
.width(Length::Units(600))
|
||||
.into()
|
||||
.on_press(Message::DefineDescriptor(
|
||||
message::DefineDescriptor::ConfirmXpub,
|
||||
))
|
||||
.width(Length::Units(200))
|
||||
} else {
|
||||
button::primary(None, "Apply").width(Length::Units(100))
|
||||
},
|
||||
)
|
||||
.align_items(Alignment::Center),
|
||||
))
|
||||
.width(Length::Units(600))
|
||||
.into()
|
||||
}
|
||||
|
||||
fn hw_list_view<'a>(
|
||||
@ -1217,18 +1263,17 @@ mod threshsold_input {
|
||||
};
|
||||
|
||||
Column::new()
|
||||
.height(Length::Units(250))
|
||||
.width(Length::Units(200))
|
||||
.push(button(icon::up_icon().size(50), Event::IncrementPressed))
|
||||
.height(Length::Units(200))
|
||||
.width(Length::Units(100))
|
||||
.push(button(icon::up_icon().size(40), Event::IncrementPressed))
|
||||
.push(text("Threshold:").small().bold())
|
||||
.push(
|
||||
Container::new(text(format!("{}/{}", self.value, self.max)).size(50))
|
||||
.height(Length::Fill)
|
||||
.align_y(alignment::Vertical::Center),
|
||||
)
|
||||
.push(button(icon::down_icon().size(50), Event::DecrementPressed))
|
||||
.push(button(icon::down_icon().size(40), Event::DecrementPressed))
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(10)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user