wallet settings: edit fingerprint aliases

This commit is contained in:
edouard 2023-03-18 15:37:49 +01:00
parent ae8df0dd4c
commit f5394bf889
3 changed files with 165 additions and 4 deletions

View File

@ -13,15 +13,18 @@ use crate::{
},
daemon::Daemon,
hw::{list_hardware_wallets, HardwareWallet, HardwareWalletConfig},
ui::component::modal,
ui::component::{form, modal},
};
pub struct WalletSettingsState {
data_dir: PathBuf,
warning: Option<Error>,
descriptor: String,
keys_aliases: Vec<(Fingerprint, form::Value<String>)>,
wallet: Arc<Wallet>,
modal: Option<RegisterWalletModal>,
processing: bool,
updated: bool,
}
impl WalletSettingsState {
@ -29,17 +32,52 @@ impl WalletSettingsState {
WalletSettingsState {
data_dir,
descriptor: wallet.main_descriptor.to_string(),
keys_aliases: Self::keys_aliases(&wallet),
wallet,
warning: None,
modal: None,
processing: false,
updated: false,
}
}
fn keys_aliases(wallet: &Wallet) -> Vec<(Fingerprint, form::Value<String>)> {
let mut keys_aliases: Vec<(Fingerprint, form::Value<String>)> = wallet
.keys_aliases
.clone()
.into_iter()
.map(|(fg, name)| {
(
fg,
form::Value {
value: name,
valid: true,
},
)
})
.collect();
for fingerprint in wallet.descriptor_keys().into_iter() {
if wallet.keys_aliases.get(&fingerprint).is_none() {
keys_aliases.push((fingerprint, form::Value::default()));
}
}
keys_aliases.sort_by(|(fg1, _), (fg2, _)| fg1.cmp(fg2));
keys_aliases
}
}
impl State for WalletSettingsState {
fn view<'a>(&'a self, cache: &'a Cache) -> Element<'a, view::Message> {
let content =
view::settings::wallet_settings(cache, self.warning.as_ref(), &self.descriptor);
let content = view::settings::wallet_settings(
cache,
self.warning.as_ref(),
&self.descriptor,
&self.keys_aliases,
self.processing,
self.updated,
);
if let Some(m) = &self.modal {
modal::Modal::new(content, m.view())
.on_blur(Some(view::Message::Close))
@ -56,18 +94,60 @@ impl State for WalletSettingsState {
message: Message,
) -> Command<Message> {
match message {
Message::Updated(res) => match res {
Ok(()) => {
self.processing = false;
self.updated = true;
Command::perform(async {}, |_| Message::LoadWallet)
}
Err(e) => {
self.processing = false;
self.warning = Some(e);
Command::none()
}
},
Message::WalletLoaded(res) => {
match res {
Ok(wallet) => {
if let Some(modal) = &mut self.modal {
modal.wallet = wallet.clone();
}
self.keys_aliases = Self::keys_aliases(&wallet);
self.wallet = wallet;
}
Err(e) => self.warning = Some(e),
};
Command::none()
}
Message::View(view::Message::Settings(
view::SettingsMessage::FingerprintAliasEdited(fg, value),
)) => {
if let Some((_, name)) = self
.keys_aliases
.iter_mut()
.find(|(fingerprint, _)| fg == *fingerprint)
{
name.value = value;
}
Command::none()
}
Message::View(view::Message::Settings(view::SettingsMessage::Save)) => {
self.modal = None;
self.processing = true;
self.updated = false;
Command::perform(
update_keys_aliases(
self.data_dir.clone(),
cache.network,
self.wallet.clone(),
self.keys_aliases
.iter()
.map(|(fg, name)| (*fg, name.value.to_owned()))
.collect(),
),
Message::Updated,
)
}
Message::View(view::Message::Close) => {
self.modal = None;
Command::none()
@ -249,6 +329,33 @@ async fn register_wallet(
Ok(fingerprint)
}
async fn update_keys_aliases(
data_dir: PathBuf,
network: Network,
wallet: Arc<Wallet>,
keys_aliases: Vec<(Fingerprint, String)>,
) -> Result<(), Error> {
let mut settings = settings::Settings::from_file(data_dir.clone(), network)?;
let checksum = wallet.descriptor_checksum();
if let Some(wallet_setting) = settings
.wallets
.iter_mut()
.find(|w| w.descriptor_checksum == checksum)
{
wallet_setting.keys = keys_aliases
.into_iter()
.map(|(master_fingerprint, name)| settings::KeySetting {
master_fingerprint,
name,
})
.collect();
}
settings.to_file(data_dir, network)?;
Ok(())
}
async fn list_hws(wallet: Arc<Wallet>) -> Vec<HardwareWallet> {
list_hardware_wallets(
&wallet.hardware_wallets,

View File

@ -1,4 +1,5 @@
use crate::app::menu::Menu;
use liana::miniscript::bitcoin::util::bip32::Fingerprint;
#[derive(Debug, Clone)]
pub enum Message {
@ -53,6 +54,8 @@ pub enum SettingsMessage {
EditWalletSettings,
AboutSection,
RegisterWallet,
FingerprintAliasEdited(Fingerprint, String),
Save,
Edit(usize, SettingsEditMessage),
}

View File

@ -523,6 +523,9 @@ pub fn wallet_settings<'a>(
cache: &'a Cache,
warning: Option<&Error>,
descriptor: &'a str,
keys_aliases: &[(Fingerprint, form::Value<String>)],
processing: bool,
updated: bool,
) -> Element<'a, Message> {
dashboard(
&Menu::Settings,
@ -548,7 +551,7 @@ pub fn wallet_settings<'a>(
)
.push(card::simple(
Column::new()
.push(text("Wallet descriptor:").small().bold())
.push(text("Wallet descriptor:").bold())
.push(text(descriptor.to_owned()).small())
.push(
Row::new()
@ -567,6 +570,54 @@ pub fn wallet_settings<'a>(
),
)
.spacing(10),
))
.push(card::simple(
Column::new()
.push(text("Fingerprint aliases:").bold())
.push(keys_aliases.iter().fold(
Column::new().spacing(10),
|col, (fingerprint, name)| {
let fg = *fingerprint;
col.push(
Row::new()
.spacing(10)
.align_items(Alignment::Center)
.push(text(fg.to_string()).bold().width(Length::Units(100)))
.push(
form::Form::new("Alias", name, move |msg| {
Message::Settings(
SettingsMessage::FingerprintAliasEdited(fg, msg),
)
})
.warning("Please enter correct alias")
.size(20)
.padding(10),
),
)
},
))
.push(
Row::new()
.align_items(Alignment::Center)
.push(Space::with_width(Length::Fill))
.push_maybe(if updated {
Some(
Row::new()
.align_items(Alignment::Center)
.push(icon::circle_check_icon().style(color::SUCCESS))
.push(text("Updated").style(color::SUCCESS)),
)
} else {
None
})
.push(if !processing {
button::primary(None, "Update")
.on_press(Message::Settings(SettingsMessage::Save))
} else {
button::primary(None, "Updating")
}),
)
.spacing(10),
)),
)
}