gui: change coins remaining time label
This commit is contained in:
parent
6582706f83
commit
956b7901c1
@ -2,8 +2,10 @@ use iced::{Alignment, Length};
|
||||
|
||||
use liana_ui::{
|
||||
color,
|
||||
component::{amount::*, badge, separation, text::*},
|
||||
icon, theme,
|
||||
component::{amount::*, badge, text::*},
|
||||
icon,
|
||||
image::*,
|
||||
theme,
|
||||
util::Collection,
|
||||
widget::*,
|
||||
};
|
||||
@ -20,14 +22,7 @@ pub fn coins_view<'a>(
|
||||
selected: &[usize],
|
||||
) -> Element<'a, Message> {
|
||||
Column::new()
|
||||
.push(
|
||||
Container::new(
|
||||
Row::new()
|
||||
.push(text(format!(" {}", coins.len())))
|
||||
.push(text(" coins")),
|
||||
)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(Container::new(h3("Coins")).width(Length::Fill))
|
||||
.push(
|
||||
Column::new()
|
||||
.spacing(10)
|
||||
@ -45,7 +40,7 @@ pub fn coins_view<'a>(
|
||||
)),
|
||||
)
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(20)
|
||||
.spacing(30)
|
||||
.into()
|
||||
}
|
||||
|
||||
@ -65,47 +60,11 @@ fn coin_list_view(
|
||||
.push(
|
||||
Row::new()
|
||||
.push(badge::coin())
|
||||
.push_maybe(if coin.spend_info.is_some() {
|
||||
Some(badge::spent())
|
||||
.push(if coin.spend_info.is_some() {
|
||||
badge::spent()
|
||||
} else {
|
||||
let seq = remaining_sequence(coin, blockheight, timelock);
|
||||
if seq == 0 {
|
||||
Some(Container::new(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.push(text(" 0").small().style(color::RED))
|
||||
.push(
|
||||
icon::hourglass_done_icon()
|
||||
.small()
|
||||
.style(color::RED),
|
||||
)
|
||||
.align_items(Alignment::Center),
|
||||
))
|
||||
} else if seq < timelock as u32 * 10 / 100 {
|
||||
Some(Container::new(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.push(
|
||||
text(format!(" {}", seq))
|
||||
.small()
|
||||
.style(color::ORANGE),
|
||||
)
|
||||
.push(
|
||||
icon::hourglass_icon()
|
||||
.small()
|
||||
.style(color::ORANGE),
|
||||
)
|
||||
.align_items(Alignment::Center),
|
||||
))
|
||||
} else {
|
||||
Some(Container::new(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.push(text(format!(" {}", seq)).small())
|
||||
.push(icon::hourglass_icon().small())
|
||||
.align_items(Alignment::Center),
|
||||
))
|
||||
}
|
||||
coin_sequence_label(seq, timelock as u32)
|
||||
})
|
||||
.push_maybe(if coin.block_height.is_none() {
|
||||
Some(badge::unconfirmed())
|
||||
@ -127,74 +86,83 @@ fn coin_list_view(
|
||||
.push_maybe(if collapsed {
|
||||
Some(
|
||||
Column::new()
|
||||
.spacing(10)
|
||||
.push(separation().width(Length::Fill))
|
||||
.padding(10)
|
||||
.spacing(5)
|
||||
.push_maybe(if coin.spend_info.is_none() {
|
||||
if let Some(b) = coin.block_height {
|
||||
if blockheight > b as u32 + timelock as u32 {
|
||||
Some(Container::new(
|
||||
p1_bold("One of the recovery path is available")
|
||||
.style(color::RED),
|
||||
))
|
||||
} else {
|
||||
Some(Container::new(p1_bold(format!(
|
||||
"One of the recovery path will be available in {} blocks",
|
||||
b as u32 + timelock as u32 - blockheight
|
||||
))))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.push(
|
||||
Column::new()
|
||||
.padding(10)
|
||||
.spacing(5)
|
||||
.push_maybe(if coin.spend_info.is_none() {
|
||||
if let Some(b) = coin.block_height {
|
||||
if blockheight > b as u32 + timelock as u32 {
|
||||
Some(Container::new(
|
||||
text("One of the recovery path is available")
|
||||
.bold()
|
||||
.small()
|
||||
.style(color::RED),
|
||||
))
|
||||
} else {
|
||||
Some(Container::new(
|
||||
text(format!("One of the recovery path will be available in {} blocks", b as u32 + timelock as u32 - blockheight))
|
||||
.bold()
|
||||
.small(),
|
||||
))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.push(
|
||||
Column::new()
|
||||
Row::new()
|
||||
.align_items(Alignment::Center)
|
||||
.push(p2_regular("Outpoint:").bold().style(color::GREY_2))
|
||||
.push(
|
||||
Row::new()
|
||||
.align_items(Alignment::Center)
|
||||
.push(text("Outpoint:").small().bold())
|
||||
.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(theme::Button::TransparentBorder)
|
||||
))
|
||||
.spacing(5),
|
||||
.push(
|
||||
p2_regular(format!("{}", coin.outpoint))
|
||||
.style(color::GREY_2),
|
||||
)
|
||||
.push(
|
||||
Button::new(icon::clipboard_icon())
|
||||
.on_press(Message::Clipboard(
|
||||
coin.outpoint.to_string(),
|
||||
))
|
||||
.style(theme::Button::TransparentBorder),
|
||||
),
|
||||
)
|
||||
.push_maybe(coin.block_height.map(|b| {
|
||||
Row::new()
|
||||
.push(text("Block height:").small().bold())
|
||||
.push(text(format!("{}", b)).small())
|
||||
.spacing(5)
|
||||
})),
|
||||
.spacing(5),
|
||||
)
|
||||
.push_maybe(coin.spend_info.map(|info| {
|
||||
Column::new()
|
||||
.push_maybe(coin.block_height.map(|b| {
|
||||
Row::new()
|
||||
.push(
|
||||
Row::new()
|
||||
.push(text("Spend txid:").small().bold())
|
||||
.push(text(format!("{}", info.txid)).small())
|
||||
.spacing(5),
|
||||
p2_regular("Block height:").bold().style(color::GREY_2),
|
||||
)
|
||||
.push(if let Some(height) = info.height {
|
||||
Row::new()
|
||||
.push(text("Spend block height:").small().bold())
|
||||
.push(text(format!("{}", height)).small())
|
||||
.spacing(5)
|
||||
} else {
|
||||
Row::new().push(text("Not in a block").bold().small())
|
||||
})
|
||||
.push(p2_regular(format!("{}", b)).style(color::GREY_2))
|
||||
.spacing(5)
|
||||
})),
|
||||
),
|
||||
)
|
||||
.push_maybe(coin.spend_info.map(|info| {
|
||||
Column::new()
|
||||
.push(
|
||||
Row::new()
|
||||
.push(p2_regular("Spend txid:").bold().style(color::GREY_2))
|
||||
.push(p2_regular(format!("{}", info.txid)))
|
||||
.spacing(5),
|
||||
)
|
||||
.push(if let Some(height) = info.height {
|
||||
Row::new()
|
||||
.push(
|
||||
p2_regular("Spend block height:")
|
||||
.bold()
|
||||
.style(color::GREY_2),
|
||||
)
|
||||
.push(p2_regular(format!("{}", height)))
|
||||
.spacing(5)
|
||||
} else {
|
||||
Row::new().push(
|
||||
p2_regular("Not in a block").bold().style(color::GREY_2),
|
||||
)
|
||||
})
|
||||
.spacing(5)
|
||||
})),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
@ -202,3 +170,69 @@ fn coin_list_view(
|
||||
)
|
||||
.style(theme::Container::Card(theme::Card::Simple))
|
||||
}
|
||||
|
||||
pub fn coin_sequence_label<'a, T: 'a>(seq: u32, timelock: u32) -> Container<'a, T> {
|
||||
if seq == 0 {
|
||||
Container::new(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.push(clock_red_icon().width(Length::Units(20)))
|
||||
.push(p2_regular("Expired"))
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
.padding(10)
|
||||
.style(theme::Container::Pill(theme::Pill::Warning))
|
||||
} else if seq < timelock as u32 * 10 / 100 {
|
||||
Container::new(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.push(clock_red_icon().width(Length::Units(20)))
|
||||
.push(p2_regular(expire_message(seq)))
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
.padding(10)
|
||||
.style(theme::Container::Pill(theme::Pill::Simple))
|
||||
} else {
|
||||
Container::new(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.push(clock_icon().width(Length::Units(20)))
|
||||
.push(p2_regular(expire_message(seq)).style(color::GREY_3))
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
.padding(10)
|
||||
.style(theme::Container::Pill(theme::Pill::Simple))
|
||||
}
|
||||
}
|
||||
|
||||
/// returns y,m,d,h,m
|
||||
pub fn expire_message(sequence: u32) -> String {
|
||||
let mut n_minutes = sequence * 10;
|
||||
let n_years = n_minutes / 525960;
|
||||
n_minutes -= n_years * 525960;
|
||||
let n_months = n_minutes / 43830;
|
||||
n_minutes -= n_months * 43830;
|
||||
let n_days = n_minutes / 1440;
|
||||
n_minutes -= n_days * 1440;
|
||||
let n_hours = n_minutes / 60;
|
||||
n_minutes -= n_hours * 60;
|
||||
|
||||
let units: Vec<String> = [
|
||||
(n_years, "year"),
|
||||
(n_months, "month"),
|
||||
(n_days, "day"),
|
||||
(n_hours, "hour"),
|
||||
(n_minutes, "minute"),
|
||||
]
|
||||
.iter()
|
||||
.filter_map(|(n, u)| {
|
||||
if *n != 0 {
|
||||
Some(format!("{} {}{}", n, u, if *n > 1 { "s" } else { "" }))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
format!("Expires in {}", units.join(","))
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ use iced::{
|
||||
|
||||
use liana_ui::{
|
||||
component::{button, text::*},
|
||||
icon::{coin_icon, cross_icon, home_icon, receive_icon, send_icon, settings_icon},
|
||||
icon::{cross_icon, home_icon, receive_icon, send_icon, settings_icon},
|
||||
image::*,
|
||||
theme,
|
||||
util::Collection,
|
||||
@ -75,7 +75,7 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> Container<'a, Message> {
|
||||
Row::new()
|
||||
.push(
|
||||
Row::new()
|
||||
.push(coin_icon())
|
||||
.push(coins_icon().width(Length::Units(20)))
|
||||
.push(text("Coins"))
|
||||
.spacing(10)
|
||||
.width(iced::Length::Fill)
|
||||
@ -114,7 +114,7 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> Container<'a, Message> {
|
||||
Row::new()
|
||||
.push(
|
||||
Row::new()
|
||||
.push(coin_icon())
|
||||
.push(coins_icon().width(Length::Units(20)))
|
||||
.push(text("Coins"))
|
||||
.spacing(10)
|
||||
.width(iced::Length::Fill)
|
||||
|
||||
@ -86,7 +86,7 @@ pub fn psbts_view<'a>(spend_txs: &[SpendTx]) -> Element<'a, Message> {
|
||||
),
|
||||
)
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(20)
|
||||
.spacing(25)
|
||||
.into()
|
||||
}
|
||||
|
||||
@ -99,8 +99,8 @@ fn spend_tx_list_view<'a>(i: usize, tx: &SpendTx) -> Element<'a, Message> {
|
||||
.push(badge::spend())
|
||||
.push(if !tx.sigs.recovery_paths().is_empty() {
|
||||
Row::new().push(
|
||||
Container::new(text(" Recovery ").small())
|
||||
.padding(3)
|
||||
Container::new(p2_regular(" Recovery "))
|
||||
.padding(10)
|
||||
.style(theme::Container::Pill(theme::Pill::Simple)),
|
||||
)
|
||||
} else {
|
||||
|
||||
@ -18,7 +18,7 @@ use crate::{
|
||||
app::{
|
||||
cache::Cache,
|
||||
error::Error,
|
||||
view::{message::*, modal},
|
||||
view::{coins, message::*, modal},
|
||||
},
|
||||
daemon::model::{remaining_sequence, Coin},
|
||||
};
|
||||
@ -207,37 +207,11 @@ fn coin_list_view<'a>(
|
||||
icon::square_icon()
|
||||
})
|
||||
.push(badge::coin())
|
||||
.push_maybe(if coin.spend_info.is_some() {
|
||||
Some(badge::spent())
|
||||
.push(if coin.spend_info.is_some() {
|
||||
badge::spent()
|
||||
} else {
|
||||
let seq = remaining_sequence(coin, blockheight, timelock);
|
||||
if seq == 0 {
|
||||
Some(Container::new(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.push(text(" 0").small().style(color::RED))
|
||||
.push(icon::hourglass_done_icon().small().style(color::RED))
|
||||
.align_items(Alignment::Center),
|
||||
))
|
||||
} else if seq < timelock as u32 * 10 / 100 {
|
||||
Some(Container::new(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.push(
|
||||
text(format!(" {}", seq)).small().style(color::ORANGE),
|
||||
)
|
||||
.push(icon::hourglass_icon().small().style(color::ORANGE))
|
||||
.align_items(Alignment::Center),
|
||||
))
|
||||
} else {
|
||||
Some(Container::new(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.push(text(format!(" {}", seq)).small())
|
||||
.push(icon::hourglass_icon().small())
|
||||
.align_items(Alignment::Center),
|
||||
))
|
||||
}
|
||||
coins::coin_sequence_label(seq, timelock as u32)
|
||||
})
|
||||
.push_maybe(if coin.block_height.is_none() {
|
||||
Some(badge::unconfirmed())
|
||||
|
||||
@ -25,14 +25,18 @@ pub fn transactions_view<'a>(
|
||||
.push(
|
||||
Column::new()
|
||||
.spacing(10)
|
||||
.push(
|
||||
pending_txs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.fold(Column::new().spacing(10), |col, (i, tx)| {
|
||||
col.push(tx_list_view(i, tx))
|
||||
}),
|
||||
)
|
||||
.push_maybe(if !pending_txs.is_empty() {
|
||||
Some(
|
||||
pending_txs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.fold(Column::new().spacing(10), |col, (i, tx)| {
|
||||
col.push(tx_list_view(i, tx))
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.push(
|
||||
txs.iter()
|
||||
.enumerate()
|
||||
@ -63,7 +67,7 @@ pub fn transactions_view<'a>(
|
||||
),
|
||||
)
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(20)
|
||||
.spacing(30)
|
||||
.into()
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use iced::{widget::tooltip, Length};
|
||||
|
||||
use crate::{component::text, icon, theme, widget::*};
|
||||
use crate::{component::text, icon, image, theme, widget::*};
|
||||
|
||||
pub struct Badge {
|
||||
icon: crate::widget::Text<'static>,
|
||||
@ -53,19 +53,23 @@ pub fn spend<T>() -> Container<'static, T> {
|
||||
}
|
||||
|
||||
pub fn coin<T>() -> Container<'static, T> {
|
||||
Container::new(icon::coin_icon().width(Length::Units(20)))
|
||||
.width(Length::Units(40))
|
||||
.height(Length::Units(40))
|
||||
.style(theme::Container::Badge(theme::Badge::Standard))
|
||||
.center_x()
|
||||
.center_y()
|
||||
Container::new(
|
||||
image::liana_grey_logo()
|
||||
.height(Length::Units(25))
|
||||
.width(Length::Units(25)),
|
||||
)
|
||||
.width(Length::Units(40))
|
||||
.height(Length::Units(40))
|
||||
.style(theme::Container::Badge(theme::Badge::Standard))
|
||||
.center_x()
|
||||
.center_y()
|
||||
}
|
||||
|
||||
pub fn unconfirmed<'a, T: 'a>() -> Container<'a, T> {
|
||||
Container::new(
|
||||
tooltip::Tooltip::new(
|
||||
Container::new(text::p2_regular(" Unconfirmed "))
|
||||
.padding(3)
|
||||
.padding(10)
|
||||
.style(theme::Container::Pill(theme::Pill::Simple)),
|
||||
"Do not treat this as a payment until it is confirmed",
|
||||
tooltip::Position::Top,
|
||||
@ -78,7 +82,7 @@ pub fn deprecated<'a, T: 'a>() -> Container<'a, T> {
|
||||
Container::new(
|
||||
tooltip::Tooltip::new(
|
||||
Container::new(text::p2_regular(" Deprecated "))
|
||||
.padding(3)
|
||||
.padding(10)
|
||||
.style(theme::Container::Pill(theme::Pill::Simple)),
|
||||
"This spend cannot be included anymore in the blockchain",
|
||||
tooltip::Position::Top,
|
||||
@ -91,7 +95,7 @@ pub fn spent<'a, T: 'a>() -> Container<'a, T> {
|
||||
Container::new(
|
||||
tooltip::Tooltip::new(
|
||||
Container::new(text::p2_regular(" Spent "))
|
||||
.padding(3)
|
||||
.padding(10)
|
||||
.style(theme::Container::Pill(theme::Pill::Simple)),
|
||||
"The spend transaction was included in the blockchain",
|
||||
tooltip::Position::Top,
|
||||
|
||||
@ -18,3 +18,21 @@ pub fn history_icon() -> Svg {
|
||||
let h = Handle::from_memory(HISTORY_ICON.to_vec());
|
||||
Svg::new(h)
|
||||
}
|
||||
|
||||
const COINS_ICON: &[u8] = include_bytes!("../static/icons/coins-icon.svg");
|
||||
pub fn coins_icon() -> Svg {
|
||||
let h = Handle::from_memory(COINS_ICON.to_vec());
|
||||
Svg::new(h)
|
||||
}
|
||||
|
||||
const CLOCK_ICON: &[u8] = include_bytes!("../static/icons/clock-icon.svg");
|
||||
pub fn clock_icon() -> Svg {
|
||||
let h = Handle::from_memory(CLOCK_ICON.to_vec());
|
||||
Svg::new(h)
|
||||
}
|
||||
|
||||
const CLOCK_RED_ICON: &[u8] = include_bytes!("../static/icons/clock-red-icon.svg");
|
||||
pub fn clock_red_icon() -> Svg {
|
||||
let h = Handle::from_memory(CLOCK_RED_ICON.to_vec());
|
||||
Svg::new(h)
|
||||
}
|
||||
|
||||
@ -288,6 +288,7 @@ pub enum Pill {
|
||||
Simple,
|
||||
Primary,
|
||||
Success,
|
||||
Warning,
|
||||
}
|
||||
|
||||
impl Pill {
|
||||
@ -312,6 +313,13 @@ impl Pill {
|
||||
border_color: color::GREY_3,
|
||||
text_color: color::GREY_3.into(),
|
||||
},
|
||||
Self::Warning => container::Appearance {
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
border_radius: 25.0,
|
||||
border_width: 1.0,
|
||||
border_color: color::RED,
|
||||
text_color: color::RED.into(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
6
gui/ui/static/icons/clock-icon.svg
Normal file
6
gui/ui/static/icons/clock-icon.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="13" r="9" stroke="#717171" stroke-width="1.5"/>
|
||||
<path d="M10 1H14" stroke="#717171" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M12 1L12 4" stroke="#717171" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M12 13L15 10" stroke="#717171" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 417 B |
6
gui/ui/static/icons/clock-red-icon.svg
Normal file
6
gui/ui/static/icons/clock-red-icon.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="13" r="9" stroke="#E9431F" stroke-width="1.5"/>
|
||||
<path d="M10 1H14" stroke="#E9431F" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M12 1L12 4" stroke="#E9431F" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M12 13L15 10" stroke="#E9431F" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 417 B |
3
gui/ui/static/icons/coins-icon.svg
Normal file
3
gui/ui/static/icons/coins-icon.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="20" height="23" viewBox="0 0 20 23" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.7189 9.02728L17.8442 10.177L18.2891 10.4269C19.237 10.9595 19.237 12.3325 18.2891 12.865L12.2525 16.2566C10.8524 17.0432 9.14756 17.0432 7.74754 16.2566L1.71092 12.865C0.763024 12.3325 0.763026 10.9595 1.71093 10.4269L2.15585 10.177L4.16334 9.02728M16.1811 14.1461L18.1129 15.1185C19.1092 15.6201 19.1412 17.0398 18.1685 17.5862L12.2525 20.9101C10.8524 21.6966 9.14756 21.6966 7.74754 20.9101L1.9178 17.6347C0.928395 17.0789 0.982913 15.6278 2.0112 15.1487L4.16334 14.1461M12.2525 11.3112L18.2891 7.91961C19.237 7.38705 19.237 6.01405 18.2891 5.48149L12.2525 2.08993C10.8524 1.30336 9.14756 1.30336 7.74754 2.08993L1.71093 5.48149C0.763027 6.01405 0.763024 7.38705 1.71092 7.91961L7.74754 11.3112C9.14756 12.0977 10.8524 12.0977 12.2525 11.3112Z" stroke="#7A7A7A" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 901 B |
Loading…
x
Reference in New Issue
Block a user