Merge #146: Add warning to home panel

53514939da522f557c9c804a2b97fd5731b17864 Add clipboard to coin outpoint (edouard)
23e533fbeea96bb6ea5137ff66414e94b997b513 Add warning to home panel (edouard)

Pull request description:

  when remaining sequence is inferior to timelock*10/100, a warning is displayed in home panel
  based on #137

ACKs for top commit:
  edouardparis:
    Self-ACK 53514939da522f557c9c804a2b97fd5731b17864

Tree-SHA512: 5d317ae7e2094e6d8841ef58ed362abcc211111fa951969d42dc96ac1729055c60edc355de17524408e4e918de3d62d419d65869348c22b48e7d9ea42449dbac
This commit is contained in:
edouard 2022-12-06 11:20:05 +01:00
commit 36dbe27b03
No known key found for this signature in database
GPG Key ID: E65F7A089C20DC8F
3 changed files with 106 additions and 51 deletions

View File

@ -13,7 +13,7 @@ use liana::miniscript::bitcoin::{Address, Amount};
use super::{cache::Cache, error::Error, menu::Menu, message::Message, view};
use crate::daemon::{
model::{Coin, HistoryTransaction},
model::{remaining_sequence, Coin, HistoryTransaction},
Daemon,
};
pub use coins::CoinsPanel;
@ -38,6 +38,8 @@ pub trait State {
pub struct Home {
balance: Amount,
recovery_warning: Option<(Amount, usize)>,
recovery_alert: Option<(Amount, usize)>,
pending_events: Vec<HistoryTransaction>,
events: Vec<HistoryTransaction>,
selected_event: Option<usize>,
@ -60,6 +62,8 @@ impl Home {
})
.sum(),
),
recovery_alert: None,
recovery_warning: None,
selected_event: None,
events: Vec::new(),
pending_events: Vec::new(),
@ -82,14 +86,20 @@ impl State for Home {
&Menu::Home,
cache,
None,
view::home::home_view(&self.balance, &self.pending_events, &self.events),
view::home::home_view(
&self.balance,
self.recovery_warning.as_ref(),
self.recovery_alert.as_ref(),
&self.pending_events,
&self.events,
),
)
}
fn update(
&mut self,
daemon: Arc<dyn Daemon + Sync + Send>,
_cache: &Cache,
cache: &Cache,
message: Message,
) -> Command<Message> {
match message {
@ -97,19 +107,29 @@ impl State for Home {
Err(e) => self.warning = Some(e),
Ok(coins) => {
self.warning = None;
self.balance = Amount::from_sat(
coins
.iter()
.map(|coin| {
// If the coin is not spent and is its transaction is confirmed
if coin.spend_info.is_none() && coin.block_height.is_some() {
coin.amount.to_sat()
} else {
0
}
})
.sum(),
);
self.balance = Amount::from_sat(0);
let mut recovery_warning = (Amount::from_sat(0), 0);
let mut recovery_alert = (Amount::from_sat(0), 0);
for coin in coins {
if coin.spend_info.is_none() && coin.block_height.is_some() {
self.balance += coin.amount;
let timelock = daemon.config().main_descriptor.timelock_value();
let seq = remaining_sequence(&coin, cache.blockheight as u32, timelock);
if seq == 0 {
recovery_alert.0 += coin.amount;
recovery_alert.1 += 1;
} else if seq < timelock * 10 / 100 {
recovery_warning.0 += coin.amount;
recovery_warning.1 += 1;
}
}
}
if recovery_warning.1 > 0 {
self.recovery_warning = Some(recovery_warning);
}
if recovery_alert.1 > 0 {
self.recovery_alert = Some(recovery_alert);
}
}
},
Message::HistoryTransactions(res) => match res {

View File

@ -12,7 +12,7 @@ use crate::ui::{
use crate::{
app::{cache::Cache, view::message::Message},
daemon::model::Coin,
daemon::model::{remaining_sequence, Coin},
};
pub fn coins_view<'a>(
@ -74,36 +74,43 @@ fn coin_list_view(
.style(badge::PillStyle::Success),
)
} else {
if let Some(b) = coin.block_height {
if blockheight > b as u32 + timelock {
Some(Container::new(
Row::new()
.spacing(5)
.push(text(" 0").small().style(color::ALERT))
.push(
icon::hourglass_done_icon()
.small()
.style(color::ALERT),
)
.align_items(Alignment::Center),
))
} else {
Some(Container::new(
Row::new()
.spacing(5)
.push(
text(format!(
" {}",
b as u32 + timelock - blockheight
))
.small(),
)
.push(icon::hourglass_icon().small())
.align_items(Alignment::Center),
))
}
let seq = remaining_sequence(coin, blockheight, timelock);
if seq == 0 {
Some(Container::new(
Row::new()
.spacing(5)
.push(text(" 0").small().style(color::ALERT))
.push(
icon::hourglass_done_icon()
.small()
.style(color::ALERT),
)
.align_items(Alignment::Center),
))
} else if seq < timelock * 10 / 100 {
Some(Container::new(
Row::new()
.spacing(5)
.push(
text(format!(" {}", seq))
.small()
.style(color::WARNING),
)
.push(
icon::hourglass_icon()
.small()
.style(color::WARNING),
)
.align_items(Alignment::Center),
))
} else {
None
Some(Container::new(
Row::new()
.spacing(5)
.push(text(format!(" {}", seq)).small())
.push(icon::hourglass_icon().small())
.align_items(Alignment::Center),
))
}
})
.spacing(10)
@ -148,10 +155,7 @@ fn coin_list_view(
))
} else {
Some(Container::new(
text(format!(
"The recovery path will be available in {} blocks",
b as u32 + timelock - blockheight
))
text(format!("The recovery path will be available in {} blocks", b as u32 + timelock - blockheight))
.bold()
.small(),
))
@ -166,8 +170,14 @@ fn coin_list_view(
Column::new()
.push(
Row::new()
.align_items(Alignment::Center)
.push(text("Outpoint:").small().bold())
.push(text(format!("{}", coin.outpoint)).small())
.push(Row::new().align_items(Alignment::Center)
.push(text(format!("{}", coin.outpoint)).small())
.push(Button::new(icon::clipboard_icon())
.on_press(Message::Clipboard(coin.outpoint.to_string()))
.style(button::Style::TransparentBorder.into())
))
.spacing(5),
)
.push_maybe(coin.block_height.map(|b| {

View File

@ -7,6 +7,7 @@ use iced::{
};
use crate::ui::{
color,
component::{badge, button::Style, card, text::*},
icon,
util::Collection,
@ -22,12 +23,36 @@ pub const HISTORY_EVENT_PAGE_SIZE: u64 = 20;
pub fn home_view<'a>(
balance: &'a bitcoin::Amount,
recovery_warning: Option<&(bitcoin::Amount, usize)>,
recovery_alert: Option<&(bitcoin::Amount, usize)>,
pending_events: &[HistoryTransaction],
events: &Vec<HistoryTransaction>,
) -> Element<'a, Message> {
Column::new()
.push(Column::new().padding(40))
.push(text(format!("{} BTC", balance.to_btc())).bold().size(50))
.push_maybe(recovery_warning.map(|(a, c)| {
Row::new()
.spacing(15)
.align_items(Alignment::Center)
.push(icon::hourglass_icon().size(30).style(color::WARNING))
.push(Container::new(text(format!(
"Recovery path will be soon available for {} coins ( {} )",
c, a
))))
.padding(10)
}))
.push_maybe(recovery_alert.map(|(a, c)| {
Row::new()
.spacing(15)
.align_items(Alignment::Center)
.push(icon::hourglass_done_icon().style(color::ALERT))
.push(Container::new(text(format!(
"Recovery path is available for {} coins ( {} )",
c, a
))))
.padding(10)
}))
.push(
Column::new()
.spacing(10)