gui: display error for rescan past pruned height

close #900
This commit is contained in:
edouardparis 2024-01-29 14:28:51 +01:00
parent ae9e42421f
commit 18f2fe4572
4 changed files with 78 additions and 92 deletions

View File

@ -13,7 +13,7 @@ use liana::config::{BitcoinConfig, BitcoindConfig, BitcoindRpcAuth, Config};
use liana_ui::{component::form, widget::Element};
use crate::{
app::{cache::Cache, error::Error, message::Message, state::settings::Setting, view, State},
app::{cache::Cache, error::Error, message::Message, view, State},
bitcoind::{RpcAuthType, RpcAuthValues},
daemon::Daemon,
};
@ -23,8 +23,8 @@ pub struct BitcoindSettingsState {
warning: Option<Error>,
config_updated: bool,
settings: Vec<Box<dyn Setting>>,
current: Option<usize>,
node_settings: Option<BitcoindSettings>,
rescan_settings: RescanSetting,
}
impl BitcoindSettingsState {
@ -34,27 +34,18 @@ impl BitcoindSettingsState {
daemon_is_external: bool,
bitcoind_is_internal: bool,
) -> Self {
let settings = if let Some(config) = &config {
vec![
BitcoindSettingsState {
warning: None,
config_updated: false,
node_settings: config.map(|config| {
BitcoindSettings::new(
config.bitcoin_config.clone(),
config.bitcoind_config.clone().unwrap(),
daemon_is_external,
bitcoind_is_internal,
)
.into(),
RescanSetting::new(cache.rescan_progress).into(),
]
} else {
vec![RescanSetting::new(cache.rescan_progress).into()]
};
BitcoindSettingsState {
warning: None,
config_updated: false,
settings,
// If a scan is running, the current setting edited is the Rescan panel.
current: cache.rescan_progress.map(|_| 1),
}),
rescan_settings: RescanSetting::new(cache.rescan_progress),
}
}
}
@ -71,25 +62,20 @@ impl State for BitcoindSettingsState {
Ok(()) => {
self.config_updated = true;
self.warning = None;
if let Some(current) = self.current {
if let Some(setting) = self.settings.get_mut(current) {
setting.edited(true);
return Command::perform(async {}, |_| {
Message::View(view::Message::Settings(
view::SettingsMessage::EditBitcoindSettings,
))
});
}
if let Some(settings) = &mut self.node_settings {
settings.edited(true);
return Command::perform(async {}, |_| {
Message::View(view::Message::Settings(
view::SettingsMessage::EditBitcoindSettings,
))
});
}
self.current = None;
}
Err(e) => {
self.config_updated = false;
self.warning = Some(e);
if let Some(current) = self.current {
if let Some(setting) = self.settings.get_mut(current) {
setting.edited(false);
}
if let Some(settings) = &mut self.node_settings {
settings.edited(false);
}
}
},
@ -97,39 +83,57 @@ impl State for BitcoindSettingsState {
Err(e) => self.warning = Some(e),
Ok(info) => {
if info.rescan_progress == Some(1.0) {
self.settings[1].edited(true);
self.rescan_settings.edited(true);
}
}
},
Message::View(view::Message::Settings(view::SettingsMessage::Edit(i, msg))) => {
if let Some(setting) = self.settings.get_mut(i) {
match msg {
view::SettingsEditMessage::Select => self.current = Some(i),
view::SettingsEditMessage::Cancel => self.current = None,
_ => {}
};
return setting.update(daemon, cache, msg);
Message::StartRescan(Err(_)) => {
self.rescan_settings.past_possible_height = true;
self.rescan_settings.processing = false;
}
Message::View(view::Message::Settings(view::SettingsMessage::BitcoindSettings(
msg,
))) => {
if let Some(settings) = &mut self.node_settings {
return settings.update(daemon, cache, msg);
}
}
Message::View(view::Message::Settings(view::SettingsMessage::RescanSettings(msg))) => {
return self.rescan_settings.update(daemon, cache, msg);
}
_ => {}
};
Command::none()
}
fn view<'a>(&'a self, cache: &'a Cache) -> Element<'a, view::Message> {
let can_edit = self.current.is_none();
let can_edit_bitcoind_settings = !self.rescan_settings.processing;
let can_do_rescan = !self.rescan_settings.processing
&& self.node_settings.as_ref().map(|settings| settings.edit) != Some(true);
view::settings::bitcoind_settings(
cache,
self.warning.as_ref(),
self.settings
.iter()
.enumerate()
.map(|(i, setting)| {
setting.view(cache, can_edit).map(move |msg| {
view::Message::Settings(view::SettingsMessage::Edit(i, msg))
})
})
.collect(),
if let Some(settings) = &self.node_settings {
vec![
settings
.view(cache, can_edit_bitcoind_settings)
.map(move |msg| {
view::Message::Settings(view::SettingsMessage::BitcoindSettings(msg))
}),
self.rescan_settings
.view(cache, can_do_rescan)
.map(move |msg| {
view::Message::Settings(view::SettingsMessage::RescanSettings(msg))
}),
]
} else {
vec![self
.rescan_settings
.view(cache, can_do_rescan)
.map(move |msg| {
view::Message::Settings(view::SettingsMessage::RescanSettings(msg))
})]
},
)
}
}
@ -153,12 +157,6 @@ pub struct BitcoindSettings {
bitcoind_is_internal: bool,
}
impl From<BitcoindSettings> for Box<dyn Setting> {
fn from(s: BitcoindSettings) -> Box<dyn Setting> {
Box::new(s)
}
}
impl BitcoindSettings {
fn new(
bitcoin_config: BitcoinConfig,
@ -211,7 +209,7 @@ impl BitcoindSettings {
}
}
impl Setting for BitcoindSettings {
impl BitcoindSettings {
fn edited(&mut self, success: bool) {
self.processing = false;
if success {
@ -311,31 +309,29 @@ impl Setting for BitcoindSettings {
#[derive(Debug, Default)]
pub struct RescanSetting {
edit: bool,
processing: bool,
success: bool,
year: form::Value<String>,
month: form::Value<String>,
day: form::Value<String>,
invalid_date: bool,
}
impl From<RescanSetting> for Box<dyn Setting> {
fn from(s: RescanSetting) -> Box<dyn Setting> {
Box::new(s)
}
past_possible_height: bool,
}
impl RescanSetting {
pub fn new(rescan_progress: Option<f64>) -> Self {
Self {
processing: rescan_progress.is_some(),
processing: if let Some(progress) = rescan_progress {
progress < 1.0
} else {
false
},
..Default::default()
}
}
}
impl Setting for RescanSetting {
impl RescanSetting {
fn edited(&mut self, success: bool) {
self.processing = false;
self.success = success;
@ -348,16 +344,6 @@ impl Setting for RescanSetting {
message: view::SettingsEditMessage,
) -> Command<Message> {
match message {
view::SettingsEditMessage::Select => {
if !self.processing {
self.edit = true;
}
}
view::SettingsEditMessage::Cancel => {
if !self.processing {
self.edit = false;
}
}
view::SettingsEditMessage::FieldEdited(field, value) => {
self.invalid_date = false;
if !self.processing && (value.is_empty() || u32::from_str(&value).is_ok()) {
@ -376,10 +362,10 @@ impl Setting for RescanSetting {
u32::from_str(&self.day.value).unwrap_or(1),
) {
if date < NaiveDate::from_str("2009-01-03").unwrap() {
self.invalid_date = true;
self.past_possible_height = true;
return Command::none();
} else {
self.invalid_date = false;
self.past_possible_height = false;
date
}
} else {
@ -409,6 +395,7 @@ impl Setting for RescanSetting {
self.processing,
can_edit,
self.invalid_date,
self.past_possible_height,
)
}
}

View File

@ -17,17 +17,6 @@ use crate::{
daemon::Daemon,
};
trait Setting: std::fmt::Debug {
fn edited(&mut self, success: bool);
fn update(
&mut self,
daemon: Arc<dyn Daemon + Sync + Send>,
cache: &Cache,
message: view::SettingsEditMessage,
) -> Command<Message>;
fn view<'a>(&self, cache: &'a Cache, can_edit: bool) -> Element<'a, view::SettingsEditMessage>;
}
pub struct SettingsState {
data_dir: PathBuf,
wallet: Arc<Wallet>,

View File

@ -63,12 +63,13 @@ pub enum SpendTxMessage {
#[derive(Debug, Clone)]
pub enum SettingsMessage {
EditBitcoindSettings,
BitcoindSettings(SettingsEditMessage),
RescanSettings(SettingsEditMessage),
EditWalletSettings,
AboutSection,
RegisterWallet,
FingerprintAliasEdited(Fingerprint, String),
Save,
Edit(usize, SettingsEditMessage),
}
#[derive(Debug, Clone)]

View File

@ -475,6 +475,7 @@ pub fn rescan<'a>(
processing: bool,
can_edit: bool,
invalid_date: bool,
past_possible_height: bool,
) -> Element<'a, SettingsEditMessage> {
card::simple(Container::new(
Column::new()
@ -534,7 +535,15 @@ pub fn rescan<'a>(
)
.push_maybe(if invalid_date {
Some(
p1_regular("Provided date is either invalid or anterior to the genesis block's timestamp.")
p1_regular("Provided date is invalid")
.style(color::RED),
)
} else {
None
})
.push_maybe(if past_possible_height {
Some(
p1_regular("Provided date earlier than the genesis block's timestamp or the node prune height")
.style(color::RED),
)
} else {