Bump iced 0.5
This commit is contained in:
parent
60defd672c
commit
de738105c0
873
gui/Cargo.lock
generated
873
gui/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -19,10 +19,9 @@ liana = { git = "https://github.com/revault/liana", branch = "master", default-f
|
||||
backtrace = "0.3"
|
||||
base64 = "0.13"
|
||||
|
||||
iced = { version = "0.4", default-features= false, features = ["tokio", "wgpu", "svg", "qr_code", "pure"] }
|
||||
iced_native = "0.5"
|
||||
iced_lazy = { version = "0.1.1", features = ["pure"] }
|
||||
iced_pure = "0.2.2"
|
||||
iced = { version = "0.5", default-features= false, features = ["tokio", "wgpu", "svg", "qr_code"] }
|
||||
iced_native = "0.6"
|
||||
iced_lazy = { version = "0.2"}
|
||||
|
||||
tokio = {version = "1.21.0", features = ["signal"]}
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
||||
@ -12,8 +12,7 @@ use std::io::Write;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use iced::pure::Element;
|
||||
use iced::{clipboard, time, Command, Subscription};
|
||||
use iced::{clipboard, time, Command, Element, Subscription};
|
||||
use iced_native::{window, Event};
|
||||
|
||||
pub use liana::config::Config as DaemonConfig;
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::pure::Element;
|
||||
use iced::Command;
|
||||
use iced::{Command, Element};
|
||||
|
||||
use crate::{
|
||||
app::{cache::Cache, error::Error, menu::Menu, message::Message, state::State, view},
|
||||
@ -10,7 +9,7 @@ use crate::{
|
||||
|
||||
pub struct CoinsPanel {
|
||||
coins: Vec<Coin>,
|
||||
selected_coin: Option<usize>,
|
||||
selected: Vec<usize>,
|
||||
warning: Option<Error>,
|
||||
/// timelock value to pass for the heir to consume a coin.
|
||||
timelock: u32,
|
||||
@ -29,7 +28,7 @@ impl CoinsPanel {
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
selected_coin: None,
|
||||
selected: Vec::new(),
|
||||
warning: None,
|
||||
timelock,
|
||||
}
|
||||
@ -42,7 +41,7 @@ impl State for CoinsPanel {
|
||||
&Menu::Coins,
|
||||
cache,
|
||||
self.warning.as_ref(),
|
||||
view::coins::coins_view(cache, &self.coins, self.timelock),
|
||||
view::coins::coins_view(cache, &self.coins, self.timelock, &self.selected),
|
||||
)
|
||||
}
|
||||
|
||||
@ -56,6 +55,7 @@ impl State for CoinsPanel {
|
||||
Message::Coins(res) => match res {
|
||||
Err(e) => self.warning = Some(e),
|
||||
Ok(coins) => {
|
||||
self.selected = Vec::new();
|
||||
self.warning = None;
|
||||
self.coins = coins
|
||||
.iter()
|
||||
@ -69,11 +69,12 @@ impl State for CoinsPanel {
|
||||
.collect();
|
||||
}
|
||||
},
|
||||
Message::View(view::Message::Close) => {
|
||||
self.selected_coin = None;
|
||||
}
|
||||
Message::View(view::Message::Select(i)) => {
|
||||
self.selected_coin = Some(i);
|
||||
if let Some(position) = self.selected.iter().position(|j| *j == i) {
|
||||
self.selected.remove(position);
|
||||
} else {
|
||||
self.selected.push(i);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
@ -6,8 +6,8 @@ use std::convert::TryInto;
|
||||
use std::sync::Arc;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use iced::pure::{column, Element};
|
||||
use iced::{widget::qr_code, Command, Subscription};
|
||||
use iced::{widget::Column, Element};
|
||||
use liana::miniscript::bitcoin::{Address, Amount};
|
||||
|
||||
use super::{cache::Cache, error::Error, menu::Menu, message::Message, view};
|
||||
@ -241,7 +241,7 @@ impl State for ReceivePanel {
|
||||
view::receive::receive(address, self.qr_code.as_ref().unwrap()),
|
||||
)
|
||||
} else {
|
||||
view::dashboard(&Menu::Receive, cache, self.warning.as_ref(), column())
|
||||
view::dashboard(&Menu::Receive, cache, self.warning.as_ref(), Column::new())
|
||||
}
|
||||
}
|
||||
fn update(
|
||||
|
||||
@ -5,7 +5,7 @@ use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::prelude::*;
|
||||
use iced::{pure::Element, Command};
|
||||
use iced::{Command, Element};
|
||||
|
||||
use liana::config::Config;
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::pure::Element;
|
||||
use iced::Command;
|
||||
use iced::{Command, Element};
|
||||
use liana::miniscript::bitcoin::util::{bip32::Fingerprint, psbt::Psbt};
|
||||
|
||||
use crate::{
|
||||
@ -364,6 +363,6 @@ pub struct NoAction {}
|
||||
|
||||
impl Action for NoAction {
|
||||
fn view(&self) -> Element<view::Message> {
|
||||
iced::pure::column().into()
|
||||
iced::widget::Column::new().into()
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ mod detail;
|
||||
mod step;
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::{pure::Element, Command};
|
||||
use iced::{Command, Element};
|
||||
|
||||
use super::{redirect, State};
|
||||
use crate::{
|
||||
|
||||
@ -2,8 +2,7 @@ use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::pure::Element;
|
||||
use iced::Command;
|
||||
use iced::{Command, Element};
|
||||
use liana::miniscript::bitcoin::{
|
||||
util::psbt::Psbt, Address, Amount, Denomination, OutPoint, Script,
|
||||
};
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
use iced::{
|
||||
pure::{column, container, row, Element},
|
||||
Alignment, Length,
|
||||
widget::{Button, Column, Container, Row},
|
||||
Alignment, Element, Length,
|
||||
};
|
||||
|
||||
use crate::ui::{
|
||||
color,
|
||||
component::{badge, card, collapse::collapse, separation, text::*},
|
||||
component::{badge, button, card, separation, text::*},
|
||||
icon,
|
||||
util::Collection,
|
||||
};
|
||||
@ -15,22 +15,36 @@ use crate::{
|
||||
daemon::model::Coin,
|
||||
};
|
||||
|
||||
pub fn coins_view<'a>(cache: &Cache, coins: &'a [Coin], timelock: u32) -> Element<'a, Message> {
|
||||
column()
|
||||
pub fn coins_view<'a>(
|
||||
cache: &Cache,
|
||||
coins: &'a [Coin],
|
||||
timelock: u32,
|
||||
selected: &[usize],
|
||||
) -> Element<'a, Message> {
|
||||
Column::new()
|
||||
.push(
|
||||
container(
|
||||
row()
|
||||
.push(text(&format!(" {}", coins.len())).bold())
|
||||
Container::new(
|
||||
Row::new()
|
||||
.push(text(format!(" {}", coins.len())))
|
||||
.push(text(" coins")),
|
||||
)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.spacing(10)
|
||||
.push(coins.iter().fold(column().spacing(10), |col, coin| {
|
||||
col.push(coin_list_view(coin, timelock, cache.blockheight as u32))
|
||||
})),
|
||||
.push(coins.iter().enumerate().fold(
|
||||
Column::new().spacing(10),
|
||||
|col, (i, coin)| {
|
||||
col.push(coin_list_view(
|
||||
coin,
|
||||
timelock,
|
||||
cache.blockheight as u32,
|
||||
i,
|
||||
selected.contains(&i),
|
||||
))
|
||||
},
|
||||
)),
|
||||
)
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(20)
|
||||
@ -38,141 +52,154 @@ pub fn coins_view<'a>(cache: &Cache, coins: &'a [Coin], timelock: u32) -> Elemen
|
||||
}
|
||||
|
||||
#[allow(clippy::collapsible_else_if)]
|
||||
fn coin_list_view(coin: &Coin, timelock: u32, blockheight: u32) -> Element<Message> {
|
||||
container(collapse::<_, _, _, _, _>(
|
||||
move || {
|
||||
row::<Message, _>()
|
||||
.push(
|
||||
row()
|
||||
.push(badge::coin())
|
||||
.push_maybe(if coin.spend_info.is_some() {
|
||||
Some(
|
||||
container(text(" Spent ").small())
|
||||
.padding(3)
|
||||
.style(badge::PillStyle::Success),
|
||||
)
|
||||
} else {
|
||||
if let Some(b) = coin.block_height {
|
||||
if blockheight > b as u32 + timelock {
|
||||
Some(container(
|
||||
row()
|
||||
.spacing(5)
|
||||
.push(text(" 0").small().color(color::ALERT))
|
||||
.push(
|
||||
icon::hourglass_done_icon()
|
||||
.small()
|
||||
.color(color::ALERT),
|
||||
)
|
||||
.align_items(Alignment::Center),
|
||||
))
|
||||
} else {
|
||||
Some(container(
|
||||
row()
|
||||
.spacing(5)
|
||||
.push(
|
||||
text(&format!(
|
||||
" {}",
|
||||
b as u32 + timelock - blockheight
|
||||
))
|
||||
.small(),
|
||||
)
|
||||
.push(icon::hourglass_icon().small())
|
||||
.align_items(Alignment::Center),
|
||||
))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.spacing(10)
|
||||
.align_items(Alignment::Center)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
row()
|
||||
.spacing(5)
|
||||
fn coin_list_view(
|
||||
coin: &Coin,
|
||||
timelock: u32,
|
||||
blockheight: u32,
|
||||
index: usize,
|
||||
collapsed: bool,
|
||||
) -> Container<Message> {
|
||||
Container::new(
|
||||
Column::new()
|
||||
.push(
|
||||
Button::new(
|
||||
Row::new()
|
||||
.push(
|
||||
text(&format!("{:.8}", coin.amount.to_btc()))
|
||||
.bold()
|
||||
.width(Length::Shrink),
|
||||
Row::new()
|
||||
.push(badge::coin())
|
||||
.push_maybe(if coin.spend_info.is_some() {
|
||||
Some(
|
||||
Container::new(text(" Spent ").small())
|
||||
.padding(3)
|
||||
.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),
|
||||
))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.spacing(10)
|
||||
.align_items(Alignment::Center)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(text("BTC"))
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(20)
|
||||
.into()
|
||||
},
|
||||
move || {
|
||||
column()
|
||||
.spacing(10)
|
||||
.push(separation().width(Length::Fill))
|
||||
.push(
|
||||
column()
|
||||
.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 {
|
||||
Some(container(
|
||||
text("The recovery path is available")
|
||||
.bold()
|
||||
.small()
|
||||
.color(color::ALERT),
|
||||
))
|
||||
} else {
|
||||
Some(container(
|
||||
text(&format!(
|
||||
"The recovery path will be available in {} blocks",
|
||||
b as u32 + timelock - blockheight
|
||||
))
|
||||
.bold()
|
||||
.small(),
|
||||
))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.push(
|
||||
column()
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.push(
|
||||
row()
|
||||
.push(text("Outpoint:").small().bold())
|
||||
.push(text(&format!("{}", coin.outpoint)).small())
|
||||
.spacing(5),
|
||||
text(format!("{:.8}", coin.amount.to_btc()))
|
||||
.bold()
|
||||
.width(Length::Shrink),
|
||||
)
|
||||
.push_maybe(coin.block_height.map(|b| {
|
||||
row()
|
||||
.push(text("Block height:").small().bold())
|
||||
.push(text(&format!("{}", b)).small())
|
||||
.push(text("BTC"))
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(20),
|
||||
)
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.padding(10)
|
||||
.on_press(Message::Select(index)),
|
||||
)
|
||||
.push_maybe(if collapsed {
|
||||
Some(
|
||||
Column::new()
|
||||
.spacing(10)
|
||||
.push(separation().width(Length::Fill))
|
||||
.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 {
|
||||
Some(Container::new(
|
||||
text("The recovery path is available")
|
||||
.bold()
|
||||
.small()
|
||||
.style(color::ALERT),
|
||||
))
|
||||
} else {
|
||||
Some(Container::new(
|
||||
text(format!(
|
||||
"The recovery path will be available in {} blocks",
|
||||
b as u32 + timelock - blockheight
|
||||
))
|
||||
.bold()
|
||||
.small(),
|
||||
))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.push(
|
||||
Column::new()
|
||||
.push(
|
||||
Row::new()
|
||||
.push(text("Outpoint:").small().bold())
|
||||
.push(text(format!("{}", coin.outpoint)).small())
|
||||
.spacing(5),
|
||||
)
|
||||
.push_maybe(coin.block_height.map(|b| {
|
||||
Row::new()
|
||||
.push(text("Block height:").small().bold())
|
||||
.push(text(format!("{}", b)).small())
|
||||
.spacing(5)
|
||||
})),
|
||||
)
|
||||
.push_maybe(coin.spend_info.map(|info| {
|
||||
Column::new()
|
||||
.push(
|
||||
Row::new()
|
||||
.push(text("Spend txid:").small().bold())
|
||||
.push(text(format!("{}", info.txid)).small())
|
||||
.spacing(5),
|
||||
)
|
||||
.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())
|
||||
})
|
||||
.spacing(5)
|
||||
})),
|
||||
)
|
||||
.push_maybe(coin.spend_info.map(|info| {
|
||||
column()
|
||||
.push(
|
||||
row()
|
||||
.push(text("Spend txid:").small().bold())
|
||||
.push(text(&format!("{}", info.txid)).small())
|
||||
.spacing(5),
|
||||
)
|
||||
.push(if let Some(height) = info.height {
|
||||
row()
|
||||
.push(text("Spend block height:").small().bold())
|
||||
.push(text(&format!("{}", height)).small())
|
||||
.spacing(5)
|
||||
} else {
|
||||
row().push(text("Not in a block").bold().small())
|
||||
})
|
||||
.spacing(5)
|
||||
})),
|
||||
),
|
||||
)
|
||||
.into()
|
||||
},
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}),
|
||||
)
|
||||
.style(card::SimpleCardStyle)
|
||||
.into()
|
||||
}
|
||||
|
||||
@ -2,8 +2,8 @@ use chrono::NaiveDateTime;
|
||||
|
||||
use iced::{
|
||||
alignment,
|
||||
pure::{button, column, container, row, Element},
|
||||
Alignment, Length,
|
||||
widget::{Button, Column, Container, Row},
|
||||
Alignment, Element, Length,
|
||||
};
|
||||
|
||||
use crate::ui::{
|
||||
@ -21,17 +21,17 @@ pub fn home_view<'a>(
|
||||
pending_events: &[HistoryTransaction],
|
||||
events: &Vec<HistoryTransaction>,
|
||||
) -> Element<'a, Message> {
|
||||
column()
|
||||
.push(column().padding(40))
|
||||
.push(text(&format!("{} BTC", balance.to_btc())).bold().size(50))
|
||||
Column::new()
|
||||
.push(Column::new().padding(40))
|
||||
.push(text(format!("{} BTC", balance.to_btc())).bold().size(50))
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.spacing(10)
|
||||
.push(
|
||||
pending_events
|
||||
.iter()
|
||||
.enumerate()
|
||||
.fold(column().spacing(10), |col, (i, event)| {
|
||||
.fold(Column::new().spacing(10), |col, (i, event)| {
|
||||
col.push(event_list_view(i, event))
|
||||
}),
|
||||
)
|
||||
@ -39,22 +39,22 @@ pub fn home_view<'a>(
|
||||
events
|
||||
.iter()
|
||||
.enumerate()
|
||||
.fold(column().spacing(10), |col, (i, event)| {
|
||||
.fold(Column::new().spacing(10), |col, (i, event)| {
|
||||
col.push(event_list_view(i, event))
|
||||
}),
|
||||
)
|
||||
.push_maybe(
|
||||
if events.len() % HISTORY_EVENT_PAGE_SIZE as usize == 0 && !events.is_empty() {
|
||||
Some(
|
||||
container(
|
||||
button(
|
||||
Container::new(
|
||||
Button::new(
|
||||
text("See more")
|
||||
.width(Length::Fill)
|
||||
.horizontal_alignment(alignment::Horizontal::Center),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.padding(15)
|
||||
.style(Style::TransparentBorder)
|
||||
.style(Style::TransparentBorder.into())
|
||||
.on_press(Message::Next),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
@ -71,23 +71,23 @@ pub fn home_view<'a>(
|
||||
}
|
||||
|
||||
fn event_list_view<'a>(i: usize, event: &HistoryTransaction) -> Element<'a, Message> {
|
||||
container(
|
||||
button(
|
||||
row()
|
||||
Container::new(
|
||||
Button::new(
|
||||
Row::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(if event.is_external() {
|
||||
badge::receive()
|
||||
} else {
|
||||
badge::spend()
|
||||
})
|
||||
.push(if let Some(t) = event.time {
|
||||
container(
|
||||
text(&format!("{}", NaiveDateTime::from_timestamp(t as i64, 0)))
|
||||
Container::new(
|
||||
text(format!("{}", NaiveDateTime::from_timestamp(t as i64, 0)))
|
||||
.small(),
|
||||
)
|
||||
} else {
|
||||
container(text(" Pending ").small())
|
||||
Container::new(text(" Pending ").small())
|
||||
.padding(3)
|
||||
.style(badge::PillStyle::Success)
|
||||
})
|
||||
@ -96,9 +96,9 @@ fn event_list_view<'a>(i: usize, event: &HistoryTransaction) -> Element<'a, Mess
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(
|
||||
text(&{
|
||||
text({
|
||||
if event.is_external() {
|
||||
format!("+ {:.8}", event.incoming_amount.to_btc())
|
||||
} else {
|
||||
@ -117,16 +117,16 @@ fn event_list_view<'a>(i: usize, event: &HistoryTransaction) -> Element<'a, Mess
|
||||
)
|
||||
.padding(10)
|
||||
.on_press(Message::Select(i))
|
||||
.style(Style::TransparentBorder),
|
||||
.style(Style::TransparentBorder.into()),
|
||||
)
|
||||
.style(card::SimpleCardStyle)
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn event_view<'a>(event: &HistoryTransaction) -> Element<'a, Message> {
|
||||
column()
|
||||
Column::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(if event.is_external() {
|
||||
badge::receive()
|
||||
} else {
|
||||
@ -136,7 +136,7 @@ pub fn event_view<'a>(event: &HistoryTransaction) -> Element<'a, Message> {
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
.push(
|
||||
text(&{
|
||||
text({
|
||||
if event.is_external() {
|
||||
format!("+ {} BTC", event.incoming_amount.to_btc())
|
||||
} else {
|
||||
@ -150,23 +150,24 @@ pub fn event_view<'a>(event: &HistoryTransaction) -> Element<'a, Message> {
|
||||
.push_maybe(
|
||||
event
|
||||
.fee_amount
|
||||
.map(|fee| container(text(&format!("Miner Fee: {} BTC", fee.to_btc())))),
|
||||
.map(|fee| Container::new(text(format!("Miner Fee: {} BTC", fee.to_btc())))),
|
||||
)
|
||||
.push(card::simple(
|
||||
column()
|
||||
Column::new()
|
||||
.push_maybe(event.time.map(|t| {
|
||||
let date = NaiveDateTime::from_timestamp(t as i64, 0);
|
||||
row()
|
||||
Row::new()
|
||||
.width(Length::Fill)
|
||||
.push(container(text("Date:").bold()).width(Length::Fill))
|
||||
.push(container(text(&format!("{}", date))).width(Length::Shrink))
|
||||
.push(Container::new(text("Date:").bold()).width(Length::Fill))
|
||||
.push(Container::new(text(format!("{}", date))).width(Length::Shrink))
|
||||
}))
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.width(Length::Fill)
|
||||
.push(container(text("Txid:").bold()).width(Length::Fill))
|
||||
.push(Container::new(text("Txid:").bold()).width(Length::Fill))
|
||||
.push(
|
||||
container(text(&format!("{}", event.tx.txid()))).width(Length::Shrink),
|
||||
Container::new(text(format!("{}", event.tx.txid())))
|
||||
.width(Length::Shrink),
|
||||
),
|
||||
)
|
||||
.spacing(5),
|
||||
|
||||
@ -11,13 +11,12 @@ pub use message::*;
|
||||
use warning::warn;
|
||||
|
||||
use iced::{
|
||||
pure::{column, container, row, scrollable, widget, Element},
|
||||
Length,
|
||||
widget::{self, scrollable, Button, Column, Container, Row},
|
||||
Element, Length,
|
||||
};
|
||||
|
||||
use crate::ui::{
|
||||
color,
|
||||
component::{badge, button, separation, text::*},
|
||||
component::{badge, button, container, separation, text::*},
|
||||
icon::{coin_icon, cross_icon, home_icon, receive_icon, send_icon, settings_icon},
|
||||
util::Collection,
|
||||
};
|
||||
@ -36,11 +35,11 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
};
|
||||
|
||||
let coins_button = if *menu == Menu::Coins {
|
||||
iced::pure::widget::button::Button::new(
|
||||
container(
|
||||
row()
|
||||
Button::new(
|
||||
Container::new(
|
||||
Row::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(coin_icon())
|
||||
.push(text("Coins"))
|
||||
.spacing(10)
|
||||
@ -48,8 +47,8 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.align_items(iced::Alignment::Center),
|
||||
)
|
||||
.push(
|
||||
container(
|
||||
text(&format!(
|
||||
Container::new(
|
||||
text(format!(
|
||||
" {} ",
|
||||
cache
|
||||
.coins
|
||||
@ -71,15 +70,15 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.padding(5)
|
||||
.center_x(),
|
||||
)
|
||||
.style(button::Style::Primary)
|
||||
.style(button::Style::Primary.into())
|
||||
.on_press(Message::Reload)
|
||||
.width(iced::Length::Units(200))
|
||||
} else {
|
||||
iced::pure::widget::button::Button::new(
|
||||
container(
|
||||
row()
|
||||
Button::new(
|
||||
Container::new(
|
||||
Row::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(coin_icon())
|
||||
.push(text("Coins"))
|
||||
.spacing(10)
|
||||
@ -87,8 +86,8 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.align_items(iced::Alignment::Center),
|
||||
)
|
||||
.push(
|
||||
container(
|
||||
text(&format!(
|
||||
Container::new(
|
||||
text(format!(
|
||||
" {} ",
|
||||
cache
|
||||
.coins
|
||||
@ -110,17 +109,17 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.padding(5)
|
||||
.center_x(),
|
||||
)
|
||||
.style(button::Style::Transparent)
|
||||
.style(button::Style::Transparent.into())
|
||||
.on_press(Message::Menu(Menu::Coins))
|
||||
.width(iced::Length::Units(200))
|
||||
};
|
||||
|
||||
let spend_button = if *menu == Menu::Spend {
|
||||
iced::pure::widget::button::Button::new(
|
||||
container(
|
||||
row()
|
||||
Button::new(
|
||||
Container::new(
|
||||
Row::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(send_icon())
|
||||
.push(text("Send"))
|
||||
.spacing(10)
|
||||
@ -131,8 +130,8 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
container(
|
||||
text(&format!(" {} ", cache.spend_txs.len()))
|
||||
Container::new(
|
||||
text(format!(" {} ", cache.spend_txs.len()))
|
||||
.small()
|
||||
.bold(),
|
||||
)
|
||||
@ -147,15 +146,15 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.padding(5)
|
||||
.center_x(),
|
||||
)
|
||||
.style(button::Style::Primary)
|
||||
.style(button::Style::Primary.into())
|
||||
.on_press(Message::Reload)
|
||||
.width(iced::Length::Units(200))
|
||||
} else {
|
||||
iced::pure::widget::button::Button::new(
|
||||
container(
|
||||
row()
|
||||
Button::new(
|
||||
Container::new(
|
||||
Row::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(send_icon())
|
||||
.push(text("Send"))
|
||||
.spacing(10)
|
||||
@ -166,8 +165,8 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
container(
|
||||
text(&format!(" {} ", cache.spend_txs.len()))
|
||||
Container::new(
|
||||
text(format!(" {} ", cache.spend_txs.len()))
|
||||
.small()
|
||||
.bold(),
|
||||
)
|
||||
@ -182,7 +181,7 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.padding(5)
|
||||
.center_x(),
|
||||
)
|
||||
.style(button::Style::Transparent)
|
||||
.style(button::Style::Transparent.into())
|
||||
.on_press(Message::Menu(Menu::Spend))
|
||||
.width(iced::Length::Units(200))
|
||||
};
|
||||
@ -207,14 +206,14 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.width(iced::Length::Units(200))
|
||||
};
|
||||
|
||||
container(
|
||||
column()
|
||||
Container::new(
|
||||
Column::new()
|
||||
.padding(10)
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.push(
|
||||
column()
|
||||
.push(container(text("Liana").bold()).padding(10))
|
||||
Column::new()
|
||||
.push(Container::new(text("Liana").bold()).padding(10))
|
||||
.push(separation().width(Length::Units(200)))
|
||||
.spacing(10),
|
||||
)
|
||||
@ -226,11 +225,11 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.height(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
container(
|
||||
column()
|
||||
Container::new(
|
||||
Column::new()
|
||||
.spacing(10)
|
||||
.push_maybe(cache.rescan_progress.map(|p| {
|
||||
container(text(&format!(" Rescan...{:.2}% ", p * 100.0)))
|
||||
Container::new(text(format!(" Rescan...{:.2}% ", p * 100.0)))
|
||||
.padding(5)
|
||||
.style(badge::PillStyle::Simple)
|
||||
}))
|
||||
@ -239,19 +238,7 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.height(Length::Shrink),
|
||||
),
|
||||
)
|
||||
.style(SidebarStyle)
|
||||
}
|
||||
|
||||
pub struct SidebarStyle;
|
||||
impl widget::container::StyleSheet for SidebarStyle {
|
||||
fn style(&self) -> widget::container::Style {
|
||||
widget::container::Style {
|
||||
background: color::FOREGROUND.into(),
|
||||
border_width: 1.0,
|
||||
border_color: color::SECONDARY,
|
||||
..widget::container::Style::default()
|
||||
}
|
||||
}
|
||||
.style(container::Style::Sidebar)
|
||||
}
|
||||
|
||||
pub fn dashboard<'a, T: Into<Element<'a, Message>>>(
|
||||
@ -260,17 +247,17 @@ pub fn dashboard<'a, T: Into<Element<'a, Message>>>(
|
||||
warning: Option<&Error>,
|
||||
content: T,
|
||||
) -> Element<'a, Message> {
|
||||
row()
|
||||
Row::new()
|
||||
.push(
|
||||
sidebar(menu, cache)
|
||||
.width(Length::Shrink)
|
||||
.height(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.push(warn(warning))
|
||||
.push(main_section(container(scrollable(
|
||||
container(content).padding(20),
|
||||
.push(main_section(Container::new(scrollable(
|
||||
Container::new(content).padding(20),
|
||||
)))),
|
||||
)
|
||||
.width(iced::Length::Fill)
|
||||
@ -279,69 +266,49 @@ pub fn dashboard<'a, T: Into<Element<'a, Message>>>(
|
||||
}
|
||||
|
||||
fn main_section<'a, T: 'a>(menu: widget::Container<'a, T>) -> widget::Container<'a, T> {
|
||||
container(menu.max_width(1500))
|
||||
.style(MainSectionStyle)
|
||||
Container::new(menu.max_width(1500))
|
||||
.style(container::Style::Background)
|
||||
.center_x()
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
}
|
||||
|
||||
pub struct MainSectionStyle;
|
||||
impl widget::container::StyleSheet for MainSectionStyle {
|
||||
fn style(&self) -> widget::container::Style {
|
||||
widget::container::Style {
|
||||
background: color::BACKGROUND.into(),
|
||||
..widget::container::Style::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modal<'a, T: Into<Element<'a, Message>>>(
|
||||
is_previous: bool,
|
||||
warning: Option<&Error>,
|
||||
content: T,
|
||||
) -> Element<'a, Message> {
|
||||
column()
|
||||
Column::new()
|
||||
.push(warn(warning))
|
||||
.push(
|
||||
container(
|
||||
row()
|
||||
Container::new(
|
||||
Row::new()
|
||||
.push(if is_previous {
|
||||
column()
|
||||
Column::new()
|
||||
.push(
|
||||
button::transparent(None, "< Previous").on_press(Message::Previous),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
} else {
|
||||
column().width(Length::Fill)
|
||||
Column::new().width(Length::Fill)
|
||||
})
|
||||
.align_items(iced::Alignment::Center)
|
||||
.push(button::primary(Some(cross_icon()), "Close").on_press(Message::Close)),
|
||||
)
|
||||
.padding(10)
|
||||
.style(ModalSectionStyle),
|
||||
.style(container::Style::Background),
|
||||
)
|
||||
.push(modal_section(container(scrollable(content))))
|
||||
.push(modal_section(Container::new(scrollable(content))))
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn modal_section<'a, T: 'a>(menu: widget::Container<'a, T>) -> widget::Container<'a, T> {
|
||||
container(menu.max_width(1500))
|
||||
Container::new(menu.max_width(1500))
|
||||
.padding(20)
|
||||
.style(ModalSectionStyle)
|
||||
.style(container::Style::Background)
|
||||
.center_x()
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
}
|
||||
|
||||
pub struct ModalSectionStyle;
|
||||
impl widget::container::StyleSheet for ModalSectionStyle {
|
||||
fn style(&self) -> widget::container::Style {
|
||||
widget::container::Style {
|
||||
background: color::BACKGROUND.into(),
|
||||
..widget::container::Style::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
use iced::{
|
||||
pure::{column, row, widget::Button, Element},
|
||||
widget::qr_code::{self, QRCode},
|
||||
Alignment,
|
||||
widget::{
|
||||
qr_code::{self, QRCode},
|
||||
Button, Column, Row,
|
||||
},
|
||||
Alignment, Element,
|
||||
};
|
||||
|
||||
use liana::miniscript::bitcoin;
|
||||
@ -15,15 +17,15 @@ use super::message::Message;
|
||||
|
||||
pub fn receive<'a>(address: &'a bitcoin::Address, qr: &'a qr_code::State) -> Element<'a, Message> {
|
||||
card::simple(
|
||||
column()
|
||||
Column::new()
|
||||
.push(QRCode::new(qr).cell_size(10))
|
||||
.push(
|
||||
row()
|
||||
.push(text(&address.to_string()).small())
|
||||
Row::new()
|
||||
.push(text(address.to_string()).small())
|
||||
.push(
|
||||
Button::new(icon::clipboard_icon())
|
||||
.on_press(Message::Clipboard(address.to_string()))
|
||||
.style(button::Style::TransparentBorder),
|
||||
.style(button::Style::TransparentBorder.into()),
|
||||
)
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
|
||||
@ -2,8 +2,8 @@ use std::str::FromStr;
|
||||
|
||||
use iced::{
|
||||
alignment,
|
||||
pure::{column, container, progress_bar, row, widget, Element},
|
||||
Alignment, Length,
|
||||
widget::{self, Column, Container, ProgressBar, Row},
|
||||
Alignment, Element, Length,
|
||||
};
|
||||
|
||||
use liana::miniscript::bitcoin;
|
||||
@ -43,29 +43,29 @@ pub fn bitcoind_edit<'a>(
|
||||
cookie_path: &form::Value<String>,
|
||||
processing: bool,
|
||||
) -> Element<'a, SettingsMessage> {
|
||||
let mut col = column().spacing(20);
|
||||
let mut col = Column::new().spacing(20);
|
||||
if blockheight != 0 {
|
||||
col = col
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(badge::Badge::new(icon::network_icon()))
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.push(text("Network:"))
|
||||
.push(text(&network.to_string()).bold()),
|
||||
.push(text(network.to_string()).bold()),
|
||||
)
|
||||
.spacing(10)
|
||||
.width(Length::FillPortion(1)),
|
||||
)
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(badge::Badge::new(icon::block_icon()))
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.push(text("Block Height:"))
|
||||
.push(text(&blockheight.to_string()).bold()),
|
||||
.push(text(blockheight.to_string()).bold()),
|
||||
)
|
||||
.spacing(10)
|
||||
.width(Length::FillPortion(1)),
|
||||
@ -76,7 +76,7 @@ pub fn bitcoind_edit<'a>(
|
||||
|
||||
col = col
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.push(text("Cookie file path:").bold().small())
|
||||
.push(
|
||||
form::Form::new("Cookie file path", cookie_path, |value| {
|
||||
@ -89,7 +89,7 @@ pub fn bitcoind_edit<'a>(
|
||||
.spacing(5),
|
||||
)
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.push(text("Socket address:").bold().small())
|
||||
.push(
|
||||
form::Form::new("Socket address:", addr, |value| {
|
||||
@ -109,10 +109,10 @@ pub fn bitcoind_edit<'a>(
|
||||
confirm_button = confirm_button.on_press(SettingsMessage::ConfirmEdit);
|
||||
}
|
||||
|
||||
card::simple(container(
|
||||
column()
|
||||
card::simple(Container::new(
|
||||
Column::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(badge::Badge::new(icon::bitcoin_icon()))
|
||||
.push(text("Bitcoind"))
|
||||
.padding(10)
|
||||
@ -123,8 +123,8 @@ pub fn bitcoind_edit<'a>(
|
||||
.push(separation().width(Length::Fill))
|
||||
.push(col)
|
||||
.push(
|
||||
container(
|
||||
row()
|
||||
Container::new(
|
||||
Row::new()
|
||||
.push(cancel_button)
|
||||
.push(confirm_button)
|
||||
.spacing(10)
|
||||
@ -146,29 +146,29 @@ pub fn bitcoind<'a>(
|
||||
is_running: Option<bool>,
|
||||
can_edit: bool,
|
||||
) -> Element<'a, SettingsMessage> {
|
||||
let mut col = column().spacing(20);
|
||||
let mut col = Column::new().spacing(20);
|
||||
if blockheight != 0 {
|
||||
col = col
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(badge::Badge::new(icon::network_icon()))
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.push(text("Network:"))
|
||||
.push(text(&network.to_string()).bold()),
|
||||
.push(text(network.to_string()).bold()),
|
||||
)
|
||||
.spacing(10)
|
||||
.width(Length::FillPortion(1)),
|
||||
)
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(badge::Badge::new(icon::block_icon()))
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.push(text("Block Height:"))
|
||||
.push(text(&blockheight.to_string()).bold()),
|
||||
.push(text(blockheight.to_string()).bold()),
|
||||
)
|
||||
.spacing(10)
|
||||
.width(Length::FillPortion(1)),
|
||||
@ -185,21 +185,21 @@ pub fn bitcoind<'a>(
|
||||
("Socket address:", config.addr.to_string()),
|
||||
];
|
||||
|
||||
let mut col_fields = column();
|
||||
let mut col_fields = Column::new();
|
||||
for (k, v) in rows {
|
||||
col_fields = col_fields.push(
|
||||
row()
|
||||
.push(container(text(k).bold().small()).width(Length::Fill))
|
||||
.push(text(&v).small()),
|
||||
Row::new()
|
||||
.push(Container::new(text(k).bold().small()).width(Length::Fill))
|
||||
.push(text(v).small()),
|
||||
);
|
||||
}
|
||||
|
||||
card::simple(container(
|
||||
column()
|
||||
card::simple(Container::new(
|
||||
Column::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(badge::Badge::new(icon::bitcoin_icon()))
|
||||
.push(text("Bitcoind"))
|
||||
.push(is_running_label(is_running))
|
||||
@ -209,11 +209,11 @@ pub fn bitcoind<'a>(
|
||||
)
|
||||
.push(if can_edit {
|
||||
widget::Button::new(icon::pencil_icon())
|
||||
.style(button::Style::TransparentBorder)
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.on_press(SettingsMessage::Edit)
|
||||
} else {
|
||||
widget::Button::new(icon::pencil_icon())
|
||||
.style(button::Style::TransparentBorder)
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
})
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
@ -228,22 +228,22 @@ pub fn bitcoind<'a>(
|
||||
pub fn is_running_label<'a, T: 'a>(is_running: Option<bool>) -> widget::Container<'a, T> {
|
||||
if let Some(running) = is_running {
|
||||
if running {
|
||||
container(
|
||||
row()
|
||||
.push(icon::dot_icon().size(5).color(color::SUCCESS))
|
||||
.push(text("Running").small().color(color::SUCCESS))
|
||||
Container::new(
|
||||
Row::new()
|
||||
.push(icon::dot_icon().size(5).style(color::SUCCESS))
|
||||
.push(text("Running").small().style(color::SUCCESS))
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
} else {
|
||||
container(
|
||||
row()
|
||||
.push(icon::dot_icon().size(5).color(color::ALERT))
|
||||
.push(text("Not running").small().color(color::ALERT))
|
||||
Container::new(
|
||||
Row::new()
|
||||
.push(icon::dot_icon().size(5).style(color::ALERT))
|
||||
.push(text("Not running").small().style(color::ALERT))
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
container(column())
|
||||
Container::new(Column::new())
|
||||
}
|
||||
}
|
||||
|
||||
@ -256,14 +256,14 @@ pub fn rescan<'a>(
|
||||
processing: bool,
|
||||
can_edit: bool,
|
||||
) -> Element<'a, SettingsMessage> {
|
||||
card::simple(container(
|
||||
column()
|
||||
card::simple(Container::new(
|
||||
Column::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(badge::Badge::new(icon::block_icon()))
|
||||
.push(text("Rescan blockchain").width(Length::Fill))
|
||||
.push_maybe(if success {
|
||||
Some(text("Rescan was successful").color(color::SUCCESS))
|
||||
Some(text("Rescan was successful").style(color::SUCCESS))
|
||||
} else {
|
||||
None
|
||||
})
|
||||
@ -273,18 +273,18 @@ pub fn rescan<'a>(
|
||||
)
|
||||
.push(separation().width(Length::Fill))
|
||||
.push(if let Some(p) = scan_progress {
|
||||
container(
|
||||
column()
|
||||
Container::new(
|
||||
Column::new()
|
||||
.width(Length::Fill)
|
||||
.push(progress_bar(0.0..=1.0, p as f32).width(Length::Fill))
|
||||
.push(text(&format!("Rescan...{:.2}%", p * 100.0))),
|
||||
.push(ProgressBar::new(0.0..=1.0, p as f32).width(Length::Fill))
|
||||
.push(text(format!("Rescan...{:.2}%", p * 100.0))),
|
||||
)
|
||||
} else {
|
||||
container(
|
||||
column()
|
||||
Container::new(
|
||||
Column::new()
|
||||
.spacing(10)
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(text("Year:").bold().small())
|
||||
.push(
|
||||
form::Form::new("2022", year, |value| {
|
||||
@ -321,18 +321,18 @@ pub fn rescan<'a>(
|
||||
})
|
||||
&& is_ok_and(&u32::from_str(&day.value), |&v| v > 0 && v <= 31))
|
||||
{
|
||||
row().push(column().width(Length::Fill)).push(
|
||||
Row::new().push(Column::new().width(Length::Fill)).push(
|
||||
button::primary(None, "Start rescan")
|
||||
.on_press(SettingsMessage::ConfirmEdit)
|
||||
.width(Length::Shrink),
|
||||
)
|
||||
} else if processing {
|
||||
row().push(column().width(Length::Fill)).push(
|
||||
Row::new().push(Column::new().width(Length::Fill)).push(
|
||||
button::primary(None, "Starting rescan...")
|
||||
.width(Length::Shrink),
|
||||
)
|
||||
} else {
|
||||
row().push(column().width(Length::Fill)).push(
|
||||
Row::new().push(Column::new().width(Length::Fill)).push(
|
||||
button::primary(None, "Start rescan").width(Length::Shrink),
|
||||
)
|
||||
},
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use iced::{
|
||||
pure::{column, container, row, scrollable, Element},
|
||||
Alignment, Length,
|
||||
widget::{Button, Column, Container, Row, Scrollable},
|
||||
Alignment, Element, Length,
|
||||
};
|
||||
|
||||
use liana::miniscript::bitcoin::{
|
||||
@ -11,14 +11,14 @@ use liana::miniscript::bitcoin::{
|
||||
use crate::{
|
||||
app::{
|
||||
error::Error,
|
||||
view::{message::*, modal_section, warning::warn, ModalSectionStyle},
|
||||
view::{message::*, modal_section, warning::warn},
|
||||
},
|
||||
daemon::model::{Coin, SpendStatus, SpendTx},
|
||||
hw::HardwareWallet,
|
||||
ui::{
|
||||
color,
|
||||
component::{
|
||||
badge, button, card, separation,
|
||||
badge, button, card, container, separation,
|
||||
text::{text, Text},
|
||||
},
|
||||
icon,
|
||||
@ -36,7 +36,7 @@ pub fn spend_view<'a, T: Into<Element<'a, Message>>>(
|
||||
spend_modal(
|
||||
show_delete,
|
||||
warning,
|
||||
column()
|
||||
Column::new()
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(20)
|
||||
.push(spend_header(tx))
|
||||
@ -59,10 +59,10 @@ pub fn save_action<'a>(saved: bool) -> Element<'a, Message> {
|
||||
.into()
|
||||
} else {
|
||||
card::simple(
|
||||
column()
|
||||
Column::new()
|
||||
.spacing(10)
|
||||
.push(text("Save the transaction"))
|
||||
.push(row().push(column().width(Length::Fill)).push(
|
||||
.push(Row::new().push(Column::new().width(Length::Fill)).push(
|
||||
button::primary(None, "Save").on_press(Message::Spend(SpendTxMessage::Confirm)),
|
||||
)),
|
||||
)
|
||||
@ -79,11 +79,11 @@ pub fn broadcast_action<'a>(saved: bool) -> Element<'a, Message> {
|
||||
.into()
|
||||
} else {
|
||||
card::simple(
|
||||
column()
|
||||
Column::new()
|
||||
.spacing(10)
|
||||
.push(text("Broadcast the transaction"))
|
||||
.push(
|
||||
row().push(column().width(Length::Fill)).push(
|
||||
Row::new().push(Column::new().width(Length::Fill)).push(
|
||||
button::primary(None, "Broadcast")
|
||||
.on_press(Message::Spend(SpendTxMessage::Confirm)),
|
||||
),
|
||||
@ -102,12 +102,12 @@ pub fn delete_action<'a>(deleted: bool) -> Element<'a, Message> {
|
||||
.into()
|
||||
} else {
|
||||
card::simple(
|
||||
column()
|
||||
Column::new()
|
||||
.spacing(10)
|
||||
.push(text("Delete the transaction draft"))
|
||||
.push(
|
||||
row()
|
||||
.push(column().width(Length::Fill))
|
||||
Row::new()
|
||||
.push(Column::new().width(Length::Fill))
|
||||
.push(
|
||||
button::transparent(None, "Cancel")
|
||||
.on_press(Message::Spend(SpendTxMessage::Cancel)),
|
||||
@ -128,20 +128,20 @@ pub fn spend_modal<'a, T: Into<Element<'a, Message>>>(
|
||||
warning: Option<&Error>,
|
||||
content: T,
|
||||
) -> Element<'a, Message> {
|
||||
column()
|
||||
Column::new()
|
||||
.push(warn(warning))
|
||||
.push(
|
||||
container(
|
||||
row()
|
||||
Container::new(
|
||||
Row::new()
|
||||
.push(if show_delete {
|
||||
column()
|
||||
Column::new()
|
||||
.push(
|
||||
button::alert(Some(icon::trash_icon()), "Delete")
|
||||
.on_press(Message::Spend(SpendTxMessage::Delete)),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
} else {
|
||||
column()
|
||||
Column::new()
|
||||
.push(
|
||||
button::transparent(None, "< Previous").on_press(Message::Previous),
|
||||
)
|
||||
@ -153,20 +153,20 @@ pub fn spend_modal<'a, T: Into<Element<'a, Message>>>(
|
||||
),
|
||||
)
|
||||
.padding(10)
|
||||
.style(ModalSectionStyle),
|
||||
.style(container::Style::Background),
|
||||
)
|
||||
.push(modal_section(container(scrollable(content))))
|
||||
.push(modal_section(Container::new(Scrollable::new(content))))
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn spend_header<'a>(tx: &SpendTx) -> Element<'a, Message> {
|
||||
column()
|
||||
Column::new()
|
||||
.spacing(20)
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(badge::Badge::new(icon::send_icon()).style(badge::Style::Standard))
|
||||
.push(text("Spend").bold())
|
||||
.spacing(5)
|
||||
@ -174,26 +174,26 @@ fn spend_header<'a>(tx: &SpendTx) -> Element<'a, Message> {
|
||||
)
|
||||
.push_maybe(match tx.status {
|
||||
SpendStatus::Deprecated => Some(
|
||||
container(text(" Deprecated ").small())
|
||||
Container::new(text(" Deprecated ").small())
|
||||
.padding(3)
|
||||
.style(badge::PillStyle::Simple),
|
||||
),
|
||||
SpendStatus::Broadcasted => Some(
|
||||
container(text(" Broadcasted ").small())
|
||||
Container::new(text(" Broadcasted ").small())
|
||||
.padding(3)
|
||||
.style(badge::PillStyle::Success),
|
||||
),
|
||||
_ => None,
|
||||
})
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
text(&format!("- {} BTC", tx.spend_amount.to_btc()))
|
||||
text(format!("- {} BTC", tx.spend_amount.to_btc()))
|
||||
.bold()
|
||||
.size(50),
|
||||
)
|
||||
.push(container(text(&format!(
|
||||
.push(Container::new(text(format!(
|
||||
"Miner Fee: {} BTC",
|
||||
tx.fee_amount.to_btc()
|
||||
)))),
|
||||
@ -203,16 +203,23 @@ fn spend_header<'a>(tx: &SpendTx) -> Element<'a, Message> {
|
||||
|
||||
fn spend_overview_view<'a>(tx: &SpendTx) -> Element<'a, Message> {
|
||||
card::simple(
|
||||
column()
|
||||
.push(container(
|
||||
row()
|
||||
Column::new()
|
||||
.push(Container::new(
|
||||
Row::new()
|
||||
.push(
|
||||
container(
|
||||
row()
|
||||
.push(container(icon::key_icon().size(30).width(Length::Fill)))
|
||||
.push(column().push(text("Number of signatures:").bold()).push(
|
||||
text(&format!("{}", tx.psbt.inputs[0].partial_sigs.len(),)),
|
||||
Container::new(
|
||||
Row::new()
|
||||
.push(Container::new(
|
||||
icon::key_icon().size(30).width(Length::Fill),
|
||||
))
|
||||
.push(
|
||||
Column::new()
|
||||
.push(text("Number of signatures:").bold())
|
||||
.push(text(format!(
|
||||
"{}",
|
||||
tx.psbt.inputs[0].partial_sigs.len(),
|
||||
))),
|
||||
)
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(20),
|
||||
)
|
||||
@ -223,15 +230,15 @@ fn spend_overview_view<'a>(tx: &SpendTx) -> Element<'a, Message> {
|
||||
))
|
||||
.push(separation().width(Length::Fill))
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(text("Tx ID:").bold().width(Length::Fill))
|
||||
.push(text(&format!("{}", tx.psbt.unsigned_tx.txid())).small())
|
||||
.push(text(format!("{}", tx.psbt.unsigned_tx.txid())).small())
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(text("Psbt:").bold().width(Length::Fill))
|
||||
.push(
|
||||
button::transparent(Some(icon::clipboard_icon()), "Copy")
|
||||
@ -251,21 +258,21 @@ fn inputs_and_outputs_view<'a>(
|
||||
network: Network,
|
||||
change_index: Option<usize>,
|
||||
) -> Element<'a, Message> {
|
||||
column()
|
||||
Column::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.spacing(10)
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.spacing(10)
|
||||
.push(text("Spent coins:").bold())
|
||||
.push(coins.iter().fold(column().spacing(10), |col, coin| {
|
||||
.push(coins.iter().fold(Column::new().spacing(10), |col, coin| {
|
||||
col.push(
|
||||
card::simple(
|
||||
column()
|
||||
Column::new()
|
||||
.width(Length::Fill)
|
||||
.push(text(&format!("{} BTC", coin.amount.to_btc())).bold())
|
||||
.push(text(&format!("{}", coin.outpoint)).small()),
|
||||
.push(text(format!("{} BTC", coin.amount.to_btc())).bold())
|
||||
.push(text(format!("{}", coin.outpoint)).small()),
|
||||
)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
@ -273,28 +280,28 @@ fn inputs_and_outputs_view<'a>(
|
||||
.width(Length::FillPortion(1)),
|
||||
)
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.spacing(10)
|
||||
.push(text("Recipients:").bold())
|
||||
.push(psbt.unsigned_tx.output.iter().enumerate().fold(
|
||||
column().spacing(10),
|
||||
Column::new().spacing(10),
|
||||
|col, (i, output)| {
|
||||
col.push(
|
||||
card::simple(
|
||||
column()
|
||||
Column::new()
|
||||
.spacing(10)
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.width(Length::Fill)
|
||||
.push(
|
||||
text(&format!(
|
||||
text(format!(
|
||||
"{} BTC",
|
||||
Amount::from_sat(output.value).to_btc()
|
||||
))
|
||||
.bold(),
|
||||
)
|
||||
.push(
|
||||
text(&format!(
|
||||
text(format!(
|
||||
"{}",
|
||||
Address::from_script(
|
||||
&output.script_pubkey,
|
||||
@ -307,7 +314,7 @@ fn inputs_and_outputs_view<'a>(
|
||||
)
|
||||
.push_maybe(if Some(i) == change_index {
|
||||
Some(
|
||||
container(text("Change"))
|
||||
Container::new(text("Change"))
|
||||
.padding(5)
|
||||
.style(badge::PillStyle::Success),
|
||||
)
|
||||
@ -332,15 +339,15 @@ pub fn sign_action<'a>(
|
||||
signed: &[Fingerprint],
|
||||
) -> Element<'a, Message> {
|
||||
card::simple(
|
||||
column()
|
||||
Column::new()
|
||||
.push(if !hws.is_empty() {
|
||||
column()
|
||||
Column::new()
|
||||
.push(text("Select hardware wallet to sign with:").bold())
|
||||
.spacing(10)
|
||||
.push(
|
||||
hws.iter()
|
||||
.enumerate()
|
||||
.fold(column().spacing(10), |col, (i, hw)| {
|
||||
.fold(Column::new().spacing(10), |col, (i, hw)| {
|
||||
col.push(hw_list_view(
|
||||
i,
|
||||
hw,
|
||||
@ -352,10 +359,10 @@ pub fn sign_action<'a>(
|
||||
)
|
||||
.width(Length::Fill)
|
||||
} else {
|
||||
column()
|
||||
Column::new()
|
||||
.push(
|
||||
card::simple(
|
||||
column()
|
||||
Column::new()
|
||||
.spacing(20)
|
||||
.width(Length::Fill)
|
||||
.push("Please connect a hardware wallet")
|
||||
@ -380,18 +387,18 @@ fn hw_list_view<'a>(
|
||||
processing: bool,
|
||||
signed: bool,
|
||||
) -> Element<'a, Message> {
|
||||
let mut bttn = iced::pure::button(
|
||||
row()
|
||||
let mut bttn = Button::new(
|
||||
Row::new()
|
||||
.push(
|
||||
column()
|
||||
.push(text(&format!("{}", hw.kind)).bold())
|
||||
.push(text(&format!("fingerprint: {}", hw.fingerprint)).small())
|
||||
Column::new()
|
||||
.push(text(format!("{}", hw.kind)).bold())
|
||||
.push(text(format!("fingerprint: {}", hw.fingerprint)).small())
|
||||
.spacing(5)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push_maybe(if chosen && processing {
|
||||
Some(
|
||||
column()
|
||||
Column::new()
|
||||
.push(text("Processing..."))
|
||||
.push(text("Please check your device").small()),
|
||||
)
|
||||
@ -400,11 +407,11 @@ fn hw_list_view<'a>(
|
||||
})
|
||||
.push_maybe(if signed {
|
||||
Some(
|
||||
column().push(
|
||||
row()
|
||||
Column::new().push(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.push(icon::circle_check_icon().color(color::SUCCESS))
|
||||
.push(text("Signed").color(color::SUCCESS)),
|
||||
.push(icon::circle_check_icon().style(color::SUCCESS))
|
||||
.push(text("Signed").style(color::SUCCESS)),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
@ -414,12 +421,12 @@ fn hw_list_view<'a>(
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.padding(10)
|
||||
.style(button::Style::Border)
|
||||
.style(button::Style::Border.into())
|
||||
.width(Length::Fill);
|
||||
if !processing {
|
||||
bttn = bttn.on_press(Message::Spend(SpendTxMessage::SelectHardwareWallet(i)));
|
||||
}
|
||||
container(bttn)
|
||||
Container::new(bttn)
|
||||
.width(Length::Fill)
|
||||
.style(card::SimpleCardStyle)
|
||||
.into()
|
||||
|
||||
@ -2,8 +2,8 @@ pub mod detail;
|
||||
pub mod step;
|
||||
|
||||
use iced::{
|
||||
pure::{button, column, container, row, Element},
|
||||
Alignment, Length,
|
||||
widget::{Button, Column, Container, Row},
|
||||
Alignment, Element, Length,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@ -19,27 +19,27 @@ use crate::{
|
||||
use super::message::Message;
|
||||
|
||||
pub fn spend_view<'a>(spend_txs: &[SpendTx]) -> Element<'a, Message> {
|
||||
column()
|
||||
Column::new()
|
||||
.push(
|
||||
row().push(column().width(Length::Fill)).push(
|
||||
Row::new().push(Column::new().width(Length::Fill)).push(
|
||||
button::primary(Some(icon::plus_icon()), "Create a new transaction")
|
||||
.on_press(Message::Menu(Menu::CreateSpendTx)),
|
||||
),
|
||||
)
|
||||
.push(
|
||||
container(
|
||||
row()
|
||||
.push(text(&format!(" {}", spend_txs.len())).bold())
|
||||
Container::new(
|
||||
Row::new()
|
||||
.push(text(format!(" {}", spend_txs.len())).bold())
|
||||
.push(text(" draft transactions")),
|
||||
)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
column().spacing(10).push(
|
||||
Column::new().spacing(10).push(
|
||||
spend_txs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.fold(column().spacing(10), |col, (i, tx)| {
|
||||
.fold(Column::new().spacing(10), |col, (i, tx)| {
|
||||
col.push(spend_tx_list_view(i, tx))
|
||||
}),
|
||||
),
|
||||
@ -50,20 +50,20 @@ pub fn spend_view<'a>(spend_txs: &[SpendTx]) -> Element<'a, Message> {
|
||||
}
|
||||
|
||||
fn spend_tx_list_view<'a>(i: usize, tx: &SpendTx) -> Element<'a, Message> {
|
||||
container(
|
||||
button(
|
||||
row()
|
||||
Container::new(
|
||||
Button::new(
|
||||
Row::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(badge::spend())
|
||||
.push_maybe(match tx.status {
|
||||
SpendStatus::Deprecated => Some(
|
||||
container(text(" Deprecated ").small())
|
||||
Container::new(text(" Deprecated ").small())
|
||||
.padding(3)
|
||||
.style(badge::PillStyle::Simple),
|
||||
),
|
||||
SpendStatus::Broadcasted => Some(
|
||||
container(text(" Broadcasted ").small())
|
||||
Container::new(text(" Broadcasted ").small())
|
||||
.padding(3)
|
||||
.style(badge::PillStyle::Success),
|
||||
),
|
||||
@ -74,9 +74,9 @@ fn spend_tx_list_view<'a>(i: usize, tx: &SpendTx) -> Element<'a, Message> {
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
column()
|
||||
.push(text(&format!("{} BTC", tx.spend_amount.to_btc())).bold())
|
||||
.push(text(&format!("fee: {}", tx.fee_amount.to_btc())).small())
|
||||
Column::new()
|
||||
.push(text(format!("{} BTC", tx.spend_amount.to_btc())).bold())
|
||||
.push(text(format!("fee: {}", tx.fee_amount.to_btc())).small())
|
||||
.width(Length::Shrink),
|
||||
)
|
||||
.align_items(Alignment::Center)
|
||||
@ -84,7 +84,7 @@ fn spend_tx_list_view<'a>(i: usize, tx: &SpendTx) -> Element<'a, Message> {
|
||||
)
|
||||
.padding(10)
|
||||
.on_press(Message::Select(i))
|
||||
.style(button::Style::TransparentBorder),
|
||||
.style(button::Style::TransparentBorder.into()),
|
||||
)
|
||||
.style(card::SimpleCardStyle)
|
||||
.into()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use iced::{
|
||||
pure::{column, container, row, widget, Element},
|
||||
Alignment, Length,
|
||||
widget::{self, Button, Column, Container, Row},
|
||||
Alignment, Element, Length,
|
||||
};
|
||||
|
||||
use liana::miniscript::bitcoin::Amount;
|
||||
@ -28,10 +28,10 @@ pub fn choose_recipients_view(
|
||||
modal(
|
||||
false,
|
||||
None,
|
||||
column()
|
||||
Column::new()
|
||||
.push(text("Choose recipients").bold().size(50))
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.push(widget::Column::with_children(recipients).spacing(10))
|
||||
.push(
|
||||
button::transparent(Some(icon::plus_icon()), "Add recipient")
|
||||
@ -59,7 +59,7 @@ pub fn recipient_view<'a>(
|
||||
address: &form::Value<String>,
|
||||
amount: &form::Value<String>,
|
||||
) -> Element<'a, CreateSpendMessage> {
|
||||
row()
|
||||
Row::new()
|
||||
.push(
|
||||
form::Form::new("Address", address, move |msg| {
|
||||
CreateSpendMessage::RecipientEdited(index, "address", msg)
|
||||
@ -69,7 +69,7 @@ pub fn recipient_view<'a>(
|
||||
.padding(10),
|
||||
)
|
||||
.push(
|
||||
container(
|
||||
Container::new(
|
||||
form::Form::new("Amount", amount, move |msg| {
|
||||
CreateSpendMessage::RecipientEdited(index, "amount", msg)
|
||||
})
|
||||
@ -97,10 +97,10 @@ pub fn choose_feerate_view<'a>(
|
||||
modal(
|
||||
true,
|
||||
None,
|
||||
column()
|
||||
Column::new()
|
||||
.push(text("Choose feerate").bold().size(50))
|
||||
.push(
|
||||
container(
|
||||
Container::new(
|
||||
form::Form::new("Feerate", feerate, move |msg| {
|
||||
Message::CreateSpend(CreateSpendMessage::FeerateEdited(msg))
|
||||
})
|
||||
@ -110,7 +110,7 @@ pub fn choose_feerate_view<'a>(
|
||||
)
|
||||
.width(Length::Units(250)),
|
||||
)
|
||||
.push_maybe(error.map(|e| card::error("Failed to create spend", &e.to_string())))
|
||||
.push_maybe(error.map(|e| card::error("Failed to create spend", e.to_string())))
|
||||
.push_maybe(if is_valid {
|
||||
Some(
|
||||
button::primary(None, "Next")
|
||||
@ -133,26 +133,26 @@ pub fn choose_coins_view<'a>(
|
||||
modal(
|
||||
true,
|
||||
None,
|
||||
column()
|
||||
Column::new()
|
||||
.push(text("Choose coins").bold().size(50))
|
||||
.push(
|
||||
column().spacing(10).push(
|
||||
Column::new().spacing(10).push(
|
||||
coins
|
||||
.iter()
|
||||
.enumerate()
|
||||
.fold(column().spacing(10), |col, (i, (coin, selected))| {
|
||||
.fold(Column::new().spacing(10), |col, (i, (coin, selected))| {
|
||||
col.push(coin_list_view(i, coin, *selected))
|
||||
}),
|
||||
),
|
||||
)
|
||||
.push_maybe(if is_valid {
|
||||
Some(container(
|
||||
Some(Container::new(
|
||||
button::primary(None, "Next")
|
||||
.on_press(Message::Next)
|
||||
.width(Length::Units(100)),
|
||||
))
|
||||
} else if total_needed.is_some() {
|
||||
Some(container(card::warning(&format!(
|
||||
Some(Container::new(card::warning(format!(
|
||||
"Total amount must be superior to {}",
|
||||
total_needed.unwrap().to_btc(),
|
||||
))))
|
||||
@ -165,24 +165,24 @@ pub fn choose_coins_view<'a>(
|
||||
}
|
||||
|
||||
fn coin_list_view<'a>(i: usize, coin: &Coin, selected: bool) -> Element<'a, Message> {
|
||||
container(
|
||||
iced::pure::button(
|
||||
row()
|
||||
Container::new(
|
||||
Button::new(
|
||||
Row::new()
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(if selected {
|
||||
icon::square_check_icon()
|
||||
} else {
|
||||
icon::square_icon()
|
||||
})
|
||||
.push(badge::coin())
|
||||
.push(text(&format!("block: {}", coin.block_height.unwrap_or(0))).small())
|
||||
.push(text(format!("block: {}", coin.block_height.unwrap_or(0))).small())
|
||||
.spacing(10)
|
||||
.align_items(Alignment::Center)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(
|
||||
text(&format!("{} BTC", coin.amount.to_btc()))
|
||||
text(format!("{} BTC", coin.amount.to_btc()))
|
||||
.bold()
|
||||
.width(Length::Shrink),
|
||||
)
|
||||
@ -191,7 +191,7 @@ fn coin_list_view<'a>(i: usize, coin: &Coin, selected: bool) -> Element<'a, Mess
|
||||
)
|
||||
.padding(10)
|
||||
.on_press(Message::CreateSpend(CreateSpendMessage::SelectCoin(i)))
|
||||
.style(button::Style::TransparentBorder),
|
||||
.style(button::Style::TransparentBorder.into()),
|
||||
)
|
||||
.style(card::SimpleCardStyle)
|
||||
.into()
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
use std::convert::From;
|
||||
|
||||
use iced::{
|
||||
pure::{column, container, row, widget},
|
||||
widget::{self, Column, Container},
|
||||
Length,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app::error::Error,
|
||||
daemon::{client::error::RpcErrorCode, DaemonError},
|
||||
ui::{color, component::text::*, icon},
|
||||
ui::component::notification,
|
||||
};
|
||||
|
||||
/// Simple warning message displayed to non technical user.
|
||||
@ -47,52 +47,8 @@ impl std::fmt::Display for WarningMessage {
|
||||
pub fn warn<'a, T: 'a>(error: Option<&Error>) -> widget::Container<'a, T> {
|
||||
if let Some(w) = error {
|
||||
let message: WarningMessage = w.into();
|
||||
warning(&message.to_string(), &w.to_string()).width(Length::Fill)
|
||||
notification::warning(message.to_string(), w.to_string()).width(Length::Fill)
|
||||
} else {
|
||||
container(column()).width(Length::Fill)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn warning<'a, T: 'a>(message: &str, error: &str) -> widget::Container<'a, T> {
|
||||
container(
|
||||
widget::Tooltip::new(
|
||||
row()
|
||||
.push(icon::warning_icon())
|
||||
.push(text(message))
|
||||
.spacing(20),
|
||||
error,
|
||||
widget::tooltip::Position::Bottom,
|
||||
)
|
||||
.style(TooltipWarningStyle),
|
||||
)
|
||||
.padding(15)
|
||||
.center_x()
|
||||
.style(WarningStyle)
|
||||
.width(Length::Fill)
|
||||
}
|
||||
|
||||
struct WarningStyle;
|
||||
impl widget::container::StyleSheet for WarningStyle {
|
||||
fn style(&self) -> widget::container::Style {
|
||||
widget::container::Style {
|
||||
border_radius: 0.0,
|
||||
text_color: iced::Color::BLACK.into(),
|
||||
background: color::WARNING.into(),
|
||||
border_color: color::WARNING,
|
||||
..widget::container::Style::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TooltipWarningStyle;
|
||||
impl widget::container::StyleSheet for TooltipWarningStyle {
|
||||
fn style(&self) -> widget::container::Style {
|
||||
widget::container::Style {
|
||||
border_radius: 0.0,
|
||||
border_width: 1.0,
|
||||
text_color: color::WARNING.into(),
|
||||
background: color::FOREGROUND.into(),
|
||||
border_color: color::WARNING,
|
||||
}
|
||||
Container::new(Column::new()).width(Length::Fill)
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,8 +3,7 @@ mod message;
|
||||
mod step;
|
||||
mod view;
|
||||
|
||||
use iced::pure::Element;
|
||||
use iced::{clipboard, Command, Subscription};
|
||||
use iced::{clipboard, Command, Element, Subscription};
|
||||
use iced_native::{window, Event};
|
||||
use liana::miniscript::bitcoin;
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use iced::{pure::Element, Command};
|
||||
use iced::{Command, Element};
|
||||
use liana::{
|
||||
descriptors::MultipathDescriptor,
|
||||
miniscript::{
|
||||
@ -424,7 +424,7 @@ impl Step for RegisterDescriptor {
|
||||
fn view(&self) -> Element<Message> {
|
||||
let desc = self.descriptor.as_ref().unwrap();
|
||||
view::register_descriptor(
|
||||
&desc.to_string(),
|
||||
desc.to_string(),
|
||||
&self.hws,
|
||||
self.error.as_ref(),
|
||||
self.processing,
|
||||
|
||||
@ -6,7 +6,7 @@ use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use async_hwi::DeviceKind;
|
||||
use iced::{pure::Element, Command};
|
||||
use iced::{Command, Element};
|
||||
use liana::{
|
||||
config::{BitcoinConfig, BitcoindConfig},
|
||||
descriptors::MultipathDescriptor,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use iced::pure::{column, container, pick_list, row, scrollable, widget, Element};
|
||||
use iced::{Alignment, Length};
|
||||
use iced::widget::{Button, Column, Container, PickList, Row, Scrollable};
|
||||
use iced::{Alignment, Element, Length};
|
||||
|
||||
use liana::miniscript::bitcoin;
|
||||
|
||||
@ -12,7 +12,7 @@ use crate::{
|
||||
ui::{
|
||||
color,
|
||||
component::{
|
||||
button, card, form,
|
||||
button, card, container, form,
|
||||
text::{text, Text},
|
||||
},
|
||||
icon,
|
||||
@ -28,19 +28,19 @@ const NETWORKS: [bitcoin::Network; 4] = [
|
||||
];
|
||||
|
||||
pub fn welcome(network: &bitcoin::Network, valid: bool) -> Element<Message> {
|
||||
container(container(
|
||||
column()
|
||||
.push(container(
|
||||
pick_list(&NETWORKS[..], Some(*network), message::Message::Network).padding(10),
|
||||
Container::new(Container::new(
|
||||
Column::new()
|
||||
.push(Container::new(
|
||||
PickList::new(&NETWORKS[..], Some(*network), message::Message::Network).padding(10),
|
||||
))
|
||||
.push(if valid {
|
||||
container(
|
||||
Container::new(
|
||||
button::primary(None, "Start the install")
|
||||
.on_press(Message::Next)
|
||||
.width(Length::Units(200)),
|
||||
)
|
||||
} else {
|
||||
card::warning("A data directory already exists for this network")
|
||||
card::warning("A data directory already exists for this network".to_string())
|
||||
})
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
@ -63,7 +63,7 @@ pub fn define_descriptor<'a>(
|
||||
sequence: &form::Value<String>,
|
||||
error: Option<&String>,
|
||||
) -> Element<'a, Message> {
|
||||
let col_descriptor = column()
|
||||
let col_descriptor = Column::new()
|
||||
.push(text("Descriptor:").bold())
|
||||
.push(
|
||||
form::Form::new("Descriptor", imported_descriptor, |msg| {
|
||||
@ -75,10 +75,10 @@ pub fn define_descriptor<'a>(
|
||||
)
|
||||
.spacing(10);
|
||||
|
||||
let col_user_xpub = column()
|
||||
let col_user_xpub = Column::new()
|
||||
.push(text("Your xpub:").bold())
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(
|
||||
form::Form::new("Xpub", user_xpub, |msg| {
|
||||
Message::DefineDescriptor(message::DefineDescriptor::UserXpubEdited(msg))
|
||||
@ -99,10 +99,10 @@ pub fn define_descriptor<'a>(
|
||||
)
|
||||
.spacing(10);
|
||||
|
||||
let col_heir_xpub = column()
|
||||
let col_heir_xpub = Column::new()
|
||||
.push(text("Heir xpub:").bold())
|
||||
.push(
|
||||
row()
|
||||
Row::new()
|
||||
.push(
|
||||
form::Form::new("Xpub", heir_xpub, |msg| {
|
||||
Message::DefineDescriptor(message::DefineDescriptor::HeirXpubEdited(msg))
|
||||
@ -123,10 +123,10 @@ pub fn define_descriptor<'a>(
|
||||
)
|
||||
.spacing(10);
|
||||
|
||||
let col_sequence = column()
|
||||
let col_sequence = Column::new()
|
||||
.push(text("Number of block:").bold())
|
||||
.push(
|
||||
container(
|
||||
Container::new(
|
||||
form::Form::new("Number of block", sequence, |msg| {
|
||||
Message::DefineDescriptor(message::DefineDescriptor::SequenceEdited(msg))
|
||||
})
|
||||
@ -139,10 +139,10 @@ pub fn define_descriptor<'a>(
|
||||
.spacing(10);
|
||||
|
||||
layout(
|
||||
column()
|
||||
Column::new()
|
||||
.push(text("Create the descriptor").bold().size(50))
|
||||
.push(
|
||||
column()
|
||||
Column::new()
|
||||
.push(col_user_xpub)
|
||||
.push(col_sequence)
|
||||
.push(col_heir_xpub)
|
||||
@ -163,7 +163,7 @@ pub fn define_descriptor<'a>(
|
||||
.on_press(Message::Next)
|
||||
},
|
||||
)
|
||||
.push_maybe(error.map(|e| card::error("Failed to create descriptor", e)))
|
||||
.push_maybe(error.map(|e| card::error("Failed to create descriptor", e.to_string())))
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.padding(100)
|
||||
@ -173,34 +173,34 @@ pub fn define_descriptor<'a>(
|
||||
}
|
||||
|
||||
pub fn register_descriptor<'a>(
|
||||
descriptor: &str,
|
||||
descriptor: String,
|
||||
hws: &[(HardwareWallet, Option<[u8; 32]>)],
|
||||
error: Option<&Error>,
|
||||
processing: bool,
|
||||
chosen_hw: Option<usize>,
|
||||
) -> Element<'a, Message> {
|
||||
layout(
|
||||
column()
|
||||
Column::new()
|
||||
.push(text("Register descriptor").bold().size(50))
|
||||
.push(
|
||||
column()
|
||||
.push(text(descriptor).small())
|
||||
Column::new()
|
||||
.push(text(descriptor.clone()).small())
|
||||
.push(
|
||||
button::transparent_border(Some(icon::clipboard_icon()), "Copy")
|
||||
.on_press(Message::Clibpboard(descriptor.to_string())),
|
||||
.on_press(Message::Clibpboard(descriptor)),
|
||||
)
|
||||
.spacing(10)
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
.push_maybe(error.map(|e| card::error("Failed to import xpub", &e.to_string())))
|
||||
.push_maybe(error.map(|e| card::error("Failed to import xpub", e.to_string())))
|
||||
.push(if !hws.is_empty() {
|
||||
column()
|
||||
.push(text(&format!("{} hardware wallets connected", hws.len())).bold())
|
||||
Column::new()
|
||||
.push(text(format!("{} hardware wallets connected", hws.len())).bold())
|
||||
.spacing(10)
|
||||
.push(
|
||||
hws.iter()
|
||||
.enumerate()
|
||||
.fold(column().spacing(10), |col, (i, hw)| {
|
||||
.fold(Column::new().spacing(10), |col, (i, hw)| {
|
||||
col.push(hw_list_view(
|
||||
i,
|
||||
&hw.0,
|
||||
@ -212,8 +212,8 @@ pub fn register_descriptor<'a>(
|
||||
)
|
||||
.width(Length::Fill)
|
||||
} else {
|
||||
column().push(card::simple(
|
||||
column()
|
||||
Column::new().push(card::simple(
|
||||
Column::new()
|
||||
.spacing(20)
|
||||
.push("No hardware wallet connected")
|
||||
.push(button::primary(None, "Refresh").on_press(Message::Reload))
|
||||
@ -238,7 +238,7 @@ pub fn define_bitcoin<'a>(
|
||||
address: &form::Value<String>,
|
||||
cookie_path: &form::Value<String>,
|
||||
) -> Element<'a, Message> {
|
||||
let col_address = column()
|
||||
let col_address = Column::new()
|
||||
.push(text("Address:").bold())
|
||||
.push(
|
||||
form::Form::new("Address", address, |msg| {
|
||||
@ -250,7 +250,7 @@ pub fn define_bitcoin<'a>(
|
||||
)
|
||||
.spacing(10);
|
||||
|
||||
let col_cookie = column()
|
||||
let col_cookie = Column::new()
|
||||
.push(text("Cookie path:").bold())
|
||||
.push(
|
||||
form::Form::new("Cookie path", cookie_path, |msg| {
|
||||
@ -263,7 +263,7 @@ pub fn define_bitcoin<'a>(
|
||||
.spacing(10);
|
||||
|
||||
layout(
|
||||
column()
|
||||
Column::new()
|
||||
.push(
|
||||
text("Set up connection to the Bitcoin full node")
|
||||
.bold()
|
||||
@ -287,9 +287,9 @@ pub fn define_bitcoin<'a>(
|
||||
pub fn install<'a>(
|
||||
generating: bool,
|
||||
config_path: Option<&std::path::PathBuf>,
|
||||
warning: Option<&String>,
|
||||
warning: Option<&'a String>,
|
||||
) -> Element<'a, Message> {
|
||||
let mut col = column()
|
||||
let mut col = Column::new()
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.padding(100)
|
||||
@ -304,10 +304,10 @@ pub fn install<'a>(
|
||||
col = col.push(button::primary(None, "Installing ...").width(Length::Units(200)))
|
||||
} else if let Some(path) = config_path {
|
||||
col = col.push(
|
||||
container(
|
||||
column()
|
||||
.push(container(text("Installed !")))
|
||||
.push(container(
|
||||
Container::new(
|
||||
Column::new()
|
||||
.push(Container::new(text("Installed !")))
|
||||
.push(Container::new(
|
||||
button::primary(None, "Start")
|
||||
.on_press(Message::Exit(path.clone()))
|
||||
.width(Length::Units(200)),
|
||||
@ -338,7 +338,7 @@ pub fn hardware_wallet_xpubs_modal<'a>(
|
||||
chosen_hw: Option<usize>,
|
||||
) -> Element<'a, Message> {
|
||||
modal(
|
||||
column()
|
||||
Column::new()
|
||||
.push(
|
||||
text(if is_heir {
|
||||
"Import the Heir xpub"
|
||||
@ -348,15 +348,15 @@ pub fn hardware_wallet_xpubs_modal<'a>(
|
||||
.bold()
|
||||
.size(50),
|
||||
)
|
||||
.push_maybe(error.map(|e| card::error("Failed to import xpub", &e.to_string())))
|
||||
.push_maybe(error.map(|e| card::error("Failed to import xpub", e.to_string())))
|
||||
.push(if !hws.is_empty() {
|
||||
column()
|
||||
.push(text(&format!("{} hardware wallets connected", hws.len())).bold())
|
||||
Column::new()
|
||||
.push(text(format!("{} hardware wallets connected", hws.len())).bold())
|
||||
.spacing(10)
|
||||
.push(
|
||||
hws.iter()
|
||||
.enumerate()
|
||||
.fold(column().spacing(10), |col, (i, hw)| {
|
||||
.fold(Column::new().spacing(10), |col, (i, hw)| {
|
||||
col.push(hw_list_view(
|
||||
i,
|
||||
hw,
|
||||
@ -368,10 +368,10 @@ pub fn hardware_wallet_xpubs_modal<'a>(
|
||||
)
|
||||
.width(Length::Fill)
|
||||
} else {
|
||||
column()
|
||||
Column::new()
|
||||
.push(
|
||||
card::simple(
|
||||
column()
|
||||
Column::new()
|
||||
.spacing(20)
|
||||
.width(Length::Fill)
|
||||
.push("Please connect a hardware wallet")
|
||||
@ -397,18 +397,18 @@ fn hw_list_view<'a>(
|
||||
processing: bool,
|
||||
registered: bool,
|
||||
) -> Element<'a, Message> {
|
||||
let mut bttn = iced::pure::button(
|
||||
row()
|
||||
let mut bttn = Button::new(
|
||||
Row::new()
|
||||
.push(
|
||||
column()
|
||||
.push(text(&format!("{}", hw.kind)).bold())
|
||||
.push(text(&format!("fingerprint: {}", hw.fingerprint)).small())
|
||||
Column::new()
|
||||
.push(text(format!("{}", hw.kind)).bold())
|
||||
.push(text(format!("fingerprint: {}", hw.fingerprint)).small())
|
||||
.spacing(5)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push_maybe(if chosen && processing {
|
||||
Some(
|
||||
column()
|
||||
Column::new()
|
||||
.push(text("Processing..."))
|
||||
.push(text("Please check your device").small()),
|
||||
)
|
||||
@ -416,7 +416,7 @@ fn hw_list_view<'a>(
|
||||
None
|
||||
})
|
||||
.push_maybe(if registered {
|
||||
Some(column().push(icon::circle_check_icon().color(color::SUCCESS)))
|
||||
Some(Column::new().push(icon::circle_check_icon().style(color::SUCCESS)))
|
||||
} else {
|
||||
None
|
||||
})
|
||||
@ -424,59 +424,49 @@ fn hw_list_view<'a>(
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.padding(10)
|
||||
.style(button::Style::TransparentBorder)
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.width(Length::Fill);
|
||||
if !processing {
|
||||
bttn = bttn.on_press(Message::Select(i));
|
||||
}
|
||||
container(bttn)
|
||||
Container::new(bttn)
|
||||
.width(Length::Fill)
|
||||
.style(card::SimpleCardStyle)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn layout<'a>(content: impl Into<Element<'a, Message>>) -> Element<'a, Message> {
|
||||
container(scrollable(
|
||||
column()
|
||||
Container::new(Scrollable::new(
|
||||
Column::new()
|
||||
.push(
|
||||
container(button::transparent(None, "< Previous").on_press(Message::Previous))
|
||||
Container::new(button::transparent(None, "< Previous").on_press(Message::Previous))
|
||||
.padding(5),
|
||||
)
|
||||
.push(container(content).width(Length::Fill).center_x()),
|
||||
.push(Container::new(content).width(Length::Fill).center_x()),
|
||||
))
|
||||
.center_x()
|
||||
.height(Length::Fill)
|
||||
.width(Length::Fill)
|
||||
.style(BackgroundStyle)
|
||||
.style(container::Style::Background)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn modal<'a>(content: impl Into<Element<'a, Message>>) -> Element<'a, Message> {
|
||||
container(scrollable(
|
||||
column()
|
||||
Container::new(Scrollable::new(
|
||||
Column::new()
|
||||
.push(
|
||||
row().push(column().width(Length::Fill)).push(
|
||||
container(
|
||||
Row::new().push(Column::new().width(Length::Fill)).push(
|
||||
Container::new(
|
||||
button::primary(Some(icon::cross_icon()), "Close").on_press(Message::Close),
|
||||
)
|
||||
.padding(10),
|
||||
),
|
||||
)
|
||||
.push(container(content).width(Length::Fill).center_x()),
|
||||
.push(Container::new(content).width(Length::Fill).center_x()),
|
||||
))
|
||||
.center_x()
|
||||
.height(Length::Fill)
|
||||
.width(Length::Fill)
|
||||
.style(BackgroundStyle)
|
||||
.style(container::Style::Background)
|
||||
.into()
|
||||
}
|
||||
|
||||
pub struct BackgroundStyle;
|
||||
impl widget::container::StyleSheet for BackgroundStyle {
|
||||
fn style(&self) -> widget::container::Style {
|
||||
widget::container::Style {
|
||||
background: color::BACKGROUND.into(),
|
||||
..widget::container::Style::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,10 @@ use std::io::ErrorKind;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::pure::{column, text, Element};
|
||||
use iced::{
|
||||
widget::{Column, Text},
|
||||
Element,
|
||||
};
|
||||
use iced::{Alignment, Command, Subscription};
|
||||
use iced_native::{window, Event};
|
||||
use log::{debug, info};
|
||||
@ -199,16 +202,16 @@ impl Loader {
|
||||
|
||||
pub fn view(&self) -> Element<Message> {
|
||||
match &self.step {
|
||||
Step::StartingDaemon => cover(text("Starting daemon...")),
|
||||
Step::Connecting => cover(text("Connecting to daemon...")),
|
||||
Step::Syncing { progress, .. } => cover(text(&format!("Syncing... {}%", progress))),
|
||||
Step::Error(error) => cover(text(&format!("Error: {}", error))),
|
||||
Step::StartingDaemon => cover(Text::new("Starting daemon...")),
|
||||
Step::Connecting => cover(Text::new("Connecting to daemon...")),
|
||||
Step::Syncing { progress, .. } => cover(Text::new(format!("Syncing... {}%", progress))),
|
||||
Step::Error(error) => cover(Text::new(format!("Error: {}", error))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cover<'a, T: 'a, C: Into<Element<'a, T>>>(content: C) -> Element<'a, T> {
|
||||
column()
|
||||
Column::new()
|
||||
.push(content)
|
||||
.width(iced::Length::Fill)
|
||||
.height(iced::Length::Fill)
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use std::{error::Error, path::PathBuf, str::FromStr};
|
||||
|
||||
use iced::pure::{Application, Element};
|
||||
use iced::{executor, Command, Settings, Subscription};
|
||||
use iced::{executor, Application, Command, Element, Settings, Subscription};
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
|
||||
@ -94,6 +93,7 @@ impl Application for GUI {
|
||||
type Executor = executor::Default;
|
||||
type Message = Message;
|
||||
type Flags = Config;
|
||||
type Theme = iced::Theme;
|
||||
|
||||
fn title(&self) -> String {
|
||||
match self.state {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use iced::{
|
||||
pure::{container, widget, Element},
|
||||
Length,
|
||||
widget::{self, Container},
|
||||
Element, Length,
|
||||
};
|
||||
|
||||
use crate::ui::{color, icon};
|
||||
@ -12,36 +12,49 @@ pub enum Style {
|
||||
}
|
||||
|
||||
impl widget::container::StyleSheet for Style {
|
||||
fn style(&self) -> widget::container::Style {
|
||||
type Style = iced::Theme;
|
||||
fn appearance(&self, _style: &Self::Style) -> widget::container::Appearance {
|
||||
match self {
|
||||
Self::Standard => widget::container::Style {
|
||||
Self::Standard => widget::container::Appearance {
|
||||
border_radius: 40.0,
|
||||
background: color::BACKGROUND.into(),
|
||||
..widget::container::Style::default()
|
||||
..widget::container::Appearance::default()
|
||||
},
|
||||
Self::Success => widget::container::Style {
|
||||
Self::Success => widget::container::Appearance {
|
||||
border_radius: 40.0,
|
||||
background: color::SUCCESS_LIGHT.into(),
|
||||
text_color: color::SUCCESS.into(),
|
||||
..widget::container::Style::default()
|
||||
..widget::container::Appearance::default()
|
||||
},
|
||||
Self::Warning => widget::container::Style {
|
||||
Self::Warning => widget::container::Appearance {
|
||||
border_radius: 40.0,
|
||||
background: color::WARNING_LIGHT.into(),
|
||||
text_color: color::WARNING.into(),
|
||||
..widget::container::Style::default()
|
||||
..widget::container::Appearance::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Badge<S: widget::container::StyleSheet> {
|
||||
icon: widget::Text,
|
||||
style: S,
|
||||
impl From<Style> for Box<dyn widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
fn from(s: Style) -> Box<dyn widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
Box::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Badge<Style> {
|
||||
pub fn new(icon: widget::Text) -> Self {
|
||||
impl From<Style> for iced::theme::Container {
|
||||
fn from(i: Style) -> iced::theme::Container {
|
||||
iced::theme::Container::Custom(i.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Badge {
|
||||
icon: widget::Text<'static>,
|
||||
style: Style,
|
||||
}
|
||||
|
||||
impl Badge {
|
||||
pub fn new(icon: widget::Text<'static>) -> Self {
|
||||
Self {
|
||||
icon,
|
||||
style: Style::Standard,
|
||||
@ -55,11 +68,9 @@ impl Badge<Style> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message: 'a, S: 'a + widget::container::StyleSheet> From<Badge<S>>
|
||||
for Element<'a, Message>
|
||||
{
|
||||
fn from(badge: Badge<S>) -> Element<'a, Message> {
|
||||
container(badge.icon.width(Length::Units(20)))
|
||||
impl<'a, Message: 'a> From<Badge> for Element<'a, Message> {
|
||||
fn from(badge: Badge) -> Element<'a, Message> {
|
||||
Container::new(badge.icon.width(Length::Units(20)))
|
||||
.width(Length::Units(40))
|
||||
.height(Length::Units(40))
|
||||
.style(badge.style)
|
||||
@ -69,51 +80,29 @@ impl<'a, Message: 'a, S: 'a + widget::container::StyleSheet> From<Badge<S>>
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ReceiveStyle;
|
||||
impl widget::container::StyleSheet for ReceiveStyle {
|
||||
fn style(&self) -> widget::container::Style {
|
||||
widget::container::Style {
|
||||
border_radius: 40.0,
|
||||
background: color::BACKGROUND.into(),
|
||||
..widget::container::Style::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn receive<T>() -> widget::container::Container<'static, T> {
|
||||
container(icon::receive_icon().width(Length::Units(20)))
|
||||
Container::new(icon::receive_icon().width(Length::Units(20)))
|
||||
.width(Length::Units(40))
|
||||
.height(Length::Units(40))
|
||||
.style(ReceiveStyle)
|
||||
.style(Style::Standard)
|
||||
.center_x()
|
||||
.center_y()
|
||||
}
|
||||
|
||||
pub struct SpendStyle;
|
||||
impl widget::container::StyleSheet for SpendStyle {
|
||||
fn style(&self) -> widget::container::Style {
|
||||
widget::container::Style {
|
||||
border_radius: 40.0,
|
||||
background: color::BACKGROUND.into(),
|
||||
..widget::container::Style::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spend<T>() -> widget::container::Container<'static, T> {
|
||||
container(icon::send_icon().width(Length::Units(20)))
|
||||
Container::new(icon::send_icon().width(Length::Units(20)))
|
||||
.width(Length::Units(40))
|
||||
.height(Length::Units(40))
|
||||
.style(ReceiveStyle)
|
||||
.style(Style::Standard)
|
||||
.center_x()
|
||||
.center_y()
|
||||
}
|
||||
|
||||
pub fn coin<T>() -> widget::container::Container<'static, T> {
|
||||
container(icon::coin_icon().width(Length::Units(20)))
|
||||
Container::new(icon::coin_icon().width(Length::Units(20)))
|
||||
.width(Length::Units(40))
|
||||
.height(Length::Units(40))
|
||||
.style(ReceiveStyle)
|
||||
.style(Style::Standard)
|
||||
.center_x()
|
||||
.center_y()
|
||||
}
|
||||
@ -126,32 +115,45 @@ pub enum PillStyle {
|
||||
}
|
||||
|
||||
impl widget::container::StyleSheet for PillStyle {
|
||||
fn style(&self) -> widget::container::Style {
|
||||
type Style = iced::Theme;
|
||||
fn appearance(&self, _style: &Self::Style) -> widget::container::Appearance {
|
||||
match self {
|
||||
Self::Primary => widget::container::Style {
|
||||
Self::Primary => widget::container::Appearance {
|
||||
background: color::PRIMARY.into(),
|
||||
border_radius: 10.0,
|
||||
text_color: iced::Color::WHITE.into(),
|
||||
..widget::container::Style::default()
|
||||
..widget::container::Appearance::default()
|
||||
},
|
||||
Self::InversePrimary => widget::container::Style {
|
||||
Self::InversePrimary => widget::container::Appearance {
|
||||
background: color::FOREGROUND.into(),
|
||||
border_radius: 10.0,
|
||||
text_color: color::PRIMARY.into(),
|
||||
..widget::container::Style::default()
|
||||
..widget::container::Appearance::default()
|
||||
},
|
||||
Self::Success => widget::container::Style {
|
||||
Self::Success => widget::container::Appearance {
|
||||
background: color::SUCCESS.into(),
|
||||
border_radius: 10.0,
|
||||
text_color: iced::Color::WHITE.into(),
|
||||
..widget::container::Style::default()
|
||||
..widget::container::Appearance::default()
|
||||
},
|
||||
Self::Simple => widget::container::Style {
|
||||
Self::Simple => widget::container::Appearance {
|
||||
background: color::BACKGROUND.into(),
|
||||
border_radius: 10.0,
|
||||
text_color: iced::Color::BLACK.into(),
|
||||
..widget::container::Style::default()
|
||||
..widget::container::Appearance::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PillStyle> for Box<dyn widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
fn from(s: PillStyle) -> Box<dyn widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
Box::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PillStyle> for iced::theme::Container {
|
||||
fn from(i: PillStyle) -> iced::theme::Container {
|
||||
iced::theme::Container::Custom(i.into())
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,33 +1,33 @@
|
||||
use iced::pure::{
|
||||
container, row,
|
||||
widget::{button, Container},
|
||||
};
|
||||
use iced::widget::{button, container, Container, Row, Text};
|
||||
use iced::{Alignment, Color, Length, Vector};
|
||||
|
||||
use super::text::text;
|
||||
use crate::ui::color;
|
||||
|
||||
pub fn alert<'a, T: 'a>(icon: Option<iced::Text>, t: &str) -> button::Button<'a, T> {
|
||||
button::Button::new(content(icon, t)).style(Style::Destructive)
|
||||
pub fn alert<'a, T: 'a>(icon: Option<Text<'a>>, t: &'static str) -> button::Button<'a, T> {
|
||||
button::Button::new(content(icon, t)).style(Style::Destructive.into())
|
||||
}
|
||||
|
||||
pub fn primary<'a, T: 'a>(icon: Option<iced::Text>, t: &str) -> button::Button<'a, T> {
|
||||
button::Button::new(content(icon, t)).style(Style::Primary)
|
||||
pub fn primary<'a, T: 'a>(icon: Option<Text<'a>>, t: &'static str) -> button::Button<'a, T> {
|
||||
button::Button::new(content(icon, t)).style(Style::Primary.into())
|
||||
}
|
||||
|
||||
pub fn transparent<'a, T: 'a>(icon: Option<iced::Text>, t: &str) -> button::Button<'a, T> {
|
||||
button::Button::new(content(icon, t)).style(Style::Transparent)
|
||||
pub fn transparent<'a, T: 'a>(icon: Option<Text<'a>>, t: &'static str) -> button::Button<'a, T> {
|
||||
button::Button::new(content(icon, t)).style(Style::Transparent.into())
|
||||
}
|
||||
|
||||
pub fn transparent_border<'a, T: 'a>(icon: Option<iced::Text>, t: &str) -> button::Button<'a, T> {
|
||||
button::Button::new(content(icon, t)).style(Style::TransparentBorder)
|
||||
pub fn transparent_border<'a, T: 'a>(
|
||||
icon: Option<Text<'a>>,
|
||||
t: &'static str,
|
||||
) -> button::Button<'a, T> {
|
||||
button::Button::new(content(icon, t)).style(Style::TransparentBorder.into())
|
||||
}
|
||||
|
||||
fn content<'a, T: 'a>(icon: Option<iced::Text>, t: &str) -> Container<'a, T> {
|
||||
fn content<'a, T: 'a>(icon: Option<Text<'a>>, t: &'static str) -> Container<'a, T> {
|
||||
match icon {
|
||||
None => container(text(t)).width(Length::Fill).center_x().padding(5),
|
||||
Some(i) => container(
|
||||
row()
|
||||
Row::new()
|
||||
.push(i)
|
||||
.push(text(t))
|
||||
.spacing(10)
|
||||
@ -50,9 +50,10 @@ pub enum Style {
|
||||
}
|
||||
|
||||
impl button::StyleSheet for Style {
|
||||
fn active(&self) -> button::Style {
|
||||
type Style = iced::Theme;
|
||||
fn active(&self, _style: &Self::Style) -> button::Appearance {
|
||||
match self {
|
||||
Style::Primary => button::Style {
|
||||
Style::Primary => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: color::PRIMARY.into(),
|
||||
border_radius: 10.0,
|
||||
@ -60,7 +61,7 @@ impl button::StyleSheet for Style {
|
||||
border_color: Color::TRANSPARENT,
|
||||
text_color: color::FOREGROUND,
|
||||
},
|
||||
Style::Destructive => button::Style {
|
||||
Style::Destructive => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: color::FOREGROUND.into(),
|
||||
border_radius: 10.0,
|
||||
@ -68,7 +69,7 @@ impl button::StyleSheet for Style {
|
||||
border_color: color::ALERT,
|
||||
text_color: color::ALERT,
|
||||
},
|
||||
Style::Transparent | Style::TransparentBorder => button::Style {
|
||||
Style::Transparent | Style::TransparentBorder => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
@ -76,7 +77,7 @@ impl button::StyleSheet for Style {
|
||||
border_color: Color::TRANSPARENT,
|
||||
text_color: Color::BLACK,
|
||||
},
|
||||
Style::Border => button::Style {
|
||||
Style::Border => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
@ -87,9 +88,9 @@ impl button::StyleSheet for Style {
|
||||
}
|
||||
}
|
||||
|
||||
fn hovered(&self) -> button::Style {
|
||||
fn hovered(&self, _style: &Self::Style) -> button::Appearance {
|
||||
match self {
|
||||
Style::Primary => button::Style {
|
||||
Style::Primary => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: color::PRIMARY.into(),
|
||||
border_radius: 10.0,
|
||||
@ -97,7 +98,7 @@ impl button::StyleSheet for Style {
|
||||
border_color: Color::TRANSPARENT,
|
||||
text_color: color::FOREGROUND,
|
||||
},
|
||||
Style::Destructive => button::Style {
|
||||
Style::Destructive => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: color::FOREGROUND.into(),
|
||||
border_radius: 10.0,
|
||||
@ -105,7 +106,7 @@ impl button::StyleSheet for Style {
|
||||
border_color: color::ALERT,
|
||||
text_color: color::ALERT,
|
||||
},
|
||||
Style::Transparent => button::Style {
|
||||
Style::Transparent => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: color::BACKGROUND.into(),
|
||||
border_radius: 10.0,
|
||||
@ -113,7 +114,7 @@ impl button::StyleSheet for Style {
|
||||
border_color: Color::TRANSPARENT,
|
||||
text_color: Color::BLACK,
|
||||
},
|
||||
Style::TransparentBorder => button::Style {
|
||||
Style::TransparentBorder => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
@ -121,7 +122,7 @@ impl button::StyleSheet for Style {
|
||||
border_color: Color::BLACK,
|
||||
text_color: Color::BLACK,
|
||||
},
|
||||
Style::Border => button::Style {
|
||||
Style::Border => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
@ -132,3 +133,15 @@ impl button::StyleSheet for Style {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Style> for Box<dyn button::StyleSheet<Style = iced::Theme>> {
|
||||
fn from(s: Style) -> Box<dyn button::StyleSheet<Style = iced::Theme>> {
|
||||
Box::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Style> for iced::theme::Button {
|
||||
fn from(i: Style) -> iced::theme::Button {
|
||||
iced::theme::Button::Custom(i.into())
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,30 +1,46 @@
|
||||
use iced::pure::{container, row, tooltip, widget, Element};
|
||||
use iced::{
|
||||
widget::{self, Container, Row, Tooltip},
|
||||
Element,
|
||||
};
|
||||
|
||||
use crate::ui::{color, component::text::text, icon};
|
||||
|
||||
pub fn simple<'a, T: 'a, C: Into<Element<'a, T>>>(content: C) -> widget::Container<'a, T> {
|
||||
container(content).padding(15).style(SimpleCardStyle)
|
||||
Container::new(content).padding(15).style(SimpleCardStyle)
|
||||
}
|
||||
|
||||
pub struct SimpleCardStyle;
|
||||
impl widget::container::StyleSheet for SimpleCardStyle {
|
||||
fn style(&self) -> widget::container::Style {
|
||||
widget::container::Style {
|
||||
type Style = iced::Theme;
|
||||
fn appearance(&self, _style: &Self::Style) -> widget::container::Appearance {
|
||||
widget::container::Appearance {
|
||||
border_radius: 10.0,
|
||||
background: color::FOREGROUND.into(),
|
||||
..widget::container::Style::default()
|
||||
..widget::container::Appearance::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SimpleCardStyle> for Box<dyn widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
fn from(s: SimpleCardStyle) -> Box<dyn widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
Box::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SimpleCardStyle> for iced::theme::Container {
|
||||
fn from(i: SimpleCardStyle) -> iced::theme::Container {
|
||||
iced::theme::Container::Custom(i.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// display an error card with the message and the error in a tooltip.
|
||||
pub fn warning<'a, T: 'a>(message: &str) -> widget::Container<'a, T> {
|
||||
container(
|
||||
row()
|
||||
pub fn warning<'a, T: 'a>(message: String) -> widget::Container<'a, T> {
|
||||
Container::new(
|
||||
Row::new()
|
||||
.spacing(20)
|
||||
.align_items(iced::Alignment::Center)
|
||||
.push(icon::warning_octagon_icon().color(color::WARNING))
|
||||
.push(text(message).color(color::WARNING)),
|
||||
.push(icon::warning_octagon_icon().style(color::WARNING))
|
||||
.push(text(message).style(color::WARNING)),
|
||||
)
|
||||
.padding(15)
|
||||
.style(WarningCardStyle)
|
||||
@ -32,26 +48,39 @@ pub fn warning<'a, T: 'a>(message: &str) -> widget::Container<'a, T> {
|
||||
|
||||
pub struct WarningCardStyle;
|
||||
impl widget::container::StyleSheet for WarningCardStyle {
|
||||
fn style(&self) -> widget::container::Style {
|
||||
widget::container::Style {
|
||||
type Style = iced::Theme;
|
||||
fn appearance(&self, _style: &Self::Style) -> widget::container::Appearance {
|
||||
widget::container::Appearance {
|
||||
border_radius: 10.0,
|
||||
border_color: color::WARNING,
|
||||
border_width: 1.5,
|
||||
background: color::FOREGROUND.into(),
|
||||
..widget::container::Style::default()
|
||||
..widget::container::Appearance::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WarningCardStyle> for Box<dyn widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
fn from(s: WarningCardStyle) -> Box<dyn widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
Box::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WarningCardStyle> for iced::theme::Container {
|
||||
fn from(i: WarningCardStyle) -> iced::theme::Container {
|
||||
iced::theme::Container::Custom(i.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// display an error card with the message and the error in a tooltip.
|
||||
pub fn error<'a, T: 'a>(message: &str, error: &str) -> widget::Container<'a, T> {
|
||||
container(
|
||||
tooltip(
|
||||
row()
|
||||
pub fn error<'a, T: 'a>(message: &'static str, error: String) -> widget::Container<'a, T> {
|
||||
Container::new(
|
||||
Tooltip::new(
|
||||
Row::new()
|
||||
.spacing(20)
|
||||
.align_items(iced::Alignment::Center)
|
||||
.push(icon::block_icon().color(color::ALERT))
|
||||
.push(text(message).color(color::ALERT)),
|
||||
.push(icon::block_icon().style(color::ALERT))
|
||||
.push(text(message).style(color::ALERT)),
|
||||
error,
|
||||
widget::tooltip::Position::Bottom,
|
||||
)
|
||||
@ -63,13 +92,26 @@ pub fn error<'a, T: 'a>(message: &str, error: &str) -> widget::Container<'a, T>
|
||||
|
||||
pub struct ErrorCardStyle;
|
||||
impl widget::container::StyleSheet for ErrorCardStyle {
|
||||
fn style(&self) -> widget::container::Style {
|
||||
widget::container::Style {
|
||||
type Style = iced::Theme;
|
||||
fn appearance(&self, _style: &Self::Style) -> widget::container::Appearance {
|
||||
widget::container::Appearance {
|
||||
border_radius: 10.0,
|
||||
border_color: color::ALERT,
|
||||
border_width: 1.5,
|
||||
background: color::FOREGROUND.into(),
|
||||
..widget::container::Style::default()
|
||||
..widget::container::Appearance::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ErrorCardStyle> for Box<dyn widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
fn from(s: ErrorCardStyle) -> Box<dyn widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
Box::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ErrorCardStyle> for iced::theme::Container {
|
||||
fn from(i: ErrorCardStyle) -> iced::theme::Container {
|
||||
iced::theme::Container::Custom(i.into())
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,95 +0,0 @@
|
||||
use iced::pure::{button, column};
|
||||
use iced_lazy::pure::{self, Component};
|
||||
use iced_native::text;
|
||||
use iced_pure::Element;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use crate::ui::component::button::Style;
|
||||
|
||||
pub fn collapse<
|
||||
'a,
|
||||
Message: 'a,
|
||||
T: Into<Message> + Clone + 'a,
|
||||
Renderer: text::Renderer + 'static,
|
||||
H: Fn() -> Element<'a, T, Renderer> + 'a,
|
||||
C: Fn() -> Element<'a, T, Renderer> + 'a,
|
||||
>(
|
||||
header: H,
|
||||
content: C,
|
||||
) -> impl Into<Element<'a, Message, Renderer>> {
|
||||
Collapse {
|
||||
header,
|
||||
content,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
struct Collapse<'a, H, C> {
|
||||
header: H,
|
||||
content: C,
|
||||
phantom: PhantomData<&'a H>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum Event<T> {
|
||||
Internal(T),
|
||||
Collapse(bool),
|
||||
}
|
||||
|
||||
impl<'a, Message, Renderer, T, H, C> Component<Message, Renderer> for Collapse<'a, H, C>
|
||||
where
|
||||
T: Into<Message> + Clone + 'a,
|
||||
H: Fn() -> Element<'a, T, Renderer>,
|
||||
C: Fn() -> Element<'a, T, Renderer>,
|
||||
Renderer: text::Renderer + 'static,
|
||||
{
|
||||
type State = bool;
|
||||
type Event = Event<T>;
|
||||
|
||||
fn update(&mut self, state: &mut Self::State, event: Event<T>) -> Option<Message> {
|
||||
match event {
|
||||
Event::Internal(e) => Some(e.into()),
|
||||
Event::Collapse(s) => {
|
||||
*state = s;
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn view(&self, state: &Self::State) -> Element<Self::Event, Renderer> {
|
||||
if *state {
|
||||
column()
|
||||
.push(
|
||||
button((self.header)().map(Event::Internal))
|
||||
.style(Style::TransparentBorder)
|
||||
.padding(10)
|
||||
.on_press(Event::Collapse(false)),
|
||||
)
|
||||
.push((self.content)().map(Event::Internal))
|
||||
.into()
|
||||
} else {
|
||||
column()
|
||||
.push(
|
||||
button((self.header)().map(Event::Internal))
|
||||
.padding(10)
|
||||
.style(Style::TransparentBorder)
|
||||
.on_press(Event::Collapse(true)),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message, Renderer, T, H: 'a, C: 'a> From<Collapse<'a, H, C>>
|
||||
for Element<'a, Message, Renderer>
|
||||
where
|
||||
Message: 'a,
|
||||
Renderer: 'static + text::Renderer,
|
||||
T: Into<Message> + Clone + 'a,
|
||||
H: Fn() -> Element<'a, T, Renderer>,
|
||||
C: Fn() -> Element<'a, T, Renderer>,
|
||||
{
|
||||
fn from(c: Collapse<'a, H, C>) -> Self {
|
||||
pure::component(c)
|
||||
}
|
||||
}
|
||||
37
gui/src/ui/component/container.rs
Normal file
37
gui/src/ui/component/container.rs
Normal file
@ -0,0 +1,37 @@
|
||||
use crate::ui::color;
|
||||
use iced::widget::container;
|
||||
|
||||
pub enum Style {
|
||||
Sidebar,
|
||||
Background,
|
||||
}
|
||||
|
||||
impl container::StyleSheet for Style {
|
||||
type Style = iced::Theme;
|
||||
fn appearance(&self, _style: &Self::Style) -> container::Appearance {
|
||||
match self {
|
||||
Self::Background => container::Appearance {
|
||||
background: color::BACKGROUND.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Self::Sidebar => container::Appearance {
|
||||
background: color::FOREGROUND.into(),
|
||||
border_width: 1.0,
|
||||
border_color: color::SECONDARY,
|
||||
..container::Appearance::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Style> for Box<dyn container::StyleSheet<Style = iced::Theme>> {
|
||||
fn from(s: Style) -> Box<dyn container::StyleSheet<Style = iced::Theme>> {
|
||||
Box::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Style> for iced::theme::Container {
|
||||
fn from(i: Style) -> iced::theme::Container {
|
||||
iced::theme::Container::Custom(i.into())
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,10 @@
|
||||
use iced::pure::{
|
||||
column, container,
|
||||
widget::text_input::{Style, StyleSheet, TextInput},
|
||||
Element,
|
||||
use iced::{
|
||||
widget::{
|
||||
text_input::{Appearance, StyleSheet, TextInput},
|
||||
Column, Container,
|
||||
},
|
||||
Element, Length,
|
||||
};
|
||||
use iced::Length;
|
||||
|
||||
use crate::ui::{color, component::text::*, util::Collection};
|
||||
|
||||
@ -70,8 +71,8 @@ where
|
||||
|
||||
impl<'a, Message: 'a + Clone> From<Form<'a, Message>> for Element<'a, Message> {
|
||||
fn from(form: Form<'a, Message>) -> Element<'a, Message> {
|
||||
container(
|
||||
column()
|
||||
Container::new(
|
||||
Column::new()
|
||||
.push(if !form.valid {
|
||||
form.input.style(InvalidFormStyle)
|
||||
} else {
|
||||
@ -79,7 +80,7 @@ impl<'a, Message: 'a + Clone> From<Form<'a, Message>> for Element<'a, Message> {
|
||||
})
|
||||
.push_maybe(if !form.valid {
|
||||
form.warning
|
||||
.map(|message| text(message).color(color::ALERT).small())
|
||||
.map(|message| text(message).style(color::ALERT).small())
|
||||
} else {
|
||||
None
|
||||
})
|
||||
@ -93,8 +94,9 @@ impl<'a, Message: 'a + Clone> From<Form<'a, Message>> for Element<'a, Message> {
|
||||
|
||||
struct InvalidFormStyle;
|
||||
impl StyleSheet for InvalidFormStyle {
|
||||
fn active(&self) -> Style {
|
||||
Style {
|
||||
type Style = iced::Theme;
|
||||
fn active(&self, _style: &Self::Style) -> Appearance {
|
||||
Appearance {
|
||||
background: iced::Background::Color(color::FOREGROUND),
|
||||
border_radius: 5.0,
|
||||
border_width: 1.0,
|
||||
@ -102,22 +104,34 @@ impl StyleSheet for InvalidFormStyle {
|
||||
}
|
||||
}
|
||||
|
||||
fn focused(&self) -> Style {
|
||||
Style {
|
||||
fn focused(&self, style: &Self::Style) -> Appearance {
|
||||
Appearance {
|
||||
border_color: color::ALERT,
|
||||
..self.active()
|
||||
..self.active(style)
|
||||
}
|
||||
}
|
||||
|
||||
fn placeholder_color(&self) -> iced::Color {
|
||||
fn placeholder_color(&self, _style: &Self::Style) -> iced::Color {
|
||||
iced::Color::from_rgb(0.7, 0.7, 0.7)
|
||||
}
|
||||
|
||||
fn value_color(&self) -> iced::Color {
|
||||
fn value_color(&self, _style: &Self::Style) -> iced::Color {
|
||||
iced::Color::from_rgb(0.3, 0.3, 0.3)
|
||||
}
|
||||
|
||||
fn selection_color(&self) -> iced::Color {
|
||||
fn selection_color(&self, _style: &Self::Style) -> iced::Color {
|
||||
iced::Color::from_rgb(0.8, 0.8, 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InvalidFormStyle> for Box<dyn StyleSheet<Style = iced::Theme>> {
|
||||
fn from(s: InvalidFormStyle) -> Box<dyn StyleSheet<Style = iced::Theme>> {
|
||||
Box::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InvalidFormStyle> for iced::theme::TextInput {
|
||||
fn from(i: InvalidFormStyle) -> iced::theme::TextInput {
|
||||
iced::theme::TextInput::Custom(i.into())
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,27 +1,41 @@
|
||||
pub mod badge;
|
||||
pub mod button;
|
||||
pub mod card;
|
||||
pub mod collapse;
|
||||
pub mod container;
|
||||
pub mod form;
|
||||
pub mod notification;
|
||||
pub mod text;
|
||||
|
||||
use iced::pure::widget::{container, Column, Container};
|
||||
use iced::widget::{Column, Container, Text};
|
||||
use iced::Length;
|
||||
|
||||
use crate::ui::color;
|
||||
|
||||
pub fn separation<'a, T: 'a>() -> Container<'a, T> {
|
||||
Container::new(Column::new().push(iced::Text::new(" ")))
|
||||
Container::new(Column::new().push(Text::new(" ")))
|
||||
.style(SepStyle)
|
||||
.height(Length::Units(1))
|
||||
}
|
||||
|
||||
pub struct SepStyle;
|
||||
impl container::StyleSheet for SepStyle {
|
||||
fn style(&self) -> container::Style {
|
||||
container::Style {
|
||||
impl iced::widget::container::StyleSheet for SepStyle {
|
||||
type Style = iced::Theme;
|
||||
fn appearance(&self, _style: &Self::Style) -> iced::widget::container::Appearance {
|
||||
iced::widget::container::Appearance {
|
||||
background: color::SECONDARY.into(),
|
||||
..container::Style::default()
|
||||
..iced::widget::container::Appearance::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SepStyle> for Box<dyn iced::widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
fn from(s: SepStyle) -> Box<dyn iced::widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
Box::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SepStyle> for iced::theme::Container {
|
||||
fn from(i: SepStyle) -> iced::theme::Container {
|
||||
iced::theme::Container::Custom(i.into())
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
use crate::{color, icon};
|
||||
use iced::{container, tooltip, Container, Length, Row, Text, Tooltip};
|
||||
use crate::ui::{color, icon};
|
||||
use iced::{
|
||||
widget::{container, tooltip, Container, Row, Text, Tooltip},
|
||||
Length,
|
||||
};
|
||||
|
||||
pub fn warning<'a, T: 'a>(message: &str, error: &str) -> Container<'a, T> {
|
||||
pub fn warning<'a, T: 'a>(message: String, error: String) -> Container<'a, T> {
|
||||
Container::new(Container::new(
|
||||
Tooltip::new(
|
||||
Row::new()
|
||||
@ -19,23 +22,37 @@ pub fn warning<'a, T: 'a>(message: &str, error: &str) -> Container<'a, T> {
|
||||
.width(Length::Fill)
|
||||
}
|
||||
|
||||
struct WarningStyle;
|
||||
pub struct WarningStyle;
|
||||
impl container::StyleSheet for WarningStyle {
|
||||
fn style(&self) -> container::Style {
|
||||
container::Style {
|
||||
type Style = iced::Theme;
|
||||
fn appearance(&self, _style: &Self::Style) -> container::Appearance {
|
||||
container::Appearance {
|
||||
border_radius: 0.0,
|
||||
text_color: iced::Color::BLACK.into(),
|
||||
background: color::WARNING.into(),
|
||||
border_color: color::WARNING,
|
||||
..container::Style::default()
|
||||
..container::Appearance::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TooltipWarningStyle;
|
||||
impl From<WarningStyle> for Box<dyn container::StyleSheet<Style = iced::Theme>> {
|
||||
fn from(s: WarningStyle) -> Box<dyn container::StyleSheet<Style = iced::Theme>> {
|
||||
Box::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<WarningStyle> for iced::theme::Container {
|
||||
fn from(i: WarningStyle) -> iced::theme::Container {
|
||||
iced::theme::Container::Custom(i.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TooltipWarningStyle;
|
||||
impl container::StyleSheet for TooltipWarningStyle {
|
||||
fn style(&self) -> container::Style {
|
||||
container::Style {
|
||||
type Style = iced::Theme;
|
||||
fn appearance(&self, _style: &Self::Style) -> container::Appearance {
|
||||
container::Appearance {
|
||||
border_radius: 0.0,
|
||||
border_width: 1.0,
|
||||
text_color: color::WARNING.into(),
|
||||
@ -44,3 +61,15 @@ impl container::StyleSheet for TooltipWarningStyle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TooltipWarningStyle> for Box<dyn container::StyleSheet<Style = iced::Theme>> {
|
||||
fn from(s: TooltipWarningStyle) -> Box<dyn container::StyleSheet<Style = iced::Theme>> {
|
||||
Box::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TooltipWarningStyle> for iced::theme::Container {
|
||||
fn from(i: TooltipWarningStyle) -> iced::theme::Container {
|
||||
iced::theme::Container::Custom(i.into())
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
use crate::ui::font;
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub fn text(content: &str) -> iced::pure::widget::Text {
|
||||
iced::pure::widget::Text::new(content)
|
||||
pub fn text<'a>(content: impl Into<Cow<'a, str>>) -> iced::widget::Text<'a> {
|
||||
iced::widget::Text::new(content)
|
||||
.font(font::REGULAR)
|
||||
.size(25)
|
||||
}
|
||||
@ -11,7 +12,7 @@ pub trait Text {
|
||||
fn small(self) -> Self;
|
||||
}
|
||||
|
||||
impl Text for iced::pure::widget::Text {
|
||||
impl Text for iced::widget::Text<'_> {
|
||||
fn bold(self) -> Self {
|
||||
self.font(font::BOLD)
|
||||
}
|
||||
|
||||
@ -1,181 +1,180 @@
|
||||
use iced::pure::text;
|
||||
use iced::{alignment, Font, Length, Text};
|
||||
use iced::{alignment, widget::Text, Font, Length};
|
||||
|
||||
const ICONS: Font = Font::External {
|
||||
name: "Icons",
|
||||
bytes: include_bytes!("../../static/icons/bootstrap-icons.ttf"),
|
||||
};
|
||||
|
||||
fn icon(unicode: char) -> Text {
|
||||
text(&unicode.to_string())
|
||||
fn icon(unicode: char) -> Text<'static> {
|
||||
Text::new(unicode.to_string())
|
||||
.font(ICONS)
|
||||
.width(Length::Units(20))
|
||||
.horizontal_alignment(alignment::Horizontal::Center)
|
||||
.size(20)
|
||||
}
|
||||
|
||||
pub fn hourglass_icon() -> Text {
|
||||
pub fn hourglass_icon() -> Text<'static> {
|
||||
icon('\u{F41F}')
|
||||
}
|
||||
|
||||
pub fn hourglass_done_icon() -> Text {
|
||||
pub fn hourglass_done_icon() -> Text<'static> {
|
||||
icon('\u{F41E}')
|
||||
}
|
||||
|
||||
pub fn vault_icon() -> Text {
|
||||
pub fn vault_icon() -> Text<'static> {
|
||||
icon('\u{F65A}')
|
||||
}
|
||||
|
||||
pub fn bitcoin_icon() -> Text {
|
||||
pub fn bitcoin_icon() -> Text<'static> {
|
||||
icon('\u{F635}')
|
||||
}
|
||||
|
||||
pub fn history_icon() -> Text {
|
||||
pub fn history_icon() -> Text<'static> {
|
||||
icon('\u{F292}')
|
||||
}
|
||||
|
||||
pub fn home_icon() -> Text {
|
||||
pub fn home_icon() -> Text<'static> {
|
||||
icon('\u{F3FC}')
|
||||
}
|
||||
|
||||
pub fn unlock_icon() -> Text {
|
||||
pub fn unlock_icon() -> Text<'static> {
|
||||
icon('\u{F600}')
|
||||
}
|
||||
|
||||
pub fn warning_octagon_icon() -> Text {
|
||||
pub fn warning_octagon_icon() -> Text<'static> {
|
||||
icon('\u{F337}')
|
||||
}
|
||||
|
||||
pub fn send_icon() -> Text {
|
||||
pub fn send_icon() -> Text<'static> {
|
||||
icon('\u{F144}')
|
||||
}
|
||||
|
||||
pub fn connect_device_icon() -> Text {
|
||||
pub fn connect_device_icon() -> Text<'static> {
|
||||
icon('\u{F348}')
|
||||
}
|
||||
|
||||
pub fn connected_device_icon() -> Text {
|
||||
pub fn connected_device_icon() -> Text<'static> {
|
||||
icon('\u{F350}')
|
||||
}
|
||||
|
||||
pub fn receive_icon() -> Text {
|
||||
pub fn receive_icon() -> Text<'static> {
|
||||
icon('\u{F123}')
|
||||
}
|
||||
|
||||
pub fn calendar_icon() -> Text {
|
||||
pub fn calendar_icon() -> Text<'static> {
|
||||
icon('\u{F1E8}')
|
||||
}
|
||||
|
||||
pub fn turnback_icon() -> Text {
|
||||
pub fn turnback_icon() -> Text<'static> {
|
||||
icon('\u{F131}')
|
||||
}
|
||||
|
||||
pub fn vaults_icon() -> Text {
|
||||
pub fn vaults_icon() -> Text<'static> {
|
||||
icon('\u{F1C7}')
|
||||
}
|
||||
|
||||
pub fn coin_icon() -> Text {
|
||||
pub fn coin_icon() -> Text<'static> {
|
||||
icon('\u{F567}')
|
||||
}
|
||||
|
||||
pub fn settings_icon() -> Text {
|
||||
pub fn settings_icon() -> Text<'static> {
|
||||
icon('\u{F3E5}')
|
||||
}
|
||||
|
||||
pub fn block_icon() -> Text {
|
||||
pub fn block_icon() -> Text<'static> {
|
||||
icon('\u{F1C8}')
|
||||
}
|
||||
|
||||
pub fn square_icon() -> Text {
|
||||
pub fn square_icon() -> Text<'static> {
|
||||
icon('\u{F584}')
|
||||
}
|
||||
|
||||
pub fn square_check_icon() -> Text {
|
||||
pub fn square_check_icon() -> Text<'static> {
|
||||
icon('\u{F26D}')
|
||||
}
|
||||
|
||||
pub fn circle_check_icon() -> Text {
|
||||
pub fn circle_check_icon() -> Text<'static> {
|
||||
icon('\u{F26B}')
|
||||
}
|
||||
|
||||
pub fn network_icon() -> Text {
|
||||
pub fn network_icon() -> Text<'static> {
|
||||
icon('\u{F40D}')
|
||||
}
|
||||
|
||||
pub fn dot_icon() -> Text {
|
||||
pub fn dot_icon() -> Text<'static> {
|
||||
icon('\u{F287}')
|
||||
}
|
||||
|
||||
pub fn clipboard_icon() -> Text {
|
||||
pub fn clipboard_icon() -> Text<'static> {
|
||||
icon('\u{F28E}')
|
||||
}
|
||||
|
||||
pub fn shield_icon() -> Text {
|
||||
pub fn shield_icon() -> Text<'static> {
|
||||
icon('\u{F53F}')
|
||||
}
|
||||
|
||||
pub fn shield_notif_icon() -> Text {
|
||||
pub fn shield_notif_icon() -> Text<'static> {
|
||||
icon('\u{F530}')
|
||||
}
|
||||
|
||||
pub fn shield_check_icon() -> Text {
|
||||
pub fn shield_check_icon() -> Text<'static> {
|
||||
icon('\u{F52F}')
|
||||
}
|
||||
|
||||
pub fn person_check_icon() -> Text {
|
||||
pub fn person_check_icon() -> Text<'static> {
|
||||
icon('\u{F4D6}')
|
||||
}
|
||||
|
||||
pub fn person_icon() -> Text {
|
||||
pub fn person_icon() -> Text<'static> {
|
||||
icon('\u{F4DA}')
|
||||
}
|
||||
|
||||
pub fn tooltip_icon() -> Text {
|
||||
pub fn tooltip_icon() -> Text<'static> {
|
||||
icon('\u{F431}')
|
||||
}
|
||||
|
||||
pub fn plus_icon() -> Text {
|
||||
pub fn plus_icon() -> Text<'static> {
|
||||
icon('\u{F4FE}')
|
||||
}
|
||||
|
||||
pub fn warning_icon() -> Text {
|
||||
pub fn warning_icon() -> Text<'static> {
|
||||
icon('\u{F33B}')
|
||||
}
|
||||
|
||||
pub fn chip_icon() -> Text {
|
||||
pub fn chip_icon() -> Text<'static> {
|
||||
icon('\u{F2D6}')
|
||||
}
|
||||
|
||||
pub fn trash_icon() -> Text {
|
||||
pub fn trash_icon() -> Text<'static> {
|
||||
icon('\u{F5DE}')
|
||||
}
|
||||
|
||||
pub fn key_icon() -> Text {
|
||||
pub fn key_icon() -> Text<'static> {
|
||||
icon('\u{F44F}')
|
||||
}
|
||||
|
||||
pub fn cross_icon() -> Text {
|
||||
pub fn cross_icon() -> Text<'static> {
|
||||
icon('\u{F62A}')
|
||||
}
|
||||
|
||||
pub fn pencil_icon() -> Text {
|
||||
pub fn pencil_icon() -> Text<'static> {
|
||||
icon('\u{F4CB}')
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn stakeholder_icon() -> Text {
|
||||
pub fn stakeholder_icon() -> Text<'static> {
|
||||
icon('\u{F4AE}')
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn manager_icon() -> Text {
|
||||
pub fn manager_icon() -> Text<'static> {
|
||||
icon('\u{F4B4}')
|
||||
}
|
||||
|
||||
pub fn done_icon() -> Text {
|
||||
pub fn done_icon() -> Text<'static> {
|
||||
icon('\u{F26B}')
|
||||
}
|
||||
|
||||
pub fn todo_icon() -> Text {
|
||||
pub fn todo_icon() -> Text<'static> {
|
||||
icon('\u{F28A}')
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/// from hecjr idea on Discord
|
||||
use iced::pure::{
|
||||
use iced::{
|
||||
widget::{Column, Row},
|
||||
Element,
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user