Merge #372: gui: design system example
d4d5a66aa1f7323398267ee80bbf98bec2284698 gui: transitioning to ui crate (edouard)
8d337eb7e183b44f967a1e7f19c23141ffef6237 ui: add support for legacy (edouard)
f3bf6fa589ed23ded4633de1ea9d80d9ab04e8f4 gui: design system example (edouard)
Pull request description:
This PR reorganizes the ui module in its own crate and makes usage of the iced theming feature.
The new theme that is introduced help to keep track of the colors and appearance of each widget, it is a crucial part for the next-coming design system and it is a `iced` good practice that since Iced 0.7 we must take care.
This PR also put the basics for a little wasm app example that will help us to share and review new components design.
ACKs for top commit:
edouardparis:
Self-ACK d4d5a66aa1f7323398267ee80bbf98bec2284698
Tree-SHA512: 9d01a2c734c1880da5115aeec5632b649f9b81bb963ab72f0772ee06705805e4df3ab294dff577765bf76b420017faf51d3a5b67e0e1dffadcd8c7d193593241
This commit is contained in:
commit
30054d2755
3
.gitignore
vendored
3
.gitignore
vendored
@ -8,3 +8,6 @@ venv/
|
||||
pytest.log
|
||||
TODO
|
||||
**/target
|
||||
**/dist
|
||||
gui/ui/Cargo.lock
|
||||
gui/ui/examples/design-system/Cargo.lock
|
||||
|
||||
10
gui/Cargo.lock
generated
10
gui/Cargo.lock
generated
@ -1690,6 +1690,7 @@ dependencies = [
|
||||
"iced_lazy",
|
||||
"iced_native",
|
||||
"liana",
|
||||
"liana_ui",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -1699,6 +1700,15 @@ dependencies = [
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "liana_ui"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"iced",
|
||||
"iced_lazy",
|
||||
"iced_native",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.137"
|
||||
|
||||
@ -16,6 +16,7 @@ path = "src/main.rs"
|
||||
[dependencies]
|
||||
async-hwi = "0.0.4"
|
||||
liana = { git = "https://github.com/wizardsardine/liana", branch = "master", default-features = false }
|
||||
liana_ui = { path = "ui" }
|
||||
backtrace = "0.3"
|
||||
base64 = "0.13"
|
||||
|
||||
@ -39,3 +40,6 @@ chrono = "0.4"
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = {version = "1.9.0", features = ["rt", "macros"]}
|
||||
|
||||
[workspace]
|
||||
members = ["ui"]
|
||||
|
||||
@ -15,10 +15,11 @@ use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use iced::{clipboard, time, Command, Element, Subscription};
|
||||
use iced::{clipboard, time, Command, Subscription};
|
||||
use tracing::{info, warn};
|
||||
|
||||
pub use liana::{config::Config as DaemonConfig, miniscript::bitcoin};
|
||||
use liana_ui::widget::Element;
|
||||
|
||||
pub use config::Config;
|
||||
pub use message::Message;
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::{Command, Element};
|
||||
use iced::Command;
|
||||
|
||||
use liana_ui::widget::Element;
|
||||
|
||||
use crate::{
|
||||
app::{cache::Cache, error::Error, menu::Menu, message::Message, state::State, view},
|
||||
|
||||
@ -8,8 +8,8 @@ use std::sync::Arc;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use iced::{widget::qr_code, Command, Subscription};
|
||||
use iced::{widget::Column, Element};
|
||||
use liana::miniscript::bitcoin::{Address, Amount};
|
||||
use liana_ui::widget::*;
|
||||
|
||||
use super::{cache::Cache, error::Error, menu::Menu, message::Message, view, wallet::Wallet};
|
||||
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::{Command, Element};
|
||||
use iced::Command;
|
||||
|
||||
use liana_ui::{component::form, widget::Element};
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
@ -18,7 +20,6 @@ use crate::{
|
||||
model::{remaining_sequence, Coin, SpendTx},
|
||||
Daemon,
|
||||
},
|
||||
ui::component::form,
|
||||
};
|
||||
|
||||
use liana::miniscript::bitcoin::{Address, Amount};
|
||||
|
||||
@ -5,15 +5,16 @@ use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::prelude::*;
|
||||
use iced::{Command, Element};
|
||||
use iced::Command;
|
||||
use tracing::info;
|
||||
|
||||
use liana::config::{BitcoinConfig, BitcoindConfig, Config};
|
||||
|
||||
use liana_ui::{component::form, widget::Element};
|
||||
|
||||
use crate::{
|
||||
app::{cache::Cache, error::Error, message::Message, state::settings::Setting, view, State},
|
||||
daemon::Daemon,
|
||||
ui::component::form,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@ -5,7 +5,9 @@ use std::convert::From;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::{Command, Element};
|
||||
use iced::Command;
|
||||
|
||||
use liana_ui::widget::Element;
|
||||
|
||||
use bitcoind::BitcoindSettingsState;
|
||||
use wallet::WalletSettingsState;
|
||||
|
||||
@ -3,17 +3,21 @@ use std::convert::From;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::{Command, Element};
|
||||
use iced::Command;
|
||||
|
||||
use liana::miniscript::bitcoin::{hashes::hex::ToHex, util::bip32::Fingerprint, Network};
|
||||
|
||||
use liana_ui::{
|
||||
component::{form, modal},
|
||||
widget::Element,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
cache::Cache, error::Error, message::Message, settings, state::State, view, wallet::Wallet,
|
||||
},
|
||||
daemon::Daemon,
|
||||
hw::{list_hardware_wallets, HardwareWallet, HardwareWalletConfig},
|
||||
ui::component::{form, modal},
|
||||
};
|
||||
|
||||
pub struct WalletSettingsState {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::{Command, Element};
|
||||
use iced::Command;
|
||||
use liana::{
|
||||
descriptors::LianaDescInfo,
|
||||
miniscript::bitcoin::{
|
||||
@ -9,6 +9,11 @@ use liana::{
|
||||
},
|
||||
};
|
||||
|
||||
use liana_ui::{
|
||||
component::{form, modal},
|
||||
widget::Element,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
cache::Cache,
|
||||
@ -23,7 +28,6 @@ use crate::{
|
||||
Daemon,
|
||||
},
|
||||
hw::{list_hardware_wallets, HardwareWallet},
|
||||
ui::component::{form, modal},
|
||||
};
|
||||
|
||||
trait Action {
|
||||
|
||||
@ -2,9 +2,13 @@ pub mod detail;
|
||||
mod step;
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::{Command, Element};
|
||||
use iced::Command;
|
||||
|
||||
use liana::miniscript::bitcoin::{consensus, util::psbt::Psbt};
|
||||
use liana_ui::{
|
||||
component::{form, modal},
|
||||
widget::Element,
|
||||
};
|
||||
|
||||
use super::{redirect, State};
|
||||
use crate::{
|
||||
@ -13,7 +17,6 @@ use crate::{
|
||||
model::{Coin, SpendTx},
|
||||
Daemon,
|
||||
},
|
||||
ui::component::{form, modal},
|
||||
};
|
||||
|
||||
pub struct SpendPanel {
|
||||
|
||||
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::{Command, Element};
|
||||
use iced::Command;
|
||||
use liana::{
|
||||
descriptors::MultipathDescriptor,
|
||||
miniscript::bitcoin::{
|
||||
@ -10,6 +10,8 @@ use liana::{
|
||||
},
|
||||
};
|
||||
|
||||
use liana_ui::{component::form, widget::Element};
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
cache::Cache, error::Error, message::Message, state::spend::detail, view, wallet::Wallet,
|
||||
@ -18,7 +20,6 @@ use crate::{
|
||||
model::{remaining_sequence, Coin, SpendTx},
|
||||
Daemon,
|
||||
},
|
||||
ui::component::form,
|
||||
};
|
||||
|
||||
/// See: https://github.com/wizardsardine/liana/blob/master/src/commands/mod.rs#L32
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
use iced::{
|
||||
widget::{Button, Column, Container, Row},
|
||||
Alignment, Element, Length,
|
||||
use iced::{Alignment, Length};
|
||||
|
||||
use liana_ui::{
|
||||
color,
|
||||
component::{badge, separation, text::*},
|
||||
icon, theme,
|
||||
util::Collection,
|
||||
widget::*,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@ -9,12 +14,6 @@ use crate::{
|
||||
view::{message::Message, util::*},
|
||||
},
|
||||
daemon::model::{remaining_sequence, Coin},
|
||||
ui::{
|
||||
color,
|
||||
component::{badge, button, card, separation, text::*},
|
||||
icon,
|
||||
util::Collection,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn coins_view<'a>(
|
||||
@ -77,11 +76,11 @@ fn coin_list_view(
|
||||
Some(Container::new(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.push(text(" 0").small().style(color::ALERT))
|
||||
.push(text(" 0").small().style(color::legacy::ALERT))
|
||||
.push(
|
||||
icon::hourglass_done_icon()
|
||||
.small()
|
||||
.style(color::ALERT),
|
||||
.style(color::legacy::ALERT),
|
||||
)
|
||||
.align_items(Alignment::Center),
|
||||
))
|
||||
@ -92,12 +91,12 @@ fn coin_list_view(
|
||||
.push(
|
||||
text(format!(" {}", seq))
|
||||
.small()
|
||||
.style(color::WARNING),
|
||||
.style(color::legacy::WARNING),
|
||||
)
|
||||
.push(
|
||||
icon::hourglass_icon()
|
||||
.small()
|
||||
.style(color::WARNING),
|
||||
.style(color::legacy::WARNING),
|
||||
)
|
||||
.align_items(Alignment::Center),
|
||||
))
|
||||
@ -124,7 +123,7 @@ fn coin_list_view(
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(20),
|
||||
)
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.style(theme::Button::TransparentBorder)
|
||||
.padding(10)
|
||||
.on_press(Message::Select(index)),
|
||||
)
|
||||
@ -144,7 +143,7 @@ fn coin_list_view(
|
||||
text("The recovery path is available")
|
||||
.bold()
|
||||
.small()
|
||||
.style(color::ALERT),
|
||||
.style(color::legacy::ALERT),
|
||||
))
|
||||
} else {
|
||||
Some(Container::new(
|
||||
@ -169,7 +168,7 @@ fn coin_list_view(
|
||||
.push(text(format!("{}", coin.outpoint)).small())
|
||||
.push(Button::new(icon::clipboard_icon())
|
||||
.on_press(Message::Clipboard(coin.outpoint.to_string()))
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.style(theme::Button::TransparentBorder)
|
||||
))
|
||||
.spacing(5),
|
||||
)
|
||||
@ -204,5 +203,5 @@ fn coin_list_view(
|
||||
None
|
||||
}),
|
||||
)
|
||||
.style(card::SimpleCardStyle)
|
||||
.style(theme::Container::Card(theme::Card::Simple))
|
||||
}
|
||||
|
||||
@ -1,18 +1,15 @@
|
||||
use chrono::NaiveDateTime;
|
||||
|
||||
use iced::{
|
||||
alignment,
|
||||
widget::{Button, Column, Container, Row},
|
||||
Alignment, Element, Length,
|
||||
};
|
||||
use iced::{alignment, Alignment, Length};
|
||||
|
||||
use crate::ui::{
|
||||
color,
|
||||
component::{badge, button::Style, card, text::*},
|
||||
icon,
|
||||
util::Collection,
|
||||
};
|
||||
use liana::miniscript::bitcoin;
|
||||
use liana_ui::{
|
||||
color,
|
||||
component::{badge, card, text::*},
|
||||
icon, theme,
|
||||
util::Collection,
|
||||
widget::*,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
@ -38,7 +35,11 @@ pub fn home_view<'a>(
|
||||
Row::new()
|
||||
.spacing(15)
|
||||
.align_items(Alignment::Center)
|
||||
.push(icon::hourglass_icon().size(30).style(color::WARNING))
|
||||
.push(
|
||||
icon::hourglass_icon()
|
||||
.size(30)
|
||||
.style(color::legacy::WARNING),
|
||||
)
|
||||
.push(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
@ -56,7 +57,7 @@ pub fn home_view<'a>(
|
||||
Row::new()
|
||||
.spacing(15)
|
||||
.align_items(Alignment::Center)
|
||||
.push(icon::hourglass_done_icon().style(color::ALERT))
|
||||
.push(icon::hourglass_done_icon().style(color::legacy::ALERT))
|
||||
.push(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
@ -97,11 +98,11 @@ pub fn home_view<'a>(
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.padding(15)
|
||||
.style(Style::TransparentBorder.into())
|
||||
.style(theme::Button::TransparentBorder)
|
||||
.on_press(Message::Next),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.style(card::SimpleCardStyle),
|
||||
.style(theme::Container::Card(theme::Card::Simple)),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
@ -154,9 +155,9 @@ fn event_list_view<'a>(i: usize, event: &HistoryTransaction) -> Element<'a, Mess
|
||||
)
|
||||
.padding(10)
|
||||
.on_press(Message::Select(i))
|
||||
.style(Style::TransparentBorder.into()),
|
||||
.style(theme::Button::TransparentBorder),
|
||||
)
|
||||
.style(card::SimpleCardStyle)
|
||||
.style(theme::Container::Card(theme::Card::Simple))
|
||||
.into()
|
||||
}
|
||||
|
||||
@ -203,7 +204,7 @@ pub fn event_view<'a>(cache: &Cache, event: &'a HistoryTransaction) -> Element<'
|
||||
.push(
|
||||
Button::new(icon::clipboard_icon())
|
||||
.on_press(Message::Clipboard(event.tx.txid().to_string()))
|
||||
.style(Style::TransparentBorder.into()),
|
||||
.style(theme::Button::TransparentBorder),
|
||||
)
|
||||
.width(Length::Shrink),
|
||||
),
|
||||
|
||||
@ -1,21 +1,14 @@
|
||||
use iced::{
|
||||
widget::{tooltip, Button, Column, Container, Row},
|
||||
Alignment, Element, Length,
|
||||
use iced::{widget::tooltip, Alignment, Length};
|
||||
|
||||
use liana_ui::{
|
||||
color,
|
||||
component::text::{text, Text},
|
||||
icon, theme,
|
||||
util::Collection,
|
||||
widget::*,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app::view::message::*,
|
||||
hw::HardwareWallet,
|
||||
ui::{
|
||||
color,
|
||||
component::{
|
||||
button, card,
|
||||
text::{text, Text},
|
||||
},
|
||||
icon,
|
||||
util::Collection,
|
||||
},
|
||||
};
|
||||
use crate::{app::view::message::*, hw::HardwareWallet};
|
||||
|
||||
pub fn hw_list_view<'a>(
|
||||
i: usize,
|
||||
@ -57,7 +50,7 @@ pub fn hw_list_view<'a>(
|
||||
message,
|
||||
tooltip::Position::Bottom,
|
||||
)
|
||||
.style(card::SimpleCardStyle),
|
||||
.style(theme::Container::Card(theme::Card::Simple)),
|
||||
),
|
||||
})
|
||||
.spacing(5)
|
||||
@ -76,20 +69,20 @@ pub fn hw_list_view<'a>(
|
||||
Row::new()
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(5)
|
||||
.push(icon::circle_check_icon().style(color::SUCCESS))
|
||||
.push(text(v).style(color::SUCCESS))
|
||||
.push(icon::circle_check_icon().style(color::legacy::SUCCESS))
|
||||
.push(text(v).style(color::legacy::SUCCESS))
|
||||
}))
|
||||
.align_items(Alignment::Center)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.padding(10)
|
||||
.style(button::Style::Border.into())
|
||||
.style(theme::Button::Secondary)
|
||||
.width(Length::Fill);
|
||||
if !processing && hw.is_supported() {
|
||||
bttn = bttn.on_press(Message::SelectHardwareWallet(i));
|
||||
}
|
||||
Container::new(bttn)
|
||||
.width(Length::Fill)
|
||||
.style(card::SimpleCardStyle)
|
||||
.style(theme::Container::Card(theme::Card::Simple))
|
||||
.into()
|
||||
}
|
||||
|
||||
@ -13,20 +13,19 @@ pub mod spend;
|
||||
pub use message::*;
|
||||
use warning::warn;
|
||||
|
||||
use iced::{
|
||||
widget::{self, scrollable, Button, Column, Container, Row},
|
||||
Element, Length,
|
||||
};
|
||||
use iced::{widget::scrollable, Length};
|
||||
|
||||
use crate::ui::{
|
||||
component::{badge, button, container, separation, text::*},
|
||||
use liana_ui::{
|
||||
component::{button, separation, text::*},
|
||||
icon::{coin_icon, cross_icon, home_icon, receive_icon, send_icon, settings_icon},
|
||||
theme,
|
||||
util::Collection,
|
||||
widget::*,
|
||||
};
|
||||
|
||||
use crate::app::{cache::Cache, error::Error, menu::Menu};
|
||||
|
||||
pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Message> {
|
||||
pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> Container<'a, Message> {
|
||||
let home_button = if *menu == Menu::Home {
|
||||
button::primary(Some(home_icon()), "Home")
|
||||
.on_press(Message::Reload)
|
||||
@ -63,7 +62,7 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.small()
|
||||
.bold(),
|
||||
)
|
||||
.style(badge::PillStyle::InversePrimary),
|
||||
.style(theme::Container::Pill(theme::Pill::InversePrimary)),
|
||||
)
|
||||
.spacing(10)
|
||||
.width(iced::Length::Fill)
|
||||
@ -73,7 +72,7 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.padding(5)
|
||||
.center_x(),
|
||||
)
|
||||
.style(button::Style::Primary.into())
|
||||
.style(theme::Button::Primary)
|
||||
.on_press(Message::Reload)
|
||||
.width(iced::Length::Units(200))
|
||||
} else {
|
||||
@ -102,7 +101,7 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.small()
|
||||
.bold(),
|
||||
)
|
||||
.style(badge::PillStyle::Primary),
|
||||
.style(theme::Pill::Primary),
|
||||
)
|
||||
.spacing(10)
|
||||
.width(iced::Length::Fill)
|
||||
@ -112,7 +111,7 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.padding(5)
|
||||
.center_x(),
|
||||
)
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
.on_press(Message::Menu(Menu::Coins))
|
||||
.width(iced::Length::Units(200))
|
||||
};
|
||||
@ -138,7 +137,7 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.small()
|
||||
.bold(),
|
||||
)
|
||||
.style(badge::PillStyle::InversePrimary),
|
||||
.style(theme::Pill::InversePrimary),
|
||||
)
|
||||
})
|
||||
.spacing(10)
|
||||
@ -149,7 +148,7 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.padding(5)
|
||||
.center_x(),
|
||||
)
|
||||
.style(button::Style::Primary.into())
|
||||
.style(theme::Button::Primary)
|
||||
.on_press(Message::Reload)
|
||||
.width(iced::Length::Units(200))
|
||||
} else {
|
||||
@ -173,7 +172,7 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.small()
|
||||
.bold(),
|
||||
)
|
||||
.style(badge::PillStyle::Primary),
|
||||
.style(theme::Pill::Primary),
|
||||
)
|
||||
})
|
||||
.spacing(10)
|
||||
@ -184,7 +183,7 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.padding(5)
|
||||
.center_x(),
|
||||
)
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
.on_press(Message::Menu(Menu::Spend))
|
||||
.width(iced::Length::Units(200))
|
||||
};
|
||||
@ -234,14 +233,14 @@ pub fn sidebar<'a>(menu: &Menu, cache: &'a Cache) -> widget::Container<'a, Messa
|
||||
.push_maybe(cache.rescan_progress.map(|p| {
|
||||
Container::new(text(format!(" Rescan...{:.2}% ", p * 100.0)))
|
||||
.padding(5)
|
||||
.style(badge::PillStyle::Simple)
|
||||
.style(theme::Pill::Simple)
|
||||
}))
|
||||
.push(settings_button),
|
||||
)
|
||||
.height(Length::Shrink),
|
||||
),
|
||||
)
|
||||
.style(container::Style::Sidebar)
|
||||
.style(theme::Container::Foreground)
|
||||
}
|
||||
|
||||
pub fn dashboard<'a, T: Into<Element<'a, Message>>>(
|
||||
@ -268,9 +267,9 @@ pub fn dashboard<'a, T: Into<Element<'a, Message>>>(
|
||||
.into()
|
||||
}
|
||||
|
||||
fn main_section<'a, T: 'a>(menu: widget::Container<'a, T>) -> widget::Container<'a, T> {
|
||||
fn main_section<'a, T: 'a>(menu: Container<'a, T>) -> Container<'a, T> {
|
||||
Container::new(menu.max_width(1500))
|
||||
.style(container::Style::Background)
|
||||
.style(theme::Container::Background)
|
||||
.center_x()
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
@ -300,7 +299,7 @@ pub fn modal<'a, T: Into<Element<'a, Message>>, F: Into<Element<'a, Message>>>(
|
||||
.push(button::primary(Some(cross_icon()), "Close").on_press(Message::Close)),
|
||||
)
|
||||
.padding(10)
|
||||
.style(container::Style::Background),
|
||||
.style(theme::Container::Background),
|
||||
)
|
||||
.push(modal_section(Container::new(scrollable(content))))
|
||||
.push_maybe(fixed_footer)
|
||||
@ -309,9 +308,9 @@ pub fn modal<'a, T: Into<Element<'a, Message>>, F: Into<Element<'a, Message>>>(
|
||||
.into()
|
||||
}
|
||||
|
||||
fn modal_section<'a, T: 'a>(menu: widget::Container<'a, T>) -> widget::Container<'a, T> {
|
||||
fn modal_section<'a, T: 'a>(menu: Container<'a, T>) -> Container<'a, T> {
|
||||
Container::new(menu.max_width(1500))
|
||||
.style(container::Style::Background)
|
||||
.style(theme::Container::Background)
|
||||
.center_x()
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
|
||||
@ -1,16 +1,14 @@
|
||||
use iced::{
|
||||
widget::{
|
||||
qr_code::{self, QRCode},
|
||||
Button, Column, Row,
|
||||
},
|
||||
Alignment, Element,
|
||||
widget::qr_code::{self, QRCode},
|
||||
Alignment,
|
||||
};
|
||||
|
||||
use liana::miniscript::bitcoin;
|
||||
|
||||
use crate::ui::{
|
||||
component::{button, card, text::*},
|
||||
icon,
|
||||
use liana_ui::{
|
||||
component::{card, text::*},
|
||||
icon, theme,
|
||||
widget::*,
|
||||
};
|
||||
|
||||
use super::message::Message;
|
||||
@ -25,7 +23,7 @@ pub fn receive<'a>(address: &'a bitcoin::Address, qr: &'a qr_code::State) -> Ele
|
||||
.push(
|
||||
Button::new(icon::clipboard_icon())
|
||||
.on_press(Message::Clipboard(address.to_string()))
|
||||
.style(button::Style::TransparentBorder.into()),
|
||||
.style(theme::Button::TransparentBorder),
|
||||
)
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
|
||||
@ -1,19 +1,16 @@
|
||||
use iced::{
|
||||
widget::{Column, Container, Row, Space},
|
||||
Alignment, Element, Length,
|
||||
};
|
||||
use iced::{widget::Space, Alignment, Length};
|
||||
|
||||
use liana::miniscript::bitcoin::Amount;
|
||||
|
||||
use crate::{
|
||||
app::view::message::{CreateSpendMessage, Message},
|
||||
ui::{
|
||||
component::{button, form, text::*},
|
||||
icon,
|
||||
util::Collection,
|
||||
},
|
||||
use liana_ui::{
|
||||
component::{button, form, text::*},
|
||||
icon,
|
||||
util::Collection,
|
||||
widget::*,
|
||||
};
|
||||
|
||||
use crate::app::view::message::{CreateSpendMessage, Message};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn recovery<'a>(
|
||||
locked_coins: &(usize, Amount),
|
||||
|
||||
@ -1,16 +1,20 @@
|
||||
use std::collections::HashSet;
|
||||
use std::str::FromStr;
|
||||
|
||||
use iced::{
|
||||
alignment,
|
||||
widget::{self, Button, Column, Container, ProgressBar, Row, Space},
|
||||
Alignment, Element, Length,
|
||||
};
|
||||
use iced::{alignment, widget::Space, Alignment, Length};
|
||||
|
||||
use liana::miniscript::bitcoin::{util::bip32::Fingerprint, Network};
|
||||
|
||||
use super::{dashboard, message::*};
|
||||
|
||||
use liana_ui::{
|
||||
color,
|
||||
component::{badge, button, card, form, separation, text::*, tooltip::tooltip},
|
||||
icon, theme,
|
||||
util::Collection,
|
||||
widget::*,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
cache::Cache,
|
||||
@ -19,12 +23,6 @@ use crate::{
|
||||
view::{hw, warning::warn},
|
||||
},
|
||||
hw::HardwareWallet,
|
||||
ui::{
|
||||
color,
|
||||
component::{badge, button, card, form, separation, text::*, tooltip::tooltip},
|
||||
icon,
|
||||
util::Collection,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn list(cache: &Cache) -> Element<Message> {
|
||||
@ -37,7 +35,7 @@ pub fn list(cache: &Cache) -> Element<Message> {
|
||||
.width(Length::Fill)
|
||||
.push(
|
||||
Button::new(text("Settings").size(30).bold())
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
.on_press(Message::Menu(Menu::Settings)))
|
||||
.push(
|
||||
Container::new(
|
||||
@ -51,11 +49,11 @@ pub fn list(cache: &Cache) -> Element<Message> {
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.style(button::Style::Border.into())
|
||||
.style(theme::Button::Secondary)
|
||||
.on_press(Message::Settings(SettingsMessage::EditBitcoindSettings))
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.style(card::SimpleCardStyle)
|
||||
.style(theme::Container::Card(theme::Card::Simple))
|
||||
)
|
||||
.push(
|
||||
Container::new(
|
||||
@ -69,11 +67,11 @@ pub fn list(cache: &Cache) -> Element<Message> {
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.style(button::Style::Border.into())
|
||||
.style(theme::Button::Secondary)
|
||||
.on_press(Message::Settings(SettingsMessage::EditWalletSettings))
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.style(card::SimpleCardStyle)
|
||||
.style(theme::Container::Card(theme::Card::Simple))
|
||||
)
|
||||
.push(
|
||||
Container::new(
|
||||
@ -88,11 +86,11 @@ pub fn list(cache: &Cache) -> Element<Message> {
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.style(button::Style::Border.into())
|
||||
.style(theme::Button::Secondary)
|
||||
.on_press(Message::Menu(Menu::Recovery))
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.style(card::SimpleCardStyle)
|
||||
.style(theme::Container::Card(theme::Card::Simple))
|
||||
)
|
||||
.push(
|
||||
Container::new(
|
||||
@ -106,11 +104,11 @@ pub fn list(cache: &Cache) -> Element<Message> {
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.style(button::Style::Border.into())
|
||||
.style(theme::Button::Secondary)
|
||||
.on_press(Message::Settings(SettingsMessage::AboutSection))
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.style(card::SimpleCardStyle)
|
||||
.style(theme::Container::Card(theme::Card::Simple))
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -131,17 +129,17 @@ pub fn bitcoind_settings<'a>(
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Button::new(text("Settings").size(30).bold())
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
.on_press(Message::Menu(Menu::Settings)),
|
||||
)
|
||||
.push(icon::chevron_right().size(30))
|
||||
.push(
|
||||
Button::new(text("Bitcoin Core").size(30).bold())
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
.on_press(Message::Settings(SettingsMessage::EditBitcoindSettings)),
|
||||
),
|
||||
)
|
||||
.push(widget::Column::with_children(settings).spacing(20)),
|
||||
.push(Column::with_children(settings).spacing(20)),
|
||||
)
|
||||
}
|
||||
|
||||
@ -162,13 +160,13 @@ pub fn about_section<'a>(
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Button::new(text("Settings").size(30).bold())
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
.on_press(Message::Menu(Menu::Settings)),
|
||||
)
|
||||
.push(icon::chevron_right().size(30))
|
||||
.push(
|
||||
Button::new(text("About").size(30).bold())
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
.on_press(Message::Settings(SettingsMessage::AboutSection)),
|
||||
),
|
||||
)
|
||||
@ -374,12 +372,11 @@ pub fn bitcoind<'a>(
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(if can_edit {
|
||||
widget::Button::new(icon::pencil_icon())
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
Button::new(icon::pencil_icon())
|
||||
.style(theme::Button::TransparentBorder)
|
||||
.on_press(SettingsEditMessage::Select)
|
||||
} else {
|
||||
widget::Button::new(icon::pencil_icon())
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
Button::new(icon::pencil_icon()).style(theme::Button::TransparentBorder)
|
||||
})
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
@ -391,20 +388,20 @@ pub fn bitcoind<'a>(
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn is_running_label<'a, T: 'a>(is_running: Option<bool>) -> widget::Container<'a, T> {
|
||||
pub fn is_running_label<'a, T: 'a>(is_running: Option<bool>) -> Container<'a, T> {
|
||||
if let Some(running) = is_running {
|
||||
if running {
|
||||
Container::new(
|
||||
Row::new()
|
||||
.push(icon::dot_icon().size(5).style(color::SUCCESS))
|
||||
.push(text("Running").small().style(color::SUCCESS))
|
||||
.push(icon::dot_icon().size(5).style(color::legacy::SUCCESS))
|
||||
.push(text("Running").small().style(color::legacy::SUCCESS))
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
} else {
|
||||
Container::new(
|
||||
Row::new()
|
||||
.push(icon::dot_icon().size(5).style(color::ALERT))
|
||||
.push(text("Not running").small().style(color::ALERT))
|
||||
.push(icon::dot_icon().size(5).style(color::legacy::ALERT))
|
||||
.push(text("Not running").small().style(color::legacy::ALERT))
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
}
|
||||
@ -429,7 +426,7 @@ pub fn rescan<'a>(
|
||||
.push(badge::Badge::new(icon::block_icon()))
|
||||
.push(text("Rescan blockchain").bold().width(Length::Fill))
|
||||
.push_maybe(if success {
|
||||
Some(text("Rescan was successful").style(color::SUCCESS))
|
||||
Some(text("Rescan was successful").style(color::legacy::SUCCESS))
|
||||
} else {
|
||||
None
|
||||
})
|
||||
@ -539,13 +536,13 @@ pub fn wallet_settings<'a>(
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Button::new(text("Settings").size(30).bold())
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
.on_press(Message::Menu(Menu::Settings)),
|
||||
)
|
||||
.push(icon::chevron_right().size(30))
|
||||
.push(
|
||||
Button::new(text("Wallet").size(30).bold())
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
.on_press(Message::Settings(SettingsMessage::AboutSection)),
|
||||
),
|
||||
)
|
||||
@ -604,8 +601,10 @@ pub fn wallet_settings<'a>(
|
||||
Some(
|
||||
Row::new()
|
||||
.align_items(Alignment::Center)
|
||||
.push(icon::circle_check_icon().style(color::SUCCESS))
|
||||
.push(text("Updated").style(color::SUCCESS)),
|
||||
.push(
|
||||
icon::circle_check_icon().style(color::legacy::SUCCESS),
|
||||
)
|
||||
.push(text("Updated").style(color::legacy::SUCCESS)),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use iced::{
|
||||
widget::{scrollable, tooltip, Button, Column, Container, Row, Scrollable, Space},
|
||||
Alignment, Element, Length,
|
||||
widget::{scrollable, tooltip, Space},
|
||||
Alignment, Length,
|
||||
};
|
||||
|
||||
use liana::{
|
||||
@ -13,6 +13,19 @@ use liana::{
|
||||
},
|
||||
};
|
||||
|
||||
use liana_ui::{
|
||||
color,
|
||||
component::{
|
||||
badge, button, card,
|
||||
collapse::Collapse,
|
||||
form, separation,
|
||||
text::{text, Text},
|
||||
},
|
||||
icon, theme,
|
||||
util::Collection,
|
||||
widget::*,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
error::Error,
|
||||
@ -20,17 +33,6 @@ use crate::{
|
||||
},
|
||||
daemon::model::{Coin, SpendStatus, SpendTx},
|
||||
hw::HardwareWallet,
|
||||
ui::{
|
||||
color,
|
||||
component::{
|
||||
badge, button, card,
|
||||
collapse::Collapse,
|
||||
container, form, separation,
|
||||
text::{text, Text},
|
||||
},
|
||||
icon,
|
||||
util::Collection,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn spend_view<'a>(
|
||||
@ -178,16 +180,16 @@ pub fn spend_modal<'a, T: Into<Element<'a, Message>>>(
|
||||
}),
|
||||
)
|
||||
.padding(10)
|
||||
.style(container::Style::Background),
|
||||
.style(theme::Container::Background),
|
||||
)
|
||||
.push(
|
||||
Container::new(Scrollable::new(
|
||||
Container::new(scrollable(
|
||||
Container::new(Container::new(content).max_width(800))
|
||||
.width(Length::Fill)
|
||||
.center_x(),
|
||||
))
|
||||
.height(Length::Fill)
|
||||
.style(container::Style::Background),
|
||||
.style(theme::Container::Background),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
@ -200,7 +202,7 @@ fn spend_header<'a>(tx: &SpendTx) -> Element<'a, Message> {
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Row::new()
|
||||
.push(badge::Badge::new(icon::send_icon()).style(badge::Style::Standard))
|
||||
.push(badge::Badge::new(icon::send_icon()).style(theme::Badge::Standard))
|
||||
.push(if tx.sigs.recovery_path().is_some() {
|
||||
text("Recovery").bold()
|
||||
} else {
|
||||
@ -266,14 +268,14 @@ fn spend_overview_view<'a>(
|
||||
.on_press(Message::Clipboard(
|
||||
tx.psbt.unsigned_tx.txid().to_string(),
|
||||
))
|
||||
.style(button::Style::TransparentBorder.into()),
|
||||
.style(theme::Button::TransparentBorder),
|
||||
)
|
||||
.align_items(Alignment::Center),
|
||||
),
|
||||
)
|
||||
.push(signatures(tx, desc_info, key_aliases)),
|
||||
)
|
||||
.style(card::SimpleCardStyle)
|
||||
.style(theme::Container::Card(theme::Card::Simple))
|
||||
.into()
|
||||
}
|
||||
|
||||
@ -286,12 +288,12 @@ pub fn signatures<'a>(
|
||||
.push(
|
||||
if let Some(sigs) = tx.path_ready() {
|
||||
Container::new(
|
||||
Scrollable::new(
|
||||
scrollable(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.align_items(Alignment::Center)
|
||||
.push(icon::circle_check_icon().style(color::SUCCESS))
|
||||
.push(text("Ready").bold().style(color::SUCCESS))
|
||||
.push(icon::circle_check_icon().style(color::legacy::SUCCESS))
|
||||
.push(text("Ready").bold().style(color::legacy::SUCCESS))
|
||||
.push(text(", signed by"))
|
||||
.push(
|
||||
sigs.signed_pubkeys
|
||||
@ -302,16 +304,16 @@ pub fn signatures<'a>(
|
||||
tooltip::Tooltip::new(
|
||||
Container::new(text(alias))
|
||||
.padding(3)
|
||||
.style(badge::PillStyle::Simple),
|
||||
.style(theme::Container::Pill(theme::Pill::Simple)),
|
||||
value.0.to_string(),
|
||||
tooltip::Position::Bottom,
|
||||
)
|
||||
.style(card::SimpleCardStyle),
|
||||
.style(theme::Container::Card(theme::Card::Simple)),
|
||||
)
|
||||
} else {
|
||||
Container::new(text(value.0.to_string()))
|
||||
.padding(3)
|
||||
.style(badge::PillStyle::Simple)
|
||||
.style(theme::Container::Pill(theme::Pill::Simple))
|
||||
})
|
||||
}),
|
||||
)
|
||||
@ -335,7 +337,7 @@ pub fn signatures<'a>(
|
||||
)
|
||||
.padding(15)
|
||||
.width(Length::Fill)
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.style(theme::Button::TransparentBorder)
|
||||
},
|
||||
move || {
|
||||
Button::new(
|
||||
@ -353,7 +355,7 @@ pub fn signatures<'a>(
|
||||
)
|
||||
.padding(15)
|
||||
.width(Length::Fill)
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.style(theme::Button::TransparentBorder)
|
||||
},
|
||||
move || {
|
||||
Into::<Element<'a, Message>>::into(
|
||||
@ -423,11 +425,11 @@ pub fn path_view<'a>(
|
||||
sigs.threshold - sigs.sigs_count
|
||||
};
|
||||
keys.sort();
|
||||
Scrollable::new(
|
||||
scrollable(
|
||||
Row::new()
|
||||
.align_items(Alignment::Center)
|
||||
.push(if sigs.sigs_count >= sigs.threshold {
|
||||
icon::circle_check_icon().style(color::SUCCESS)
|
||||
icon::circle_check_icon().style(color::legacy::SUCCESS)
|
||||
} else {
|
||||
icon::circle_cross_icon()
|
||||
})
|
||||
@ -452,16 +454,16 @@ pub fn path_view<'a>(
|
||||
tooltip::Tooltip::new(
|
||||
Container::new(text(alias))
|
||||
.padding(3)
|
||||
.style(badge::PillStyle::Simple),
|
||||
.style(theme::Container::Pill(theme::Pill::Simple)),
|
||||
value.0.to_string(),
|
||||
tooltip::Position::Bottom,
|
||||
)
|
||||
.style(card::SimpleCardStyle),
|
||||
.style(theme::Container::Card(theme::Card::Simple)),
|
||||
)
|
||||
} else {
|
||||
Container::new(text(value.0.to_string()))
|
||||
.padding(3)
|
||||
.style(badge::PillStyle::Simple)
|
||||
.style(theme::Container::Pill(theme::Pill::Simple))
|
||||
})
|
||||
} else {
|
||||
None
|
||||
@ -482,16 +484,16 @@ pub fn path_view<'a>(
|
||||
tooltip::Tooltip::new(
|
||||
Container::new(text(alias))
|
||||
.padding(3)
|
||||
.style(badge::PillStyle::Simple),
|
||||
.style(theme::Container::Pill(theme::Pill::Simple)),
|
||||
value.0.to_string(),
|
||||
tooltip::Position::Bottom,
|
||||
)
|
||||
.style(card::SimpleCardStyle),
|
||||
.style(theme::Container::Card(theme::Card::Simple)),
|
||||
)
|
||||
} else {
|
||||
Container::new(text(value.0.to_string()))
|
||||
.padding(3)
|
||||
.style(badge::PillStyle::Simple)
|
||||
.style(theme::Container::Pill(theme::Pill::Simple))
|
||||
})
|
||||
}),
|
||||
),
|
||||
@ -531,7 +533,7 @@ pub fn inputs_and_outputs_view<'a>(
|
||||
)
|
||||
.padding(15)
|
||||
.width(Length::Fill)
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.style(theme::Button::TransparentBorder)
|
||||
},
|
||||
move || {
|
||||
Button::new(
|
||||
@ -550,7 +552,7 @@ pub fn inputs_and_outputs_view<'a>(
|
||||
)
|
||||
.padding(15)
|
||||
.width(Length::Fill)
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.style(theme::Button::TransparentBorder)
|
||||
},
|
||||
move || {
|
||||
coins
|
||||
@ -575,7 +577,7 @@ pub fn inputs_and_outputs_view<'a>(
|
||||
coin.outpoint.to_string(),
|
||||
))
|
||||
.style(
|
||||
button::Style::TransparentBorder.into(),
|
||||
theme::Button::TransparentBorder,
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -585,7 +587,7 @@ pub fn inputs_and_outputs_view<'a>(
|
||||
.into()
|
||||
},
|
||||
))
|
||||
.style(card::SimpleCardStyle),
|
||||
.style(theme::Container::Card(theme::Card::Simple)),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
@ -609,7 +611,7 @@ pub fn inputs_and_outputs_view<'a>(
|
||||
)
|
||||
.padding(15)
|
||||
.width(Length::Fill)
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.style(theme::Button::TransparentBorder)
|
||||
},
|
||||
move || {
|
||||
Button::new(
|
||||
@ -628,7 +630,7 @@ pub fn inputs_and_outputs_view<'a>(
|
||||
)
|
||||
.padding(15)
|
||||
.width(Length::Fill)
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.style(theme::Button::TransparentBorder)
|
||||
},
|
||||
move || {
|
||||
tx.output
|
||||
@ -655,7 +657,7 @@ pub fn inputs_and_outputs_view<'a>(
|
||||
addr.to_string(),
|
||||
))
|
||||
.style(
|
||||
button::Style::TransparentBorder.into(),
|
||||
theme::Button::TransparentBorder,
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -669,7 +671,7 @@ pub fn inputs_and_outputs_view<'a>(
|
||||
Some(
|
||||
Container::new(text("Change"))
|
||||
.padding(5)
|
||||
.style(badge::PillStyle::Success),
|
||||
.style(theme::Container::Pill(theme::Pill::Success)),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
@ -684,7 +686,7 @@ pub fn inputs_and_outputs_view<'a>(
|
||||
Some(
|
||||
Container::new(text("Deposit"))
|
||||
.padding(5)
|
||||
.style(badge::PillStyle::Success),
|
||||
.style(theme::Container::Pill(theme::Pill::Success)),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
@ -698,7 +700,7 @@ pub fn inputs_and_outputs_view<'a>(
|
||||
.into()
|
||||
},
|
||||
))
|
||||
.style(card::SimpleCardStyle),
|
||||
.style(theme::Container::Card(theme::Card::Simple)),
|
||||
),
|
||||
)
|
||||
.into()
|
||||
@ -768,9 +770,10 @@ pub fn sign_action<'a>(
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(5)
|
||||
.push(
|
||||
icon::circle_check_icon().style(color::SUCCESS),
|
||||
icon::circle_check_icon()
|
||||
.style(color::legacy::SUCCESS),
|
||||
)
|
||||
.push(text("Signed").style(color::SUCCESS)),
|
||||
.push(text("Signed").style(color::legacy::SUCCESS)),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
@ -778,7 +781,7 @@ pub fn sign_action<'a>(
|
||||
)
|
||||
.on_press(Message::Spend(SpendTxMessage::SelectHotSigner))
|
||||
.padding(10)
|
||||
.style(button::Style::Border.into())
|
||||
.style(theme::Button::Secondary)
|
||||
.width(Length::Fill)
|
||||
}))
|
||||
.width(Length::Fill),
|
||||
@ -844,7 +847,7 @@ pub fn update_spend_success_view<'a>() -> Element<'a, Message> {
|
||||
Column::new()
|
||||
.push(
|
||||
card::simple(Container::new(
|
||||
text("Spend transaction is updated").style(color::SUCCESS),
|
||||
text("Spend transaction is updated").style(color::legacy::SUCCESS),
|
||||
))
|
||||
.padding(50),
|
||||
)
|
||||
|
||||
@ -1,20 +1,19 @@
|
||||
pub mod detail;
|
||||
pub mod step;
|
||||
|
||||
use iced::{
|
||||
widget::{Button, Column, Container, Row, Space},
|
||||
Alignment, Element, Length,
|
||||
use iced::{widget::Space, Alignment, Length};
|
||||
|
||||
use liana_ui::{
|
||||
color,
|
||||
component::{badge, button, card, form, text::*},
|
||||
icon, theme,
|
||||
util::Collection,
|
||||
widget::*,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app::{error::Error, menu::Menu, view::util::*},
|
||||
daemon::model::{SpendStatus, SpendTx},
|
||||
ui::{
|
||||
color,
|
||||
component::{badge, button, card, form, text::*},
|
||||
icon,
|
||||
util::Collection,
|
||||
},
|
||||
};
|
||||
|
||||
use super::{message::*, warning::warn};
|
||||
@ -57,7 +56,7 @@ pub fn import_spend_success_view<'a>() -> Element<'a, Message> {
|
||||
Column::new()
|
||||
.push(
|
||||
card::simple(Container::new(
|
||||
text("PSBT is imported").style(color::SUCCESS),
|
||||
text("PSBT is imported").style(color::legacy::SUCCESS),
|
||||
))
|
||||
.padding(50),
|
||||
)
|
||||
@ -133,7 +132,7 @@ fn spend_tx_list_view<'a>(i: usize, tx: &SpendTx) -> Element<'a, Message> {
|
||||
.push(
|
||||
Container::new(text(" Recovery ").small())
|
||||
.padding(3)
|
||||
.style(badge::PillStyle::Simple),
|
||||
.style(theme::Container::Pill(theme::Pill::Simple)),
|
||||
)
|
||||
} else {
|
||||
let sigs = tx.sigs.primary_path();
|
||||
@ -172,8 +171,8 @@ fn spend_tx_list_view<'a>(i: usize, tx: &SpendTx) -> Element<'a, Message> {
|
||||
)
|
||||
.padding(10)
|
||||
.on_press(Message::Select(i))
|
||||
.style(button::Style::TransparentBorder.into()),
|
||||
.style(theme::Button::TransparentBorder),
|
||||
)
|
||||
.style(card::SimpleCardStyle)
|
||||
.style(theme::Container::Card(theme::Card::Simple))
|
||||
.into()
|
||||
}
|
||||
|
||||
@ -1,10 +1,18 @@
|
||||
use iced::{
|
||||
widget::{self, Button, Column, Container, Row},
|
||||
Alignment, Element, Length,
|
||||
};
|
||||
use iced::{Alignment, Length};
|
||||
|
||||
use liana::miniscript::bitcoin::Amount;
|
||||
|
||||
use liana_ui::{
|
||||
color,
|
||||
component::{
|
||||
badge, button, form,
|
||||
text::{text, Text},
|
||||
},
|
||||
icon, theme,
|
||||
util::Collection,
|
||||
widget::*,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
cache::Cache,
|
||||
@ -12,15 +20,6 @@ use crate::{
|
||||
view::{message::*, modal, util::amount},
|
||||
},
|
||||
daemon::model::{remaining_sequence, Coin},
|
||||
ui::{
|
||||
color,
|
||||
component::{
|
||||
badge, button, card, form,
|
||||
text::{text, Text},
|
||||
},
|
||||
icon,
|
||||
util::Collection,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn choose_recipients_view<'a>(
|
||||
@ -37,7 +36,7 @@ pub fn choose_recipients_view<'a>(
|
||||
.push(text("Choose recipients").bold().size(50))
|
||||
.push(
|
||||
Column::new()
|
||||
.push(widget::Column::with_children(recipients).spacing(10))
|
||||
.push(Column::with_children(recipients).spacing(10))
|
||||
.push(
|
||||
button::transparent(Some(icon::plus_icon()), "Add recipient")
|
||||
.on_press(Message::CreateSpend(CreateSpendMessage::AddRecipient)),
|
||||
@ -64,7 +63,10 @@ pub fn choose_recipients_view<'a>(
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push_maybe(if duplicate {
|
||||
Some(text("Two recipient addresses are the same").style(color::WARNING))
|
||||
Some(
|
||||
text("Two recipient addresses are the same")
|
||||
.style(color::legacy::WARNING),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
@ -213,9 +215,11 @@ fn coin_list_view<'a>(
|
||||
Some(Container::new(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.push(text(" 0").small().style(color::ALERT))
|
||||
.push(text(" 0").small().style(color::legacy::ALERT))
|
||||
.push(
|
||||
icon::hourglass_done_icon().small().style(color::ALERT),
|
||||
icon::hourglass_done_icon()
|
||||
.small()
|
||||
.style(color::legacy::ALERT),
|
||||
)
|
||||
.align_items(Alignment::Center),
|
||||
))
|
||||
@ -224,9 +228,15 @@ fn coin_list_view<'a>(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.push(
|
||||
text(format!(" {}", seq)).small().style(color::WARNING),
|
||||
text(format!(" {}", seq))
|
||||
.small()
|
||||
.style(color::legacy::WARNING),
|
||||
)
|
||||
.push(
|
||||
icon::hourglass_icon()
|
||||
.small()
|
||||
.style(color::legacy::WARNING),
|
||||
)
|
||||
.push(icon::hourglass_icon().small().style(color::WARNING))
|
||||
.align_items(Alignment::Center),
|
||||
))
|
||||
} else {
|
||||
@ -254,8 +264,8 @@ fn coin_list_view<'a>(
|
||||
)
|
||||
.padding(10)
|
||||
.on_press(Message::CreateSpend(CreateSpendMessage::SelectCoin(i)))
|
||||
.style(button::Style::TransparentBorder.into()),
|
||||
.style(theme::Button::TransparentBorder),
|
||||
)
|
||||
.style(card::SimpleCardStyle)
|
||||
.style(theme::Container::Card(theme::Card::Simple))
|
||||
.into()
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use iced::{widget::Row, Element};
|
||||
use liana::miniscript::bitcoin::Amount;
|
||||
|
||||
use crate::ui::{color, component::text::*, util::Collection};
|
||||
use liana_ui::{color, component::text::*, util::Collection, widget::*};
|
||||
|
||||
pub fn amount<'a, T: 'a>(a: &Amount) -> impl Into<Element<'a, T>> {
|
||||
amount_with_size(a, TEXT_REGULAR_SIZE)
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
use std::convert::From;
|
||||
|
||||
use iced::{
|
||||
widget::{self, Column, Container},
|
||||
Length,
|
||||
};
|
||||
use iced::Length;
|
||||
|
||||
use liana_ui::{component::notification, widget::*};
|
||||
|
||||
use crate::{
|
||||
app::error::Error,
|
||||
daemon::{client::error::RpcErrorCode, DaemonError},
|
||||
ui::component::notification,
|
||||
};
|
||||
|
||||
/// Simple warning message displayed to non technical user.
|
||||
@ -48,7 +46,7 @@ impl std::fmt::Display for WarningMessage {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn warn<'a, T: 'a + Clone>(error: Option<&Error>) -> widget::Container<'a, T> {
|
||||
pub fn warn<'a, T: 'a + Clone>(error: Option<&Error>) -> Container<'a, T> {
|
||||
if let Some(w) = error {
|
||||
let message: WarningMessage = w.into();
|
||||
notification::warning(message.to_string(), w.to_string()).width(Length::Fill)
|
||||
|
||||
@ -4,8 +4,9 @@ mod prompt;
|
||||
mod step;
|
||||
mod view;
|
||||
|
||||
use iced::{clipboard, Command, Element, Subscription};
|
||||
use iced::{clipboard, Command, Subscription};
|
||||
use liana::miniscript::bitcoin;
|
||||
use liana_ui::widget::Element;
|
||||
use tracing::{error, info, warn};
|
||||
|
||||
use context::Context;
|
||||
|
||||
@ -3,7 +3,7 @@ use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::{Command, Element};
|
||||
use iced::Command;
|
||||
use liana::{
|
||||
descriptors::{LianaDescKeys, MultipathDescriptor},
|
||||
miniscript::{
|
||||
@ -17,6 +17,11 @@ use liana::{
|
||||
},
|
||||
};
|
||||
|
||||
use liana_ui::{
|
||||
component::{form, modal::Modal},
|
||||
widget::Element,
|
||||
};
|
||||
|
||||
use async_hwi::DeviceKind;
|
||||
|
||||
use crate::{
|
||||
@ -28,7 +33,6 @@ use crate::{
|
||||
view, Error,
|
||||
},
|
||||
signer::Signer,
|
||||
ui::component::{form, modal::Modal},
|
||||
};
|
||||
|
||||
pub trait DescriptorKeyModal {
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::{Command, Element};
|
||||
use iced::Command;
|
||||
use liana::{bip39, signer::HotSigner};
|
||||
|
||||
use liana_ui::widget::Element;
|
||||
|
||||
use crate::{
|
||||
installer::{context::Context, message::Message, step::Step, view},
|
||||
signer::Signer,
|
||||
|
||||
@ -10,10 +10,10 @@ pub use mnemonic::{BackupMnemonic, RecoverMnemonic};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
use iced::{Command, Element};
|
||||
use iced::Command;
|
||||
use liana::{config::BitcoindConfig, miniscript::bitcoin};
|
||||
|
||||
use crate::ui::component::form;
|
||||
use liana_ui::{component::form, widget::*};
|
||||
|
||||
use crate::installer::{
|
||||
context::Context,
|
||||
|
||||
@ -1,12 +1,22 @@
|
||||
use iced::widget::{
|
||||
scrollable::Properties, Button, Checkbox, Column, Container, PickList, Row, Scrollable, Space,
|
||||
TextInput,
|
||||
checkbox, container, pick_list, scrollable, scrollable::Properties, Space, TextInput,
|
||||
};
|
||||
use iced::{alignment, Alignment, Element, Length};
|
||||
use iced::{alignment, Alignment, Length};
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use liana::miniscript::bitcoin;
|
||||
use liana_ui::{
|
||||
color,
|
||||
component::{
|
||||
button, card, collapse, form, separation,
|
||||
text::{text, Text},
|
||||
tooltip,
|
||||
},
|
||||
icon, theme,
|
||||
util::Collection,
|
||||
widget::*,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
hw::HardwareWallet,
|
||||
@ -15,16 +25,6 @@ use crate::{
|
||||
message::{self, Message},
|
||||
prompt, Error,
|
||||
},
|
||||
ui::{
|
||||
color,
|
||||
component::{
|
||||
button, card, collapse, container, form, separation,
|
||||
text::{text, Text},
|
||||
tooltip,
|
||||
},
|
||||
icon,
|
||||
util::Collection,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@ -92,7 +92,7 @@ pub fn welcome<'a>() -> Element<'a, Message> {
|
||||
)
|
||||
.padding(20),
|
||||
)
|
||||
.style(button::Style::Border.into())
|
||||
.style(theme::Button::Secondary)
|
||||
.on_press(Message::CreateWallet),
|
||||
)
|
||||
.push(
|
||||
@ -106,7 +106,7 @@ pub fn welcome<'a>() -> Element<'a, Message> {
|
||||
)
|
||||
.padding(20),
|
||||
)
|
||||
.style(button::Style::Border.into())
|
||||
.style(theme::Button::Secondary)
|
||||
.on_press(Message::ParticipateWallet),
|
||||
)
|
||||
.push(
|
||||
@ -120,7 +120,7 @@ pub fn welcome<'a>() -> Element<'a, Message> {
|
||||
)
|
||||
.padding(20),
|
||||
)
|
||||
.style(button::Style::Border.into())
|
||||
.style(theme::Button::Secondary)
|
||||
.on_press(Message::ImportWallet),
|
||||
),
|
||||
)
|
||||
@ -153,10 +153,11 @@ pub fn define_descriptor<'a>(
|
||||
.spacing(10)
|
||||
.align_items(Alignment::Center)
|
||||
.push(text("Network:").bold())
|
||||
.push(Container::new(
|
||||
PickList::new(&NETWORKS[..], Some(Network::from(network)), |net| {
|
||||
.push(container(
|
||||
pick_list(&NETWORKS[..], Some(Network::from(network)), |net| {
|
||||
Message::Network(net.into())
|
||||
})
|
||||
.style(theme::PickList::Simple)
|
||||
.padding(10),
|
||||
))
|
||||
.push_maybe(if network_valid {
|
||||
@ -195,7 +196,7 @@ pub fn define_descriptor<'a>(
|
||||
None
|
||||
})
|
||||
.push(
|
||||
Scrollable::new(
|
||||
scrollable(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.align_items(Alignment::Center)
|
||||
@ -210,7 +211,7 @@ pub fn define_descriptor<'a>(
|
||||
)
|
||||
.width(Length::Units(200))
|
||||
.height(Length::Units(200))
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.style(theme::Button::TransparentBorder)
|
||||
.on_press(
|
||||
Message::DefineDescriptor(
|
||||
message::DefineDescriptor::AddKey(false),
|
||||
@ -252,7 +253,7 @@ pub fn define_descriptor<'a>(
|
||||
None
|
||||
})
|
||||
.push(
|
||||
Scrollable::new(
|
||||
scrollable(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.align_items(Alignment::Center)
|
||||
@ -267,7 +268,7 @@ pub fn define_descriptor<'a>(
|
||||
)
|
||||
.width(Length::Units(200))
|
||||
.height(Length::Units(200))
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.style(theme::Button::TransparentBorder)
|
||||
.on_press(
|
||||
Message::DefineDescriptor(
|
||||
message::DefineDescriptor::AddKey(true),
|
||||
@ -359,7 +360,7 @@ pub fn import_descriptor<'a>(
|
||||
.align_items(Alignment::Center)
|
||||
.push(text("Network:").bold())
|
||||
.push(Container::new(
|
||||
PickList::new(&NETWORKS[..], Some(Network::from(network)), |net| {
|
||||
pick_list(&NETWORKS[..], Some(Network::from(network)), |net| {
|
||||
Message::Network(net.into())
|
||||
})
|
||||
.padding(10),
|
||||
@ -430,7 +431,7 @@ pub fn signer_xpubs(xpubs: &Vec<String>) -> Element<Message> {
|
||||
)
|
||||
.on_press(Message::UseHotSigner)
|
||||
.padding(10)
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.style(theme::Button::TransparentBorder)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push_maybe(if xpubs.is_empty() {
|
||||
@ -448,7 +449,7 @@ pub fn signer_xpubs(xpubs: &Vec<String>) -> Element<Message> {
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Container::new(
|
||||
Scrollable::new(Container::new(text(xpub).small()).padding(10))
|
||||
scrollable(Container::new(text(xpub).small()).padding(10))
|
||||
.horizontal_scroll(
|
||||
Properties::new().width(2).scroller_width(2),
|
||||
),
|
||||
@ -478,7 +479,7 @@ pub fn signer_xpubs(xpubs: &Vec<String>) -> Element<Message> {
|
||||
None
|
||||
}),
|
||||
)
|
||||
.style(card::SimpleCardStyle)
|
||||
.style(theme::Container::Card(theme::Card::Simple))
|
||||
.into()
|
||||
}
|
||||
|
||||
@ -523,7 +524,7 @@ pub fn hardware_wallet_xpubs<'a>(
|
||||
message,
|
||||
iced::widget::tooltip::Position::Bottom,
|
||||
)
|
||||
.style(card::SimpleCardStyle),
|
||||
.style(theme::Container::Card(theme::Card::Simple)),
|
||||
),
|
||||
})
|
||||
.spacing(5)
|
||||
@ -534,16 +535,16 @@ pub fn hardware_wallet_xpubs<'a>(
|
||||
Row::new()
|
||||
.spacing(5)
|
||||
.align_items(Alignment::Center)
|
||||
.push(icon::warning_icon().style(color::ALERT))
|
||||
.push(text("An error occured").style(color::ALERT)),
|
||||
.push(icon::warning_icon().style(color::legacy::ALERT))
|
||||
.push(text("An error occured").style(color::legacy::ALERT)),
|
||||
e,
|
||||
iced::widget::tooltip::Position::Bottom,
|
||||
)
|
||||
.style(card::ErrorCardStyle)
|
||||
.style(theme::Container::Card(theme::Card::Error))
|
||||
})),
|
||||
)
|
||||
.padding(10)
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.style(theme::Button::TransparentBorder)
|
||||
.width(Length::Fill);
|
||||
if !processing && hw.is_supported() {
|
||||
bttn = bttn.on_press(Message::Select(i));
|
||||
@ -566,7 +567,7 @@ pub fn hardware_wallet_xpubs<'a>(
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Container::new(
|
||||
Scrollable::new(Container::new(text(xpub).small()).padding(10))
|
||||
scrollable(Container::new(text(xpub).small()).padding(10))
|
||||
.horizontal_scroll(
|
||||
Properties::new().width(2).scroller_width(2),
|
||||
),
|
||||
@ -598,7 +599,7 @@ pub fn hardware_wallet_xpubs<'a>(
|
||||
None
|
||||
}),
|
||||
)
|
||||
.style(card::SimpleCardStyle)
|
||||
.style(theme::Container::Card(theme::Card::Simple))
|
||||
.into()
|
||||
}
|
||||
|
||||
@ -615,7 +616,7 @@ pub fn participate_xpub<'a>(
|
||||
.align_items(Alignment::Center)
|
||||
.push(text("Network:").bold())
|
||||
.push(Container::new(
|
||||
PickList::new(&NETWORKS[..], Some(Network::from(network)), |net| {
|
||||
pick_list(&NETWORKS[..], Some(Network::from(network)), |net| {
|
||||
Message::Network(net.into())
|
||||
})
|
||||
.padding(10),
|
||||
@ -658,7 +659,7 @@ pub fn participate_xpub<'a>(
|
||||
.push(signer)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(Checkbox::new(
|
||||
.push(checkbox(
|
||||
"I have shared my public keys",
|
||||
shared,
|
||||
Message::UserActionDone,
|
||||
@ -744,7 +745,7 @@ pub fn register_descriptor<'a>(
|
||||
)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(Checkbox::new(
|
||||
.push(checkbox(
|
||||
"I have registered the descriptor on my device(s)",
|
||||
done,
|
||||
Message::UserActionDone,
|
||||
@ -789,7 +790,7 @@ pub fn backup_descriptor<'a>(
|
||||
.push(text("Learn more").small().bold())
|
||||
.push(icon::collapse_icon()),
|
||||
)
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
},
|
||||
|| {
|
||||
Button::new(
|
||||
@ -799,7 +800,7 @@ pub fn backup_descriptor<'a>(
|
||||
.push(text("Learn more").small().bold())
|
||||
.push(icon::collapsed_icon()),
|
||||
)
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
},
|
||||
help_backup,
|
||||
))
|
||||
@ -818,7 +819,7 @@ pub fn backup_descriptor<'a>(
|
||||
.spacing(10)
|
||||
.max_width(1000),
|
||||
))
|
||||
.push(Checkbox::new(
|
||||
.push(checkbox(
|
||||
"I have backed up my descriptor",
|
||||
done,
|
||||
Message::UserActionDone,
|
||||
@ -1051,7 +1052,7 @@ pub fn undefined_descriptor_key<'a>() -> Element<'a, message::DefineKey> {
|
||||
.push(Space::with_width(Length::Fill))
|
||||
.push(
|
||||
Button::new(icon::cross_icon())
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
.on_press(message::DefineKey::Delete),
|
||||
),
|
||||
)
|
||||
@ -1061,7 +1062,7 @@ pub fn undefined_descriptor_key<'a>() -> Element<'a, message::DefineKey> {
|
||||
.spacing(15)
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Scrollable::new(
|
||||
scrollable(
|
||||
icon::key_icon()
|
||||
.style(color::DARK_GREY)
|
||||
.size(50)
|
||||
@ -1069,7 +1070,11 @@ pub fn undefined_descriptor_key<'a>() -> Element<'a, message::DefineKey> {
|
||||
)
|
||||
.horizontal_scroll(Properties::new().width(2).scroller_width(2)),
|
||||
)
|
||||
.push(icon::circle_check_icon().style(color::FOREGROUND).size(50)),
|
||||
.push(
|
||||
icon::circle_check_icon()
|
||||
.style(color::legacy::FOREGROUND)
|
||||
.size(50),
|
||||
),
|
||||
)
|
||||
.height(Length::Fill)
|
||||
.align_y(alignment::Vertical::Center),
|
||||
@ -1100,7 +1105,7 @@ pub fn defined_descriptor_key(
|
||||
.push(Space::with_width(Length::Fill))
|
||||
.push(
|
||||
Button::new(icon::cross_icon())
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
.on_press(message::DefineKey::Delete),
|
||||
),
|
||||
)
|
||||
@ -1114,13 +1119,13 @@ pub fn defined_descriptor_key(
|
||||
.spacing(15)
|
||||
.align_items(Alignment::Center)
|
||||
.push(
|
||||
Scrollable::new(text(name).bold()).horizontal_scroll(
|
||||
scrollable(text(name).bold()).horizontal_scroll(
|
||||
Properties::new().width(2).scroller_width(2),
|
||||
),
|
||||
)
|
||||
.push(
|
||||
icon::circle_check_icon()
|
||||
.style(color::SUCCESS)
|
||||
.style(color::legacy::SUCCESS)
|
||||
.size(40)
|
||||
.width(Length::Units(50)),
|
||||
),
|
||||
@ -1145,7 +1150,7 @@ pub fn defined_descriptor_key(
|
||||
.push(
|
||||
text("Key is for a different network")
|
||||
.small()
|
||||
.style(color::ALERT),
|
||||
.style(color::legacy::ALERT),
|
||||
)
|
||||
.into()
|
||||
} else if duplicate_key {
|
||||
@ -1157,7 +1162,7 @@ pub fn defined_descriptor_key(
|
||||
.height(Length::Units(200))
|
||||
.width(Length::Units(200)),
|
||||
)
|
||||
.push(text("Duplicate key").small().style(color::ALERT))
|
||||
.push(text("Duplicate key").small().style(color::legacy::ALERT))
|
||||
.into()
|
||||
} else if duplicate_name {
|
||||
Column::new()
|
||||
@ -1168,7 +1173,7 @@ pub fn defined_descriptor_key(
|
||||
.height(Length::Units(200))
|
||||
.width(Length::Units(200)),
|
||||
)
|
||||
.push(text("Duplicate name").small().style(color::ALERT))
|
||||
.push(text("Duplicate name").small().style(color::legacy::ALERT))
|
||||
.into()
|
||||
} else {
|
||||
card::simple(col)
|
||||
@ -1243,7 +1248,7 @@ pub fn edit_key_modal<'a>(
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push_maybe(if chosen_signer {
|
||||
Some(icon::circle_check_icon().style(color::SUCCESS))
|
||||
Some(icon::circle_check_icon().style(color::legacy::SUCCESS))
|
||||
} else {
|
||||
None
|
||||
})
|
||||
@ -1251,7 +1256,7 @@ pub fn edit_key_modal<'a>(
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.on_press(Message::UseHotSigner)
|
||||
.style(button::Style::Border.into()),
|
||||
.style(theme::Button::Secondary),
|
||||
)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
@ -1382,7 +1387,7 @@ fn hw_list_view(
|
||||
message,
|
||||
iced::widget::tooltip::Position::Bottom,
|
||||
)
|
||||
.style(card::SimpleCardStyle),
|
||||
.style(theme::Container::Card(theme::Card::Simple)),
|
||||
),
|
||||
})
|
||||
.spacing(5)
|
||||
@ -1398,7 +1403,7 @@ fn hw_list_view(
|
||||
None
|
||||
})
|
||||
.push_maybe(if registered {
|
||||
Some(Column::new().push(icon::circle_check_icon().style(color::SUCCESS)))
|
||||
Some(Column::new().push(icon::circle_check_icon().style(color::legacy::SUCCESS)))
|
||||
} else {
|
||||
None
|
||||
})
|
||||
@ -1406,14 +1411,14 @@ fn hw_list_view(
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.padding(10)
|
||||
.style(button::Style::TransparentBorder.into())
|
||||
.style(theme::Button::TransparentBorder)
|
||||
.width(Length::Fill);
|
||||
if !processing && hw.is_supported() {
|
||||
bttn = bttn.on_press(Message::Select(i));
|
||||
}
|
||||
Container::new(bttn)
|
||||
.width(Length::Fill)
|
||||
.style(card::SimpleCardStyle)
|
||||
.style(theme::Container::Card(theme::Card::Simple))
|
||||
.into()
|
||||
}
|
||||
|
||||
@ -1443,7 +1448,7 @@ pub fn backup_mnemonic<'a>(
|
||||
)
|
||||
}),
|
||||
)
|
||||
.push(Checkbox::new(
|
||||
.push(checkbox(
|
||||
"I have backed up my mnemonic",
|
||||
done,
|
||||
Message::UserActionDone,
|
||||
@ -1485,7 +1490,7 @@ pub fn recover_mnemonic<'a>(
|
||||
suggestions.iter().fold(Row::new().spacing(5), |row, sugg| {
|
||||
row.push(
|
||||
Button::new(text(sugg))
|
||||
.style(button::Style::Border.into())
|
||||
.style(theme::Button::Secondary)
|
||||
.on_press(Message::MnemonicWord(
|
||||
current,
|
||||
sugg.to_string(),
|
||||
@ -1516,7 +1521,10 @@ pub fn recover_mnemonic<'a>(
|
||||
.width(Length::Units(100)),
|
||||
)
|
||||
.push_maybe(if *valid {
|
||||
Some(icon::circle_check_icon().style(color::SUCCESS))
|
||||
Some(
|
||||
icon::circle_check_icon()
|
||||
.style(color::legacy::SUCCESS),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}),
|
||||
@ -1524,7 +1532,9 @@ pub fn recover_mnemonic<'a>(
|
||||
},
|
||||
))
|
||||
.push(Space::with_height(Length::Units(50)))
|
||||
.push_maybe(error.map(|e| card::invalid(text(e).style(color::ALERT)))),
|
||||
.push_maybe(
|
||||
error.map(|e| card::invalid(text(e).style(color::legacy::ALERT))),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
@ -1572,7 +1582,7 @@ fn layout<'a>(
|
||||
progress: (usize, usize),
|
||||
content: impl Into<Element<'a, Message>>,
|
||||
) -> Element<'a, Message> {
|
||||
Container::new(Scrollable::new(
|
||||
Container::new(scrollable(
|
||||
Column::new()
|
||||
.push(
|
||||
Container::new(button::transparent(None, "< Previous").on_press(Message::Previous))
|
||||
@ -1588,19 +1598,15 @@ fn layout<'a>(
|
||||
.center_x()
|
||||
.height(Length::Fill)
|
||||
.width(Length::Fill)
|
||||
.style(container::Style::Background)
|
||||
.style(theme::Container::Background)
|
||||
.into()
|
||||
}
|
||||
|
||||
mod threshsold_input {
|
||||
use crate::ui::{
|
||||
component::{button, text::*},
|
||||
icon,
|
||||
};
|
||||
use iced::alignment::{self, Alignment};
|
||||
use iced::widget::{Button, Column, Container};
|
||||
use iced::{Element, Length};
|
||||
use iced::Length;
|
||||
use iced_lazy::{self, Component};
|
||||
use liana_ui::{component::text::*, icon, theme, widget::*};
|
||||
|
||||
pub struct ThresholdInput<Message> {
|
||||
value: usize,
|
||||
@ -1636,7 +1642,7 @@ mod threshsold_input {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Message> Component<Message, iced::Renderer> for ThresholdInput<Message> {
|
||||
impl<Message> Component<Message, iced::Renderer<theme::Theme>> for ThresholdInput<Message> {
|
||||
type State = ();
|
||||
type Event = Event;
|
||||
|
||||
@ -1662,7 +1668,7 @@ mod threshsold_input {
|
||||
fn view(&self, _state: &Self::State) -> Element<Self::Event> {
|
||||
let button = |label, on_press| {
|
||||
Button::new(label)
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
.width(Length::Units(50))
|
||||
.on_press(on_press)
|
||||
};
|
||||
|
||||
@ -1,21 +1,17 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use iced::{
|
||||
widget::{Button, Column, Container, Row},
|
||||
Alignment, Command, Element, Length, Subscription,
|
||||
};
|
||||
use iced::{Alignment, Command, Length, Subscription};
|
||||
|
||||
use liana::{config::ConfigError, miniscript::bitcoin::Network};
|
||||
|
||||
use crate::{
|
||||
app,
|
||||
ui::{
|
||||
component::{badge, button, card, text::*},
|
||||
icon,
|
||||
util::*,
|
||||
},
|
||||
use liana_ui::{
|
||||
component::{badge, card, text::*},
|
||||
icon, theme,
|
||||
util::*,
|
||||
widget::*,
|
||||
};
|
||||
|
||||
use crate::app;
|
||||
|
||||
pub struct Launcher {
|
||||
choices: Vec<Network>,
|
||||
datadir_path: PathBuf,
|
||||
@ -102,9 +98,9 @@ impl Launcher {
|
||||
badge::Badge::new(icon::bitcoin_icon()).style(
|
||||
match choice {
|
||||
Network::Bitcoin => {
|
||||
badge::Style::Bitcoin
|
||||
theme::Badge::Bitcoin
|
||||
}
|
||||
_ => badge::Style::Standard,
|
||||
_ => theme::Badge::Standard,
|
||||
},
|
||||
),
|
||||
)
|
||||
@ -118,7 +114,7 @@ impl Launcher {
|
||||
.on_press(ViewMessage::Check(*choice))
|
||||
.padding(10)
|
||||
.width(Length::Fill)
|
||||
.style(button::Style::Border.into()),
|
||||
.style(theme::Button::Secondary),
|
||||
)
|
||||
},
|
||||
)
|
||||
@ -133,7 +129,7 @@ impl Launcher {
|
||||
.on_press(ViewMessage::StartInstall)
|
||||
.padding(10)
|
||||
.width(Length::Fill)
|
||||
.style(button::Style::TransparentBorder.into()),
|
||||
.style(theme::Button::TransparentBorder),
|
||||
),
|
||||
)
|
||||
.max_width(500)
|
||||
|
||||
@ -6,7 +6,6 @@ pub mod launcher;
|
||||
pub mod loader;
|
||||
pub mod logger;
|
||||
pub mod signer;
|
||||
pub mod ui;
|
||||
pub mod utils;
|
||||
|
||||
use liana::Version;
|
||||
|
||||
@ -3,10 +3,6 @@ use std::io::ErrorKind;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
use iced::{
|
||||
widget::{Column, Container, ProgressBar, Row},
|
||||
Element,
|
||||
};
|
||||
use iced::{Alignment, Command, Length, Subscription};
|
||||
use tracing::{debug, info};
|
||||
|
||||
@ -15,6 +11,12 @@ use liana::{
|
||||
miniscript::bitcoin,
|
||||
StartupError,
|
||||
};
|
||||
use liana_ui::{
|
||||
component::{button, notification, text::*},
|
||||
icon,
|
||||
util::Collection,
|
||||
widget::*,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app::{
|
||||
@ -23,11 +25,6 @@ use crate::{
|
||||
wallet::{Wallet, WalletError},
|
||||
},
|
||||
daemon::{client, embedded::EmbeddedDaemon, model::*, Daemon, DaemonError},
|
||||
ui::{
|
||||
component::{button, notification, text::*},
|
||||
icon,
|
||||
util::Collection,
|
||||
},
|
||||
};
|
||||
|
||||
type Lianad = client::Lianad<client::jsonrpc::JsonRPCClient>;
|
||||
|
||||
@ -2,13 +2,14 @@
|
||||
|
||||
use std::{error::Error, io::Write, path::PathBuf, str::FromStr};
|
||||
|
||||
use iced::{executor, Application, Command, Element, Settings, Subscription};
|
||||
use iced::{executor, Application, Command, Settings, Subscription};
|
||||
use tracing::{error, info};
|
||||
use tracing_subscriber::filter::LevelFilter;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
|
||||
use liana::{config::Config as DaemonConfig, miniscript::bitcoin};
|
||||
use liana_ui::{theme, widget::Element};
|
||||
|
||||
use liana_gui::{
|
||||
app::{
|
||||
@ -87,7 +88,7 @@ impl Application for GUI {
|
||||
type Executor = executor::Default;
|
||||
type Message = Message;
|
||||
type Flags = Config;
|
||||
type Theme = iced::Theme;
|
||||
type Theme = theme::Theme;
|
||||
|
||||
fn title(&self) -> String {
|
||||
match self.state {
|
||||
|
||||
@ -1,81 +0,0 @@
|
||||
use iced::Color;
|
||||
|
||||
pub const BACKGROUND: Color = Color::from_rgb(
|
||||
0xF6 as f32 / 255.0,
|
||||
0xF7 as f32 / 255.0,
|
||||
0xF8 as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const BORDER_GREY: Color = Color::from_rgb(
|
||||
0xd0 as f32 / 255.0,
|
||||
0xd7 as f32 / 255.0,
|
||||
0xde as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const FOREGROUND: Color = Color::WHITE;
|
||||
|
||||
pub const PRIMARY: Color = Color::BLACK;
|
||||
|
||||
pub const SECONDARY: Color = DARK_GREY;
|
||||
|
||||
pub const SUCCESS: Color = Color::from_rgb(
|
||||
0x29 as f32 / 255.0,
|
||||
0xBC as f32 / 255.0,
|
||||
0x97 as f32 / 255.0,
|
||||
);
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const SUCCESS_LIGHT: Color = Color::from_rgba(
|
||||
0x29 as f32 / 255.0,
|
||||
0xBC as f32 / 255.0,
|
||||
0x97 as f32 / 255.0,
|
||||
0.5f32,
|
||||
);
|
||||
|
||||
pub const ALERT: Color = Color::from_rgb(
|
||||
0xF0 as f32 / 255.0,
|
||||
0x43 as f32 / 255.0,
|
||||
0x59 as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const ALERT_LIGHT: Color = Color::from_rgba(
|
||||
0xF0 as f32 / 255.0,
|
||||
0x43 as f32 / 255.0,
|
||||
0x59 as f32 / 255.0,
|
||||
0.5f32,
|
||||
);
|
||||
|
||||
pub const WARNING: Color =
|
||||
Color::from_rgb(0xFF as f32 / 255.0, 0xa7 as f32 / 255.0, 0x0 as f32 / 255.0);
|
||||
|
||||
pub const WARNING_LIGHT: Color = Color::from_rgba(
|
||||
0xFF as f32 / 255.0,
|
||||
0xa7 as f32 / 255.0,
|
||||
0x0 as f32 / 255.0,
|
||||
0.5f32,
|
||||
);
|
||||
|
||||
pub const CANCEL: Color = Color::from_rgb(
|
||||
0x34 as f32 / 255.0,
|
||||
0x37 as f32 / 255.0,
|
||||
0x3D as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const INFO: Color = Color::from_rgb(
|
||||
0x2A as f32 / 255.0,
|
||||
0x98 as f32 / 255.0,
|
||||
0xBD as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const INFO_LIGHT: Color = Color::from_rgba(
|
||||
0x2A as f32 / 255.0,
|
||||
0x98 as f32 / 255.0,
|
||||
0xBD as f32 / 255.0,
|
||||
0.5f32,
|
||||
);
|
||||
|
||||
pub const DARK_GREY: Color = Color::from_rgb(
|
||||
0x8c as f32 / 255.0,
|
||||
0x97 as f32 / 255.0,
|
||||
0xa6 as f32 / 255.0,
|
||||
);
|
||||
@ -1,209 +0,0 @@
|
||||
use iced::{
|
||||
widget::{self, tooltip, Container},
|
||||
Element, Length,
|
||||
};
|
||||
|
||||
use crate::ui::{
|
||||
color,
|
||||
component::{card, text::*},
|
||||
icon,
|
||||
};
|
||||
|
||||
pub enum Style {
|
||||
Standard,
|
||||
Success,
|
||||
Warning,
|
||||
Bitcoin,
|
||||
}
|
||||
|
||||
impl widget::container::StyleSheet for Style {
|
||||
type Style = iced::Theme;
|
||||
fn appearance(&self, _style: &Self::Style) -> widget::container::Appearance {
|
||||
match self {
|
||||
Self::Standard => widget::container::Appearance {
|
||||
border_radius: 40.0,
|
||||
background: color::BACKGROUND.into(),
|
||||
..widget::container::Appearance::default()
|
||||
},
|
||||
Self::Success => widget::container::Appearance {
|
||||
border_radius: 40.0,
|
||||
background: color::SUCCESS_LIGHT.into(),
|
||||
text_color: color::SUCCESS.into(),
|
||||
..widget::container::Appearance::default()
|
||||
},
|
||||
Self::Warning => widget::container::Appearance {
|
||||
border_radius: 40.0,
|
||||
background: color::WARNING_LIGHT.into(),
|
||||
text_color: color::WARNING.into(),
|
||||
..widget::container::Appearance::default()
|
||||
},
|
||||
Self::Bitcoin => widget::container::Appearance {
|
||||
border_radius: 40.0,
|
||||
background: color::WARNING.into(),
|
||||
text_color: iced::Color::WHITE.into(),
|
||||
..widget::container::Appearance::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 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,
|
||||
}
|
||||
}
|
||||
pub fn style(self, style: Style) -> Self {
|
||||
Self {
|
||||
icon: self.icon,
|
||||
style,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
.center_x()
|
||||
.center_y()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn receive<T>() -> widget::container::Container<'static, T> {
|
||||
Container::new(icon::receive_icon().width(Length::Units(20)))
|
||||
.width(Length::Units(40))
|
||||
.height(Length::Units(40))
|
||||
.style(Style::Standard)
|
||||
.center_x()
|
||||
.center_y()
|
||||
}
|
||||
|
||||
pub fn spend<T>() -> widget::container::Container<'static, T> {
|
||||
Container::new(icon::send_icon().width(Length::Units(20)))
|
||||
.width(Length::Units(40))
|
||||
.height(Length::Units(40))
|
||||
.style(Style::Standard)
|
||||
.center_x()
|
||||
.center_y()
|
||||
}
|
||||
|
||||
pub fn coin<T>() -> widget::container::Container<'static, T> {
|
||||
Container::new(icon::coin_icon().width(Length::Units(20)))
|
||||
.width(Length::Units(40))
|
||||
.height(Length::Units(40))
|
||||
.style(Style::Standard)
|
||||
.center_x()
|
||||
.center_y()
|
||||
}
|
||||
|
||||
pub enum PillStyle {
|
||||
InversePrimary,
|
||||
Primary,
|
||||
Success,
|
||||
Simple,
|
||||
}
|
||||
|
||||
impl widget::container::StyleSheet for PillStyle {
|
||||
type Style = iced::Theme;
|
||||
fn appearance(&self, _style: &Self::Style) -> widget::container::Appearance {
|
||||
match self {
|
||||
Self::Primary => widget::container::Appearance {
|
||||
background: color::PRIMARY.into(),
|
||||
border_radius: 10.0,
|
||||
text_color: iced::Color::WHITE.into(),
|
||||
..widget::container::Appearance::default()
|
||||
},
|
||||
Self::InversePrimary => widget::container::Appearance {
|
||||
background: color::FOREGROUND.into(),
|
||||
border_radius: 10.0,
|
||||
text_color: color::PRIMARY.into(),
|
||||
..widget::container::Appearance::default()
|
||||
},
|
||||
Self::Success => widget::container::Appearance {
|
||||
background: color::SUCCESS.into(),
|
||||
border_radius: 10.0,
|
||||
text_color: iced::Color::WHITE.into(),
|
||||
..widget::container::Appearance::default()
|
||||
},
|
||||
Self::Simple => widget::container::Appearance {
|
||||
background: color::BACKGROUND.into(),
|
||||
border_radius: 10.0,
|
||||
text_color: iced::Color::BLACK.into(),
|
||||
..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())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unconfirmed<'a, T: 'a>() -> widget::container::Container<'a, T> {
|
||||
Container::new(
|
||||
tooltip::Tooltip::new(
|
||||
Container::new(text(" Unconfirmed ").small())
|
||||
.padding(3)
|
||||
.style(PillStyle::Simple),
|
||||
"Do not treat this as a payment until it is confirmed",
|
||||
tooltip::Position::Top,
|
||||
)
|
||||
.style(card::SimpleCardStyle),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn deprecated<'a, T: 'a>() -> widget::container::Container<'a, T> {
|
||||
Container::new(
|
||||
tooltip::Tooltip::new(
|
||||
Container::new(text(" Deprecated ").small())
|
||||
.padding(3)
|
||||
.style(PillStyle::Simple),
|
||||
"This spend cannot be included anymore in the blockchain",
|
||||
tooltip::Position::Top,
|
||||
)
|
||||
.style(card::SimpleCardStyle),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn spent<'a, T: 'a>() -> widget::container::Container<'a, T> {
|
||||
Container::new(
|
||||
tooltip::Tooltip::new(
|
||||
Container::new(text(" Spent ").small())
|
||||
.padding(3)
|
||||
.style(PillStyle::Simple),
|
||||
"The spend transaction was included in the blockchain",
|
||||
tooltip::Position::Top,
|
||||
)
|
||||
.style(card::SimpleCardStyle),
|
||||
)
|
||||
}
|
||||
@ -1,151 +0,0 @@
|
||||
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<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<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<Text<'a>>, t: &'static str) -> button::Button<'a, T> {
|
||||
button::Button::new(content(icon, t)).style(Style::Transparent.into())
|
||||
}
|
||||
|
||||
pub fn border<'a, T: 'a>(icon: Option<Text<'a>>, t: &'static str) -> button::Button<'a, T> {
|
||||
button::Button::new(content(icon, t)).style(Style::Border.into())
|
||||
}
|
||||
|
||||
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<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::new()
|
||||
.push(i)
|
||||
.push(text(t))
|
||||
.spacing(10)
|
||||
.width(iced::Length::Fill)
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
.width(iced::Length::Fill)
|
||||
.center_x()
|
||||
.padding(5),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Style {
|
||||
Primary,
|
||||
Transparent,
|
||||
TransparentBorder,
|
||||
Border,
|
||||
Destructive,
|
||||
}
|
||||
|
||||
impl button::StyleSheet for Style {
|
||||
type Style = iced::Theme;
|
||||
fn active(&self, _style: &Self::Style) -> button::Appearance {
|
||||
match self {
|
||||
Style::Primary => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: color::PRIMARY.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: Color::TRANSPARENT,
|
||||
text_color: color::FOREGROUND,
|
||||
},
|
||||
Style::Destructive => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: color::FOREGROUND.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: color::ALERT,
|
||||
text_color: color::ALERT,
|
||||
},
|
||||
Style::Transparent | Style::TransparentBorder => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: Color::TRANSPARENT,
|
||||
text_color: Color::BLACK,
|
||||
},
|
||||
Style::Border => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 1.2,
|
||||
border_color: color::BORDER_GREY,
|
||||
text_color: Color::BLACK,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn hovered(&self, _style: &Self::Style) -> button::Appearance {
|
||||
match self {
|
||||
Style::Primary => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: color::PRIMARY.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: Color::TRANSPARENT,
|
||||
text_color: color::FOREGROUND,
|
||||
},
|
||||
Style::Destructive => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: color::FOREGROUND.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: color::ALERT,
|
||||
text_color: color::ALERT,
|
||||
},
|
||||
Style::Transparent => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: Color::TRANSPARENT,
|
||||
text_color: Color::BLACK,
|
||||
},
|
||||
Style::TransparentBorder => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 1.0,
|
||||
border_color: Color::BLACK,
|
||||
text_color: Color::BLACK,
|
||||
},
|
||||
Style::Border => button::Appearance {
|
||||
shadow_offset: Vector::default(),
|
||||
background: Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 1.0,
|
||||
border_color: Color::BLACK,
|
||||
text_color: Color::BLACK,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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,149 +0,0 @@
|
||||
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::new(content).padding(15).style(SimpleCardStyle)
|
||||
}
|
||||
|
||||
pub struct SimpleCardStyle;
|
||||
impl widget::container::StyleSheet for SimpleCardStyle {
|
||||
type Style = iced::Theme;
|
||||
fn appearance(&self, _style: &Self::Style) -> widget::container::Appearance {
|
||||
widget::container::Appearance {
|
||||
border_radius: 10.0,
|
||||
border_color: color::BORDER_GREY,
|
||||
border_width: 1.0,
|
||||
background: color::FOREGROUND.into(),
|
||||
..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())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn invalid<'a, T: 'a, C: Into<Element<'a, T>>>(content: C) -> widget::Container<'a, T> {
|
||||
Container::new(content).padding(15).style(InvalidCardStyle)
|
||||
}
|
||||
|
||||
pub struct InvalidCardStyle;
|
||||
impl widget::container::StyleSheet for InvalidCardStyle {
|
||||
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.0,
|
||||
background: color::FOREGROUND.into(),
|
||||
..widget::container::Appearance::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InvalidCardStyle> for Box<dyn widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
fn from(s: InvalidCardStyle) -> Box<dyn widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
Box::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InvalidCardStyle> for iced::theme::Container {
|
||||
fn from(i: InvalidCardStyle) -> 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: String) -> widget::Container<'a, T> {
|
||||
Container::new(
|
||||
Row::new()
|
||||
.spacing(20)
|
||||
.align_items(iced::Alignment::Center)
|
||||
.push(icon::warning_octagon_icon().style(color::WARNING))
|
||||
.push(text(message).style(color::WARNING)),
|
||||
)
|
||||
.padding(15)
|
||||
.style(WarningCardStyle)
|
||||
}
|
||||
|
||||
pub struct WarningCardStyle;
|
||||
impl widget::container::StyleSheet for WarningCardStyle {
|
||||
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::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: &'static str, error: String) -> widget::Container<'a, T> {
|
||||
Container::new(
|
||||
Tooltip::new(
|
||||
Row::new()
|
||||
.spacing(20)
|
||||
.align_items(iced::Alignment::Center)
|
||||
.push(icon::warning_icon().style(color::ALERT))
|
||||
.push(text(message).style(color::ALERT)),
|
||||
error,
|
||||
widget::tooltip::Position::Bottom,
|
||||
)
|
||||
.style(ErrorCardStyle),
|
||||
)
|
||||
.padding(15)
|
||||
.style(ErrorCardStyle)
|
||||
}
|
||||
|
||||
pub struct ErrorCardStyle;
|
||||
impl widget::container::StyleSheet for ErrorCardStyle {
|
||||
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::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,37 +0,0 @@
|
||||
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::BORDER_GREY,
|
||||
..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,46 +0,0 @@
|
||||
pub mod badge;
|
||||
pub mod button;
|
||||
pub mod card;
|
||||
pub mod collapse;
|
||||
pub mod container;
|
||||
pub mod form;
|
||||
pub mod modal;
|
||||
pub mod notification;
|
||||
pub mod text;
|
||||
pub mod tooltip;
|
||||
|
||||
pub use tooltip::tooltip;
|
||||
|
||||
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(Text::new(" ")))
|
||||
.style(SepStyle)
|
||||
.height(Length::Units(1))
|
||||
}
|
||||
|
||||
pub struct SepStyle;
|
||||
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::BORDER_GREY.into(),
|
||||
..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,36 +0,0 @@
|
||||
use crate::ui::{color, icon};
|
||||
use iced::widget::{self, Tooltip};
|
||||
|
||||
pub fn tooltip<'a, T: 'a>(help: &'static str) -> Tooltip<'a, T> {
|
||||
Tooltip::new(
|
||||
icon::tooltip_icon().style(color::DARK_GREY),
|
||||
help,
|
||||
widget::tooltip::Position::Right,
|
||||
)
|
||||
.style(TooltipStyle)
|
||||
}
|
||||
pub struct TooltipStyle;
|
||||
impl widget::container::StyleSheet for TooltipStyle {
|
||||
type Style = iced::Theme;
|
||||
fn appearance(&self, _style: &Self::Style) -> widget::container::Appearance {
|
||||
widget::container::Appearance {
|
||||
border_radius: 10.0,
|
||||
border_color: color::DARK_GREY,
|
||||
border_width: 1.5,
|
||||
background: color::FOREGROUND.into(),
|
||||
..widget::container::Appearance::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TooltipStyle> for Box<dyn widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
fn from(s: TooltipStyle) -> Box<dyn widget::container::StyleSheet<Style = iced::Theme>> {
|
||||
Box::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TooltipStyle> for iced::theme::Container {
|
||||
fn from(i: TooltipStyle) -> iced::theme::Container {
|
||||
iced::theme::Container::Custom(i.into())
|
||||
}
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
pub mod color;
|
||||
/// component are wrappers around iced elements;
|
||||
pub mod component;
|
||||
pub mod font;
|
||||
pub mod icon;
|
||||
pub mod util;
|
||||
11
gui/ui/Cargo.toml
Normal file
11
gui/ui/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "liana_ui"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
iced = "0.7"
|
||||
iced_native = "0.8"
|
||||
iced_lazy = { version = "0.4"}
|
||||
6
gui/ui/README.md
Normal file
6
gui/ui/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# `liana_ui`
|
||||
|
||||
UI components used across the liana GUI iced application.
|
||||
|
||||
An wasm compatible example of the design system can be found in
|
||||
`./examples/design-system`
|
||||
12
gui/ui/examples/design-system/Cargo.toml
Normal file
12
gui/ui/examples/design-system/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "design-system"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
iced = "0.7"
|
||||
iced_native = "0.8"
|
||||
web-sys = "0.3.61"
|
||||
liana_ui = { path = "../.." }
|
||||
7
gui/ui/examples/design-system/README.md
Normal file
7
gui/ui/examples/design-system/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
## Use WASM
|
||||
|
||||
`trunk serve`
|
||||
|
||||
to build for a directory on a distant server
|
||||
|
||||
`trunk build --public-url /design-system`
|
||||
18
gui/ui/examples/design-system/index.html
Normal file
18
gui/ui/examples/design-system/index.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" content="text/html; charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Liana design system</title>
|
||||
<base data-trunk-public-url />
|
||||
<style>
|
||||
body {
|
||||
margin:0px;
|
||||
overflow:hidden;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<link data-trunk rel="rust" href="Cargo.toml" data-wasm-opt="z" data-bin="design-system" />
|
||||
</body>
|
||||
</html>
|
||||
175
gui/ui/examples/design-system/src/main.rs
Normal file
175
gui/ui/examples/design-system/src/main.rs
Normal file
@ -0,0 +1,175 @@
|
||||
mod section;
|
||||
|
||||
use iced::widget::{button, column, container, radio, row, text, Space};
|
||||
use iced::{executor, Application, Command, Length, Settings, Subscription};
|
||||
use liana_ui::{theme, widget::*};
|
||||
|
||||
pub fn main() -> iced::Result {
|
||||
DesignSystem::run(Settings::with_flags(Config {}))
|
||||
}
|
||||
|
||||
struct Config {}
|
||||
|
||||
#[derive(Default)]
|
||||
struct DesignSystem {
|
||||
theme: theme::Theme,
|
||||
sections: Vec<Box<dyn Section>>,
|
||||
current: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum ThemeType {
|
||||
Light,
|
||||
Dark,
|
||||
Legacy,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Message {
|
||||
ThemeChanged(ThemeType),
|
||||
Event(iced_native::Event),
|
||||
Section(usize),
|
||||
Ignore,
|
||||
}
|
||||
|
||||
impl Application for DesignSystem {
|
||||
type Message = Message;
|
||||
type Theme = theme::Theme;
|
||||
type Flags = Config;
|
||||
type Executor = executor::Default;
|
||||
|
||||
fn title(&self) -> String {
|
||||
String::from("Liana - Design System")
|
||||
}
|
||||
|
||||
fn new(_config: Config) -> (Self, Command<Self::Message>) {
|
||||
let app = Self {
|
||||
theme: theme::Theme::Light,
|
||||
sections: vec![
|
||||
Box::new(section::Overview {}),
|
||||
Box::new(section::Colors {}),
|
||||
Box::new(section::Buttons {}),
|
||||
],
|
||||
current: 0,
|
||||
};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
use iced_native::{command, window};
|
||||
let window = web_sys::window().unwrap();
|
||||
let (width, height) = (
|
||||
(window.inner_width().unwrap().as_f64().unwrap()) as u32,
|
||||
(window.inner_height().unwrap().as_f64().unwrap()) as u32,
|
||||
);
|
||||
(
|
||||
app,
|
||||
Command::single(command::Action::Window(window::Action::Resize {
|
||||
width,
|
||||
height,
|
||||
})),
|
||||
)
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
(app, Command::none())
|
||||
}
|
||||
|
||||
fn update(&mut self, message: Message) -> Command<Self::Message> {
|
||||
match message {
|
||||
Message::ThemeChanged(theme) => {
|
||||
self.theme = match theme {
|
||||
ThemeType::Light => theme::Theme::Light,
|
||||
ThemeType::Dark => theme::Theme::Dark,
|
||||
ThemeType::Legacy => theme::Theme::Legacy,
|
||||
}
|
||||
}
|
||||
Message::Section(i) => {
|
||||
if self.sections.get(i).is_some() {
|
||||
self.current = i;
|
||||
}
|
||||
}
|
||||
Message::Event(iced::Event::Window(iced_native::window::Event::Resized {
|
||||
width,
|
||||
height,
|
||||
})) => {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
use iced_native::{command, window};
|
||||
return Command::single(command::Action::Window(window::Action::Resize {
|
||||
width,
|
||||
height,
|
||||
}));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Command::none()
|
||||
}
|
||||
|
||||
fn subscription(&self) -> Subscription<Self::Message> {
|
||||
iced_native::subscription::events().map(Self::Message::Event)
|
||||
}
|
||||
|
||||
fn view(&self) -> Element<Message> {
|
||||
let sidebar = container(
|
||||
column![
|
||||
[ThemeType::Light, ThemeType::Dark].iter().fold(
|
||||
column![text("Choose a theme:")].spacing(10),
|
||||
|column, theme| {
|
||||
column.push(radio(
|
||||
format!("{theme:?}"),
|
||||
*theme,
|
||||
Some(match self.theme {
|
||||
theme::Theme::Light => ThemeType::Light,
|
||||
theme::Theme::Dark => ThemeType::Dark,
|
||||
theme::Theme::Legacy => ThemeType::Legacy,
|
||||
}),
|
||||
Message::ThemeChanged,
|
||||
))
|
||||
},
|
||||
),
|
||||
Space::with_height(Length::Units(100)),
|
||||
self.sections.iter().enumerate().fold(
|
||||
Column::new().spacing(10),
|
||||
|col, (i, section)| col.push(
|
||||
button(
|
||||
container(text(section.title()))
|
||||
.width(Length::Fill)
|
||||
.padding(5)
|
||||
)
|
||||
.style(if i == self.current {
|
||||
theme::Button::Primary
|
||||
} else {
|
||||
theme::Button::Transparent
|
||||
})
|
||||
.on_press(Message::Section(i))
|
||||
.width(Length::Units(200))
|
||||
)
|
||||
)
|
||||
]
|
||||
.spacing(20),
|
||||
)
|
||||
.padding(20)
|
||||
.style(theme::Container::Foreground)
|
||||
.height(Length::Fill);
|
||||
|
||||
container(row![
|
||||
sidebar.width(Length::Units(200)),
|
||||
Space::with_width(Length::Units(150)),
|
||||
column![
|
||||
Space::with_height(Length::Units(150)),
|
||||
container(self.sections[self.current].view()).width(Length::Fill)
|
||||
]
|
||||
])
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.into()
|
||||
}
|
||||
|
||||
fn theme(&self) -> theme::Theme {
|
||||
self.theme.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Section {
|
||||
fn title(&self) -> &'static str;
|
||||
fn view(&self) -> Element<Message>;
|
||||
}
|
||||
104
gui/ui/examples/design-system/src/section.rs
Normal file
104
gui/ui/examples/design-system/src/section.rs
Normal file
@ -0,0 +1,104 @@
|
||||
use iced::{
|
||||
alignment,
|
||||
widget::{button, column, container, row, Space},
|
||||
Alignment, Length,
|
||||
};
|
||||
use liana_ui::{color, component::text::*, theme, widget::Element};
|
||||
|
||||
use super::{Message, Section};
|
||||
|
||||
pub struct Overview {}
|
||||
|
||||
impl Section for Overview {
|
||||
fn title(&self) -> &'static str {
|
||||
"Overview"
|
||||
}
|
||||
|
||||
fn view(&self) -> Element<Message> {
|
||||
column![
|
||||
text("Hello").bold().size(50),
|
||||
column![text(
|
||||
"This is the Liana design system for the Iced framework"
|
||||
)]
|
||||
.spacing(10)
|
||||
]
|
||||
.spacing(100)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Colors {}
|
||||
|
||||
impl Section for Colors {
|
||||
fn title(&self) -> &'static str {
|
||||
"Colors"
|
||||
}
|
||||
|
||||
fn view(&self) -> Element<Message> {
|
||||
column![
|
||||
text(self.title()).bold().size(50),
|
||||
column![
|
||||
color_row(color::BLACK, "BLACK (0,0,0)"),
|
||||
color_row(color::LIGHT_BLACK, "LIGHT_BLACK #141414 original design"),
|
||||
color_row(color::GREEN, "GREEN #00FF66 original design"),
|
||||
color_row(color::DARK_GREY, "DARK_GREY #555555"),
|
||||
color_row(color::GREY, "GREY #CCCCCC original design"),
|
||||
color_row(color::LIGHT_GREY, "LIGHT_GREY #E6E6E6 original design"),
|
||||
color_row(color::RED, "RED #F04359"),
|
||||
color_row(color::ORANGE, "ORANGE #FFa700")
|
||||
]
|
||||
.spacing(10)
|
||||
]
|
||||
.spacing(100)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
fn color_row<'a, T: 'a>(color: iced::Color, label: &'static str) -> Element<'a, T> {
|
||||
row![
|
||||
container(Space::with_width(Length::Units(100)))
|
||||
.height(Length::Units(100))
|
||||
.style(theme::Container::Custom(color)),
|
||||
text(label)
|
||||
]
|
||||
.spacing(10)
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(10)
|
||||
.into()
|
||||
}
|
||||
|
||||
pub struct Buttons {}
|
||||
|
||||
impl Section for Buttons {
|
||||
fn title(&self) -> &'static str {
|
||||
"Buttons"
|
||||
}
|
||||
|
||||
fn view(&self) -> Element<Message> {
|
||||
column![
|
||||
text(self.title()).bold().size(50),
|
||||
column![
|
||||
button_row(theme::Button::Primary, "Primary"),
|
||||
button_row(theme::Button::Secondary, "Secondary"),
|
||||
button_row(theme::Button::Destructive, "Destructive"),
|
||||
button_row(theme::Button::Transparent, "Transparent")
|
||||
]
|
||||
.spacing(20)
|
||||
]
|
||||
.spacing(100)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
fn button_row(style: theme::Button, label: &'static str) -> Element<Message> {
|
||||
button(
|
||||
container(text(label))
|
||||
.width(Length::Fill)
|
||||
.align_x(alignment::Horizontal::Center),
|
||||
)
|
||||
.width(Length::Units(200))
|
||||
.padding(5)
|
||||
.style(style)
|
||||
.on_press(Message::Ignore)
|
||||
.into()
|
||||
}
|
||||
126
gui/ui/src/color.rs
Normal file
126
gui/ui/src/color.rs
Normal file
@ -0,0 +1,126 @@
|
||||
use iced::Color;
|
||||
|
||||
pub const BLACK: Color = iced::Color::BLACK;
|
||||
|
||||
pub const LIGHT_BLACK: Color = Color::from_rgb(
|
||||
0x14 as f32 / 255.0,
|
||||
0x14 as f32 / 255.0,
|
||||
0x14 as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const GREEN: Color = Color::from_rgb(
|
||||
0x00 as f32 / 255.0,
|
||||
0xFF as f32 / 255.0,
|
||||
0x66 as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const DARK_GREY: Color = Color::from_rgb(
|
||||
0x55 as f32 / 255.0,
|
||||
0x55 as f32 / 255.0,
|
||||
0x55 as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const GREY: Color = Color::from_rgb(
|
||||
0xCC as f32 / 255.0,
|
||||
0xCC as f32 / 255.0,
|
||||
0xCC as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const LIGHT_GREY: Color = Color::from_rgb(
|
||||
0xE6 as f32 / 255.0,
|
||||
0xE6 as f32 / 255.0,
|
||||
0xE6 as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const RED: Color = Color::from_rgb(
|
||||
0xF0 as f32 / 255.0,
|
||||
0x43 as f32 / 255.0,
|
||||
0x59 as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const ORANGE: Color =
|
||||
Color::from_rgb(0xFF as f32 / 255.0, 0xa7 as f32 / 255.0, 0x0 as f32 / 255.0);
|
||||
|
||||
pub mod legacy {
|
||||
use iced::Color;
|
||||
|
||||
pub const BACKGROUND: Color = Color::from_rgb(
|
||||
0xF6 as f32 / 255.0,
|
||||
0xF7 as f32 / 255.0,
|
||||
0xF8 as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const BORDER_GREY: Color = Color::from_rgb(
|
||||
0xd0 as f32 / 255.0,
|
||||
0xd7 as f32 / 255.0,
|
||||
0xde as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const FOREGROUND: Color = Color::WHITE;
|
||||
|
||||
pub const PRIMARY: Color = Color::BLACK;
|
||||
|
||||
pub const SECONDARY: Color = DARK_GREY;
|
||||
|
||||
pub const SUCCESS: Color = Color::from_rgb(
|
||||
0x29 as f32 / 255.0,
|
||||
0xBC as f32 / 255.0,
|
||||
0x97 as f32 / 255.0,
|
||||
);
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const SUCCESS_LIGHT: Color = Color::from_rgba(
|
||||
0x29 as f32 / 255.0,
|
||||
0xBC as f32 / 255.0,
|
||||
0x97 as f32 / 255.0,
|
||||
0.5f32,
|
||||
);
|
||||
|
||||
pub const ALERT: Color = Color::from_rgb(
|
||||
0xF0 as f32 / 255.0,
|
||||
0x43 as f32 / 255.0,
|
||||
0x59 as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const ALERT_LIGHT: Color = Color::from_rgba(
|
||||
0xF0 as f32 / 255.0,
|
||||
0x43 as f32 / 255.0,
|
||||
0x59 as f32 / 255.0,
|
||||
0.5f32,
|
||||
);
|
||||
|
||||
pub const WARNING: Color =
|
||||
Color::from_rgb(0xFF as f32 / 255.0, 0xa7 as f32 / 255.0, 0x0 as f32 / 255.0);
|
||||
|
||||
pub const WARNING_LIGHT: Color = Color::from_rgba(
|
||||
0xFF as f32 / 255.0,
|
||||
0xa7 as f32 / 255.0,
|
||||
0x0 as f32 / 255.0,
|
||||
0.5f32,
|
||||
);
|
||||
|
||||
pub const CANCEL: Color = Color::from_rgb(
|
||||
0x34 as f32 / 255.0,
|
||||
0x37 as f32 / 255.0,
|
||||
0x3D as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const INFO: Color = Color::from_rgb(
|
||||
0x2A as f32 / 255.0,
|
||||
0x98 as f32 / 255.0,
|
||||
0xBD as f32 / 255.0,
|
||||
);
|
||||
|
||||
pub const INFO_LIGHT: Color = Color::from_rgba(
|
||||
0x2A as f32 / 255.0,
|
||||
0x98 as f32 / 255.0,
|
||||
0xBD as f32 / 255.0,
|
||||
0.5f32,
|
||||
);
|
||||
|
||||
pub const DARK_GREY: Color = Color::from_rgb(
|
||||
0x8c as f32 / 255.0,
|
||||
0x97 as f32 / 255.0,
|
||||
0xa6 as f32 / 255.0,
|
||||
);
|
||||
}
|
||||
101
gui/ui/src/component/badge.rs
Normal file
101
gui/ui/src/component/badge.rs
Normal file
@ -0,0 +1,101 @@
|
||||
use iced::{widget::tooltip, Length};
|
||||
|
||||
use crate::{component::text::*, icon, theme, widget::*};
|
||||
|
||||
pub struct Badge {
|
||||
icon: crate::widget::Text<'static>,
|
||||
style: theme::Badge,
|
||||
}
|
||||
|
||||
impl Badge {
|
||||
pub fn new(icon: crate::widget::Text<'static>) -> Self {
|
||||
Self {
|
||||
icon,
|
||||
style: theme::Badge::Standard,
|
||||
}
|
||||
}
|
||||
pub fn style(self, style: theme::Badge) -> Self {
|
||||
Self {
|
||||
icon: self.icon,
|
||||
style,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(theme::Container::Badge(badge.style))
|
||||
.center_x()
|
||||
.center_y()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn receive<T>() -> Container<'static, T> {
|
||||
Container::new(icon::receive_icon().width(Length::Units(20)))
|
||||
.width(Length::Units(40))
|
||||
.height(Length::Units(40))
|
||||
.style(theme::Container::Badge(theme::Badge::Standard))
|
||||
.center_x()
|
||||
.center_y()
|
||||
}
|
||||
|
||||
pub fn spend<T>() -> Container<'static, T> {
|
||||
Container::new(icon::send_icon().width(Length::Units(20)))
|
||||
.width(Length::Units(40))
|
||||
.height(Length::Units(40))
|
||||
.style(theme::Container::Badge(theme::Badge::Standard))
|
||||
.center_x()
|
||||
.center_y()
|
||||
}
|
||||
|
||||
pub fn coin<T>() -> Container<'static, T> {
|
||||
Container::new(icon::coin_icon().width(Length::Units(20)))
|
||||
.width(Length::Units(40))
|
||||
.height(Length::Units(40))
|
||||
.style(theme::Container::Badge(theme::Badge::Standard))
|
||||
.center_x()
|
||||
.center_y()
|
||||
}
|
||||
|
||||
pub fn unconfirmed<'a, T: 'a>() -> Container<'a, T> {
|
||||
Container::new(
|
||||
tooltip::Tooltip::new(
|
||||
Container::new(text(" Unconfirmed ").small())
|
||||
.padding(3)
|
||||
.style(theme::Container::Pill(theme::Pill::Simple)),
|
||||
"Do not treat this as a payment until it is confirmed",
|
||||
tooltip::Position::Top,
|
||||
)
|
||||
.style(theme::Container::Card(theme::Card::Simple)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn deprecated<'a, T: 'a>() -> Container<'a, T> {
|
||||
Container::new(
|
||||
tooltip::Tooltip::new(
|
||||
Container::new(text(" Deprecated ").small())
|
||||
.padding(3)
|
||||
.style(theme::Container::Pill(theme::Pill::Simple)),
|
||||
"This spend cannot be included anymore in the blockchain",
|
||||
tooltip::Position::Top,
|
||||
)
|
||||
.style(theme::Container::Card(theme::Card::Simple)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn spent<'a, T: 'a>() -> Container<'a, T> {
|
||||
Container::new(
|
||||
tooltip::Tooltip::new(
|
||||
Container::new(text(" Spent ").small())
|
||||
.padding(3)
|
||||
.style(theme::Container::Pill(theme::Pill::Simple)),
|
||||
"The spend transaction was included in the blockchain",
|
||||
tooltip::Position::Top,
|
||||
)
|
||||
.style(theme::Container::Card(theme::Card::Simple)),
|
||||
)
|
||||
}
|
||||
40
gui/ui/src/component/button.rs
Normal file
40
gui/ui/src/component/button.rs
Normal file
@ -0,0 +1,40 @@
|
||||
use crate::{theme, widget::*};
|
||||
use iced::widget::{button, container, row};
|
||||
use iced::{Alignment, Length};
|
||||
|
||||
use super::text::text;
|
||||
|
||||
pub fn alert<'a, T: 'a>(icon: Option<Text<'a>>, t: &'static str) -> Button<'a, T> {
|
||||
button::Button::new(content(icon, t)).style(theme::Button::Destructive)
|
||||
}
|
||||
|
||||
pub fn primary<'a, T: 'a>(icon: Option<Text<'a>>, t: &'static str) -> Button<'a, T> {
|
||||
button::Button::new(content(icon, t)).style(theme::Button::Primary)
|
||||
}
|
||||
|
||||
pub fn transparent<'a, T: 'a>(icon: Option<Text<'a>>, t: &'static str) -> Button<'a, T> {
|
||||
button::Button::new(content(icon, t)).style(theme::Button::Transparent)
|
||||
}
|
||||
|
||||
pub fn border<'a, T: 'a>(icon: Option<Text<'a>>, t: &'static str) -> Button<'a, T> {
|
||||
button::Button::new(content(icon, t)).style(theme::Button::Secondary)
|
||||
}
|
||||
|
||||
pub fn transparent_border<'a, T: 'a>(icon: Option<Text<'a>>, t: &'static str) -> Button<'a, T> {
|
||||
button(content(icon, t)).style(theme::Button::TransparentBorder)
|
||||
}
|
||||
|
||||
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![i, text(t)]
|
||||
.spacing(10)
|
||||
.width(iced::Length::Fill)
|
||||
.align_items(Alignment::Center),
|
||||
)
|
||||
.width(iced::Length::Fill)
|
||||
.center_x()
|
||||
.padding(5),
|
||||
}
|
||||
}
|
||||
44
gui/ui/src/component/card.rs
Normal file
44
gui/ui/src/component/card.rs
Normal file
@ -0,0 +1,44 @@
|
||||
use crate::{color, component::text::text, icon, theme, widget::*};
|
||||
|
||||
pub fn simple<'a, T: 'a, C: Into<Element<'a, T>>>(content: C) -> Container<'a, T> {
|
||||
Container::new(content)
|
||||
.padding(15)
|
||||
.style(theme::Container::Card(theme::Card::Simple))
|
||||
}
|
||||
|
||||
pub fn invalid<'a, T: 'a, C: Into<Element<'a, T>>>(content: C) -> Container<'a, T> {
|
||||
Container::new(content)
|
||||
.padding(15)
|
||||
.style(theme::Container::Card(theme::Card::Invalid))
|
||||
}
|
||||
|
||||
/// display an error card with the message and the error in a tooltip.
|
||||
pub fn warning<'a, T: 'a>(message: String) -> Container<'a, T> {
|
||||
Container::new(
|
||||
Row::new()
|
||||
.spacing(20)
|
||||
.align_items(iced::Alignment::Center)
|
||||
.push(icon::warning_octagon_icon().style(color::legacy::WARNING))
|
||||
.push(text(message).style(color::legacy::WARNING)),
|
||||
)
|
||||
.padding(15)
|
||||
.style(theme::Container::Card(theme::Card::Warning))
|
||||
}
|
||||
|
||||
/// display an error card with the message and the error in a tooltip.
|
||||
pub fn error<'a, T: 'a>(message: &'static str, error: String) -> Container<'a, T> {
|
||||
Container::new(
|
||||
iced::widget::tooltip::Tooltip::new(
|
||||
Row::new()
|
||||
.spacing(20)
|
||||
.align_items(iced::Alignment::Center)
|
||||
.push(icon::warning_icon().style(color::legacy::ALERT))
|
||||
.push(text(message).style(color::legacy::ALERT)),
|
||||
error,
|
||||
iced::widget::tooltip::Position::Bottom,
|
||||
)
|
||||
.style(theme::Container::Card(theme::Card::Error)),
|
||||
)
|
||||
.padding(15)
|
||||
.style(theme::Container::Card(theme::Card::Error))
|
||||
}
|
||||
@ -1,7 +1,5 @@
|
||||
use iced::{
|
||||
widget::{Button, Column},
|
||||
Element,
|
||||
};
|
||||
use crate::widget::*;
|
||||
use iced::widget::column;
|
||||
use iced_lazy::{self, Component};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@ -36,7 +34,8 @@ pub enum Event<T> {
|
||||
Collapse(bool),
|
||||
}
|
||||
|
||||
impl<'a, Message, T, H, F, C> Component<Message, iced::Renderer> for Collapse<'a, Message, H, F, C>
|
||||
impl<'a, Message, T, H, F, C> Component<Message, iced::Renderer<crate::theme::Theme>>
|
||||
for Collapse<'a, Message, H, F, C>
|
||||
where
|
||||
T: Into<Message> + Clone + 'a,
|
||||
H: Fn() -> Button<'a, Event<T>>,
|
||||
@ -58,14 +57,13 @@ where
|
||||
|
||||
fn view(&self, state: &Self::State) -> Element<Self::Event> {
|
||||
if *state {
|
||||
Column::new()
|
||||
.push((self.after)().on_press(Event::Collapse(false)))
|
||||
.push((self.content)().map(Event::Internal))
|
||||
.into()
|
||||
column![
|
||||
(self.after)().on_press(Event::Collapse(false)),
|
||||
(self.content)().map(Event::Internal)
|
||||
]
|
||||
.into()
|
||||
} else {
|
||||
Column::new()
|
||||
.push((self.before)().on_press(Event::Collapse(true)))
|
||||
.into()
|
||||
column![(self.before)().on_press(Event::Collapse(true))].into()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,9 +73,9 @@ impl<'a, Message, T, H: 'a, F: 'a, C: 'a> From<Collapse<'a, Message, H, F, C>>
|
||||
where
|
||||
Message: 'a,
|
||||
T: Into<Message> + Clone + 'a,
|
||||
H: Fn() -> Button<'a, Event<T>, iced::Renderer>,
|
||||
F: Fn() -> Button<'a, Event<T>, iced::Renderer>,
|
||||
C: Fn() -> Element<'a, T, iced::Renderer>,
|
||||
H: Fn() -> Button<'a, Event<T>>,
|
||||
F: Fn() -> Button<'a, Event<T>>,
|
||||
C: Fn() -> Element<'a, T>,
|
||||
{
|
||||
fn from(c: Collapse<'a, Message, H, F, C>) -> Self {
|
||||
iced_lazy::component(c)
|
||||
@ -1,12 +1,6 @@
|
||||
use iced::{
|
||||
widget::{
|
||||
text_input::{Appearance, StyleSheet, TextInput},
|
||||
Column, Container,
|
||||
},
|
||||
Element, Length,
|
||||
};
|
||||
use iced::{widget::text_input, Length};
|
||||
|
||||
use crate::ui::{color, component::text::*, util::Collection};
|
||||
use crate::{color, component::text::*, theme, util::Collection, widget::*};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Value<T> {
|
||||
@ -24,7 +18,7 @@ impl std::default::Default for Value<String> {
|
||||
}
|
||||
|
||||
pub struct Form<'a, Message> {
|
||||
input: TextInput<'a, Message>,
|
||||
input: text_input::TextInput<'a, Message, iced::Renderer<theme::Theme>>,
|
||||
warning: Option<&'a str>,
|
||||
valid: bool,
|
||||
}
|
||||
@ -44,7 +38,7 @@ where
|
||||
F: 'static + Fn(String) -> Message,
|
||||
{
|
||||
Self {
|
||||
input: TextInput::new(placeholder, &value.value, on_change),
|
||||
input: text_input::TextInput::new(placeholder, &value.value, on_change),
|
||||
warning: None,
|
||||
valid: value.valid,
|
||||
}
|
||||
@ -74,13 +68,13 @@ impl<'a, Message: 'a + Clone> From<Form<'a, Message>> for Element<'a, Message> {
|
||||
Container::new(
|
||||
Column::new()
|
||||
.push(if !form.valid {
|
||||
form.input.style(InvalidFormStyle)
|
||||
form.input.style(theme::Form::Invalid)
|
||||
} else {
|
||||
form.input
|
||||
})
|
||||
.push_maybe(if !form.valid {
|
||||
form.warning
|
||||
.map(|message| text(message).style(color::ALERT).small())
|
||||
.map(|message| text(message).style(color::legacy::ALERT).small())
|
||||
} else {
|
||||
None
|
||||
})
|
||||
@ -91,47 +85,3 @@ impl<'a, Message: 'a + Clone> From<Form<'a, Message>> for Element<'a, Message> {
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
struct InvalidFormStyle;
|
||||
impl StyleSheet for InvalidFormStyle {
|
||||
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,
|
||||
border_color: color::ALERT,
|
||||
}
|
||||
}
|
||||
|
||||
fn focused(&self, style: &Self::Style) -> Appearance {
|
||||
Appearance {
|
||||
border_color: color::ALERT,
|
||||
..self.active(style)
|
||||
}
|
||||
}
|
||||
|
||||
fn placeholder_color(&self, _style: &Self::Style) -> iced::Color {
|
||||
iced::Color::from_rgb(0.7, 0.7, 0.7)
|
||||
}
|
||||
|
||||
fn value_color(&self, _style: &Self::Style) -> iced::Color {
|
||||
iced::Color::from_rgb(0.3, 0.3, 0.3)
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
21
gui/ui/src/component/mod.rs
Normal file
21
gui/ui/src/component/mod.rs
Normal file
@ -0,0 +1,21 @@
|
||||
pub mod badge;
|
||||
pub mod button;
|
||||
pub mod card;
|
||||
pub mod collapse;
|
||||
pub mod form;
|
||||
pub mod modal;
|
||||
pub mod notification;
|
||||
pub mod text;
|
||||
pub mod tooltip;
|
||||
|
||||
pub use tooltip::tooltip;
|
||||
|
||||
use iced::Length;
|
||||
|
||||
use crate::{theme, widget::*};
|
||||
|
||||
pub fn separation<'a, T: 'a>() -> Container<'a, T> {
|
||||
Container::new(Column::new().push(Text::new(" ")))
|
||||
.style(theme::Container::Border)
|
||||
.height(Length::Units(1))
|
||||
}
|
||||
@ -1,12 +1,9 @@
|
||||
use crate::ui::{
|
||||
color,
|
||||
component::{button, collapse, text::*},
|
||||
icon,
|
||||
};
|
||||
use iced::{
|
||||
widget::{container, Button, Container, Row},
|
||||
Alignment, Element, Length,
|
||||
use crate::{
|
||||
component::{collapse, text::*},
|
||||
icon, theme,
|
||||
widget::*,
|
||||
};
|
||||
use iced::{Alignment, Length};
|
||||
|
||||
pub fn warning<'a, T: 'a + Clone>(message: String, error: String) -> Container<'a, T> {
|
||||
let message_clone = message.clone();
|
||||
@ -26,7 +23,7 @@ pub fn warning<'a, T: 'a + Clone>(message: String, error: String) -> Container<'
|
||||
.push(icon::collapse_icon()),
|
||||
),
|
||||
)
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
},
|
||||
move || {
|
||||
Button::new(
|
||||
@ -42,37 +39,11 @@ pub fn warning<'a, T: 'a + Clone>(message: String, error: String) -> Container<'
|
||||
.push(icon::collapsed_icon()),
|
||||
),
|
||||
)
|
||||
.style(button::Style::Transparent.into())
|
||||
.style(theme::Button::Transparent)
|
||||
},
|
||||
move || Element::<'a, T>::from(text(error.to_owned()).small()),
|
||||
)))
|
||||
.padding(15)
|
||||
.style(WarningStyle)
|
||||
.style(theme::Container::Card(theme::Card::Warning))
|
||||
.width(Length::Fill)
|
||||
}
|
||||
|
||||
pub struct WarningStyle;
|
||||
impl container::StyleSheet for WarningStyle {
|
||||
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::Appearance::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,9 @@
|
||||
use crate::ui::font;
|
||||
use crate::{font, theme::Theme};
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub const TEXT_REGULAR_SIZE: u16 = 25;
|
||||
|
||||
pub fn text<'a>(content: impl Into<Cow<'a, str>>) -> iced::widget::Text<'a> {
|
||||
pub fn text<'a>(content: impl Into<Cow<'a, str>>) -> iced::widget::Text<'a, iced::Renderer<Theme>> {
|
||||
iced::widget::Text::new(content)
|
||||
.font(font::REGULAR)
|
||||
.size(TEXT_REGULAR_SIZE)
|
||||
@ -14,7 +14,7 @@ pub trait Text {
|
||||
fn small(self) -> Self;
|
||||
}
|
||||
|
||||
impl Text for iced::widget::Text<'_> {
|
||||
impl Text for iced::widget::Text<'_, iced::Renderer<Theme>> {
|
||||
fn bold(self) -> Self {
|
||||
self.font(font::BOLD)
|
||||
}
|
||||
12
gui/ui/src/component/tooltip.rs
Normal file
12
gui/ui/src/component/tooltip.rs
Normal file
@ -0,0 +1,12 @@
|
||||
use crate::{icon, theme, widget::*};
|
||||
|
||||
pub fn tooltip<'a, T: 'a>(help: &'static str) -> Container<'a, T> {
|
||||
Container::new(
|
||||
iced::widget::tooltip::Tooltip::new(
|
||||
icon::tooltip_icon(),
|
||||
help,
|
||||
iced::widget::tooltip::Position::Right,
|
||||
)
|
||||
.style(theme::Container::Card(theme::Card::Simple)),
|
||||
)
|
||||
}
|
||||
@ -2,10 +2,10 @@ use iced::Font;
|
||||
|
||||
pub const BOLD: Font = Font::External {
|
||||
name: "Bold",
|
||||
bytes: include_bytes!("../../static/fonts/OpenSans-Bold.ttf"),
|
||||
bytes: include_bytes!("../static/fonts/OpenSans-Bold.ttf"),
|
||||
};
|
||||
|
||||
pub const REGULAR: Font = Font::External {
|
||||
name: "Regular",
|
||||
bytes: include_bytes!("../../static/fonts/OpenSans-Regular.ttf"),
|
||||
bytes: include_bytes!("../static/fonts/OpenSans-Regular.ttf"),
|
||||
};
|
||||
@ -1,8 +1,9 @@
|
||||
use iced::{alignment, widget::Text, Font, Length};
|
||||
use crate::widget::*;
|
||||
use iced::{alignment, Font, Length};
|
||||
|
||||
const ICONS: Font = Font::External {
|
||||
name: "Icons",
|
||||
bytes: include_bytes!("../../static/icons/bootstrap-icons.ttf"),
|
||||
bytes: include_bytes!("../static/icons/bootstrap-icons.ttf"),
|
||||
};
|
||||
|
||||
fn icon(unicode: char) -> Text<'static> {
|
||||
23
gui/ui/src/lib.rs
Normal file
23
gui/ui/src/lib.rs
Normal file
@ -0,0 +1,23 @@
|
||||
pub mod color;
|
||||
pub mod component;
|
||||
pub mod font;
|
||||
pub mod icon;
|
||||
pub mod theme;
|
||||
pub mod util;
|
||||
|
||||
pub mod widget {
|
||||
#![allow(dead_code)]
|
||||
use crate::theme::Theme;
|
||||
|
||||
pub type Renderer = iced::Renderer<Theme>;
|
||||
pub type Element<'a, Message> = iced::Element<'a, Message, Renderer>;
|
||||
pub type Container<'a, Message> = iced::widget::Container<'a, Message, Renderer>;
|
||||
pub type Column<'a, Message> = iced::widget::Column<'a, Message, Renderer>;
|
||||
pub type Row<'a, Message> = iced::widget::Row<'a, Message, Renderer>;
|
||||
pub type Button<'a, Message> = iced::widget::Button<'a, Message, Renderer>;
|
||||
pub type Text<'a> = iced::widget::Text<'a, Renderer>;
|
||||
pub type Tooltip<'a> = iced::widget::Tooltip<'a, Renderer>;
|
||||
pub type ProgressBar = iced::widget::ProgressBar<Renderer>;
|
||||
pub type PickList<'a, Message> = iced::widget::PickList<'a, Message, Renderer>;
|
||||
pub type Scrollable<'a, Message> = iced::widget::Scrollable<'a, Message, Renderer>;
|
||||
}
|
||||
781
gui/ui/src/theme.rs
Normal file
781
gui/ui/src/theme.rs
Normal file
@ -0,0 +1,781 @@
|
||||
use iced::{
|
||||
application,
|
||||
widget::{
|
||||
button, checkbox, container, pick_list, progress_bar, radio, scrollable, text, text_input,
|
||||
},
|
||||
};
|
||||
|
||||
use super::color;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
|
||||
pub enum Theme {
|
||||
Dark,
|
||||
Light,
|
||||
#[default]
|
||||
Legacy,
|
||||
}
|
||||
|
||||
impl application::StyleSheet for Theme {
|
||||
type Style = ();
|
||||
|
||||
fn appearance(&self, _style: &Self::Style) -> application::Appearance {
|
||||
match self {
|
||||
Theme::Light => application::Appearance {
|
||||
background_color: color::LIGHT_GREY,
|
||||
text_color: color::LIGHT_BLACK,
|
||||
},
|
||||
Theme::Dark => application::Appearance {
|
||||
background_color: color::LIGHT_BLACK,
|
||||
text_color: color::LIGHT_GREY,
|
||||
},
|
||||
Theme::Legacy => application::Appearance {
|
||||
background_color: color::legacy::BACKGROUND,
|
||||
text_color: color::BLACK,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub enum Overlay {
|
||||
#[default]
|
||||
Default,
|
||||
}
|
||||
impl iced::overlay::menu::StyleSheet for Theme {
|
||||
type Style = Overlay;
|
||||
|
||||
fn appearance(&self, _style: &Self::Style) -> iced::overlay::menu::Appearance {
|
||||
iced::overlay::menu::Appearance {
|
||||
text_color: color::BLACK,
|
||||
background: color::LIGHT_GREY.into(),
|
||||
border_width: 1.0,
|
||||
border_radius: 0.0,
|
||||
border_color: color::GREEN,
|
||||
selected_text_color: color::BLACK,
|
||||
selected_background: color::GREEN.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<PickList> for Overlay {
|
||||
fn from(_p: PickList) -> Overlay {
|
||||
Overlay::Default
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub enum Text {
|
||||
#[default]
|
||||
Default,
|
||||
Color(iced::Color),
|
||||
}
|
||||
|
||||
impl From<iced::Color> for Text {
|
||||
fn from(color: iced::Color) -> Self {
|
||||
Text::Color(color)
|
||||
}
|
||||
}
|
||||
|
||||
impl text::StyleSheet for Theme {
|
||||
type Style = Text;
|
||||
|
||||
fn appearance(&self, style: Self::Style) -> text::Appearance {
|
||||
match style {
|
||||
Text::Default => Default::default(),
|
||||
Text::Color(c) => text::Appearance { color: Some(c) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub enum Container {
|
||||
#[default]
|
||||
Transparent,
|
||||
Background,
|
||||
Foreground,
|
||||
Border,
|
||||
Card(Card),
|
||||
Badge(Badge),
|
||||
Pill(Pill),
|
||||
Custom(iced::Color),
|
||||
}
|
||||
|
||||
impl container::StyleSheet for Theme {
|
||||
type Style = Container;
|
||||
fn appearance(&self, style: &Self::Style) -> iced::widget::container::Appearance {
|
||||
match self {
|
||||
Theme::Light => match style {
|
||||
Container::Transparent => container::Appearance {
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Container::Background => container::Appearance {
|
||||
background: color::LIGHT_GREY.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Container::Foreground => container::Appearance {
|
||||
background: color::GREY.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Container::Border => container::Appearance {
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
border_width: 1.0,
|
||||
border_color: color::LIGHT_BLACK,
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Container::Card(c) => c.appearance(self),
|
||||
Container::Badge(c) => c.appearance(self),
|
||||
Container::Pill(c) => c.appearance(self),
|
||||
Container::Custom(c) => container::Appearance {
|
||||
background: (*c).into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
},
|
||||
Theme::Dark => match style {
|
||||
Container::Transparent => container::Appearance {
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Container::Background => container::Appearance {
|
||||
background: color::LIGHT_BLACK.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Container::Foreground => container::Appearance {
|
||||
background: color::BLACK.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Container::Border => container::Appearance {
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
border_width: 1.0,
|
||||
border_color: color::LIGHT_GREY,
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Container::Card(c) => c.appearance(self),
|
||||
Container::Badge(c) => c.appearance(self),
|
||||
Container::Pill(c) => c.appearance(self),
|
||||
Container::Custom(c) => container::Appearance {
|
||||
background: (*c).into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
},
|
||||
Theme::Legacy => match style {
|
||||
Container::Transparent => container::Appearance {
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Container::Background => container::Appearance {
|
||||
background: color::legacy::BACKGROUND.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Container::Foreground => container::Appearance {
|
||||
background: color::legacy::FOREGROUND.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Container::Border => container::Appearance {
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
border_width: 1.0,
|
||||
border_color: color::legacy::BORDER_GREY,
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Container::Card(c) => c.appearance(self),
|
||||
Container::Badge(c) => c.appearance(self),
|
||||
Container::Pill(c) => c.appearance(self),
|
||||
Container::Custom(c) => container::Appearance {
|
||||
background: (*c).into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Card> for Container {
|
||||
fn from(c: Card) -> Container {
|
||||
Container::Card(c)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Badge> for Container {
|
||||
fn from(c: Badge) -> Container {
|
||||
Container::Badge(c)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Pill> for Container {
|
||||
fn from(c: Pill) -> Container {
|
||||
Container::Pill(c)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub enum Card {
|
||||
#[default]
|
||||
Simple,
|
||||
Invalid,
|
||||
Warning,
|
||||
Error,
|
||||
}
|
||||
|
||||
impl Card {
|
||||
fn appearance(&self, theme: &Theme) -> iced::widget::container::Appearance {
|
||||
match theme {
|
||||
Theme::Light => match self {
|
||||
Card::Simple => container::Appearance {
|
||||
background: color::GREY.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Card::Invalid => container::Appearance {
|
||||
background: color::GREY.into(),
|
||||
text_color: color::BLACK.into(),
|
||||
border_width: 1.0,
|
||||
border_color: color::RED,
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Card::Error => container::Appearance {
|
||||
background: color::GREY.into(),
|
||||
text_color: color::RED.into(),
|
||||
border_width: 1.0,
|
||||
border_color: color::RED,
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Card::Warning => container::Appearance {
|
||||
background: color::ORANGE.into(),
|
||||
text_color: color::GREY.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
},
|
||||
Theme::Dark => match self {
|
||||
Card::Simple => container::Appearance {
|
||||
background: color::LIGHT_BLACK.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Card::Invalid => container::Appearance {
|
||||
background: color::LIGHT_BLACK.into(),
|
||||
text_color: color::BLACK.into(),
|
||||
border_width: 1.0,
|
||||
border_color: color::RED,
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Card::Error => container::Appearance {
|
||||
background: color::LIGHT_BLACK.into(),
|
||||
text_color: color::RED.into(),
|
||||
border_width: 1.0,
|
||||
border_color: color::RED,
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Card::Warning => container::Appearance {
|
||||
background: color::ORANGE.into(),
|
||||
text_color: color::GREY.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
},
|
||||
Theme::Legacy => match self {
|
||||
Card::Simple => container::Appearance {
|
||||
background: color::legacy::FOREGROUND.into(),
|
||||
border_radius: 10.0,
|
||||
border_color: color::legacy::BORDER_GREY,
|
||||
border_width: 1.0,
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Card::Invalid => container::Appearance {
|
||||
background: color::legacy::FOREGROUND.into(),
|
||||
text_color: iced::Color::BLACK.into(),
|
||||
border_width: 1.0,
|
||||
border_radius: 10.0,
|
||||
border_color: color::legacy::ALERT,
|
||||
},
|
||||
Card::Error => container::Appearance {
|
||||
background: color::legacy::FOREGROUND.into(),
|
||||
text_color: color::legacy::ALERT.into(),
|
||||
border_width: 1.0,
|
||||
border_radius: 10.0,
|
||||
border_color: color::legacy::ALERT,
|
||||
},
|
||||
Card::Warning => container::Appearance {
|
||||
border_radius: 0.0,
|
||||
text_color: iced::Color::BLACK.into(),
|
||||
background: color::legacy::WARNING.into(),
|
||||
border_color: color::legacy::WARNING,
|
||||
..container::Appearance::default()
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub enum Badge {
|
||||
#[default]
|
||||
Standard,
|
||||
Bitcoin,
|
||||
}
|
||||
|
||||
impl Badge {
|
||||
fn appearance(&self, _theme: &Theme) -> iced::widget::container::Appearance {
|
||||
match self {
|
||||
Self::Standard => container::Appearance {
|
||||
border_radius: 40.0,
|
||||
background: color::legacy::BACKGROUND.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Self::Bitcoin => container::Appearance {
|
||||
border_radius: 40.0,
|
||||
background: color::legacy::WARNING.into(),
|
||||
text_color: iced::Color::WHITE.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub enum Pill {
|
||||
#[default]
|
||||
Simple,
|
||||
InversePrimary,
|
||||
Primary,
|
||||
Success,
|
||||
}
|
||||
|
||||
impl Pill {
|
||||
fn appearance(&self, _theme: &Theme) -> iced::widget::container::Appearance {
|
||||
match self {
|
||||
Self::Primary => container::Appearance {
|
||||
background: color::legacy::PRIMARY.into(),
|
||||
border_radius: 10.0,
|
||||
text_color: iced::Color::WHITE.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Self::InversePrimary => container::Appearance {
|
||||
background: color::legacy::FOREGROUND.into(),
|
||||
border_radius: 10.0,
|
||||
text_color: color::legacy::PRIMARY.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Self::Success => container::Appearance {
|
||||
background: color::legacy::SUCCESS.into(),
|
||||
border_radius: 10.0,
|
||||
text_color: iced::Color::WHITE.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
Self::Simple => container::Appearance {
|
||||
background: color::legacy::BACKGROUND.into(),
|
||||
border_radius: 10.0,
|
||||
text_color: iced::Color::BLACK.into(),
|
||||
..container::Appearance::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Radio {}
|
||||
impl radio::StyleSheet for Theme {
|
||||
type Style = Radio;
|
||||
|
||||
fn active(&self, _style: &Self::Style, _is_selected: bool) -> radio::Appearance {
|
||||
radio::Appearance {
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
dot_color: color::GREEN,
|
||||
border_width: 1.0,
|
||||
border_color: color::GREEN,
|
||||
text_color: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn hovered(&self, style: &Self::Style, is_selected: bool) -> radio::Appearance {
|
||||
let active = self.active(style, is_selected);
|
||||
radio::Appearance {
|
||||
dot_color: color::GREEN,
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
..active
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct Scrollable {}
|
||||
impl scrollable::StyleSheet for Theme {
|
||||
type Style = Scrollable;
|
||||
|
||||
fn active(&self, _style: &Self::Style) -> scrollable::Scrollbar {
|
||||
scrollable::Scrollbar {
|
||||
background: None,
|
||||
border_width: 0.0,
|
||||
border_color: color::legacy::BORDER_GREY,
|
||||
border_radius: 10.0,
|
||||
scroller: scrollable::Scroller {
|
||||
color: color::legacy::BORDER_GREY,
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn hovered(&self, style: &Self::Style) -> scrollable::Scrollbar {
|
||||
let active = self.active(style);
|
||||
scrollable::Scrollbar { ..active }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub enum PickList {
|
||||
#[default]
|
||||
Simple,
|
||||
}
|
||||
impl pick_list::StyleSheet for Theme {
|
||||
type Style = PickList;
|
||||
|
||||
fn active(&self, _style: &Self::Style) -> pick_list::Appearance {
|
||||
pick_list::Appearance {
|
||||
placeholder_color: color::legacy::FOREGROUND,
|
||||
handle_color: color::legacy::FOREGROUND,
|
||||
background: color::legacy::FOREGROUND.into(),
|
||||
border_width: 1.0,
|
||||
border_color: color::legacy::BORDER_GREY,
|
||||
border_radius: 10.0,
|
||||
text_color: iced::Color::BLACK,
|
||||
}
|
||||
}
|
||||
|
||||
fn hovered(&self, style: &Self::Style) -> pick_list::Appearance {
|
||||
let active = self.active(style);
|
||||
pick_list::Appearance { ..active }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CheckBox {}
|
||||
impl checkbox::StyleSheet for Theme {
|
||||
type Style = CheckBox;
|
||||
|
||||
fn active(&self, _style: &Self::Style, _is_selected: bool) -> checkbox::Appearance {
|
||||
checkbox::Appearance {
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
border_width: 1.0,
|
||||
border_color: color::GREY,
|
||||
checkmark_color: color::GREEN,
|
||||
text_color: None,
|
||||
border_radius: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
fn hovered(&self, style: &Self::Style, is_selected: bool) -> checkbox::Appearance {
|
||||
let active = self.active(style, is_selected);
|
||||
checkbox::Appearance { ..active }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub enum Button {
|
||||
#[default]
|
||||
Primary,
|
||||
Secondary,
|
||||
Destructive,
|
||||
Transparent,
|
||||
TransparentBorder,
|
||||
}
|
||||
|
||||
impl button::StyleSheet for Theme {
|
||||
type Style = Button;
|
||||
|
||||
fn active(&self, style: &Self::Style) -> button::Appearance {
|
||||
match self {
|
||||
Theme::Light => match style {
|
||||
Button::Primary => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::LIGHT_BLACK.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::LIGHT_GREY,
|
||||
},
|
||||
Button::Secondary => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 1.0,
|
||||
border_color: color::DARK_GREY,
|
||||
text_color: color::LIGHT_BLACK,
|
||||
},
|
||||
Button::Destructive => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::RED.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::LIGHT_GREY,
|
||||
},
|
||||
Button::Transparent | Button::TransparentBorder => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::LIGHT_BLACK,
|
||||
},
|
||||
},
|
||||
Theme::Dark => match style {
|
||||
Button::Primary => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::GREY.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::LIGHT_BLACK,
|
||||
},
|
||||
Button::Secondary => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::LIGHT_BLACK.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 1.0,
|
||||
border_color: color::LIGHT_GREY,
|
||||
text_color: color::LIGHT_GREY,
|
||||
},
|
||||
Button::Destructive => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::RED.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::LIGHT_BLACK,
|
||||
},
|
||||
Button::Transparent | Button::TransparentBorder => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::LIGHT_GREY,
|
||||
},
|
||||
},
|
||||
Theme::Legacy => match style {
|
||||
Button::Primary => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::legacy::PRIMARY.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::legacy::FOREGROUND,
|
||||
},
|
||||
Button::Destructive => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::legacy::FOREGROUND.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: color::legacy::ALERT,
|
||||
text_color: color::legacy::ALERT,
|
||||
},
|
||||
Button::Transparent | Button::TransparentBorder => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: iced::Color::BLACK,
|
||||
},
|
||||
Button::Secondary => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 1.2,
|
||||
border_color: color::legacy::BORDER_GREY,
|
||||
text_color: iced::Color::BLACK,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn hovered(&self, style: &Self::Style) -> button::Appearance {
|
||||
match self {
|
||||
Theme::Light => match style {
|
||||
Button::Primary => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::LIGHT_BLACK.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::LIGHT_GREY,
|
||||
},
|
||||
Button::Secondary => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::LIGHT_BLACK.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::LIGHT_GREY,
|
||||
},
|
||||
Button::Destructive => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::RED.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::LIGHT_GREY,
|
||||
},
|
||||
Button::Transparent => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::DARK_GREY.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::LIGHT_GREY,
|
||||
},
|
||||
Button::TransparentBorder => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::DARK_GREY.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 1.0,
|
||||
border_color: color::LIGHT_BLACK,
|
||||
text_color: color::LIGHT_GREY,
|
||||
},
|
||||
},
|
||||
Theme::Dark => match style {
|
||||
Button::Primary => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::GREY.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::LIGHT_BLACK,
|
||||
},
|
||||
Button::Secondary => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::GREY.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::LIGHT_BLACK,
|
||||
},
|
||||
Button::Destructive => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::RED.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::LIGHT_BLACK,
|
||||
},
|
||||
Button::Transparent => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::DARK_GREY.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::LIGHT_GREY,
|
||||
},
|
||||
Button::TransparentBorder => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::DARK_GREY.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 1.0,
|
||||
border_color: color::LIGHT_GREY,
|
||||
text_color: color::LIGHT_GREY,
|
||||
},
|
||||
},
|
||||
Theme::Legacy => match style {
|
||||
Button::Primary => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::legacy::PRIMARY.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: color::legacy::FOREGROUND,
|
||||
},
|
||||
Button::Destructive => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: color::legacy::FOREGROUND.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: color::legacy::ALERT,
|
||||
text_color: color::legacy::ALERT,
|
||||
},
|
||||
Button::Transparent => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 0.0,
|
||||
border_color: iced::Color::TRANSPARENT,
|
||||
text_color: iced::Color::BLACK,
|
||||
},
|
||||
Button::TransparentBorder => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 1.0,
|
||||
border_color: iced::Color::BLACK,
|
||||
text_color: iced::Color::BLACK,
|
||||
},
|
||||
Button::Secondary => button::Appearance {
|
||||
shadow_offset: iced::Vector::default(),
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
border_radius: 10.0,
|
||||
border_width: 1.0,
|
||||
border_color: iced::Color::BLACK,
|
||||
text_color: iced::Color::BLACK,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub enum Form {
|
||||
#[default]
|
||||
Simple,
|
||||
Invalid,
|
||||
}
|
||||
|
||||
impl text_input::StyleSheet for Theme {
|
||||
type Style = Form;
|
||||
fn active(&self, style: &Self::Style) -> text_input::Appearance {
|
||||
match style {
|
||||
Form::Simple => text_input::Appearance {
|
||||
background: iced::Background::Color(color::legacy::FOREGROUND),
|
||||
border_radius: 5.0,
|
||||
border_width: 1.0,
|
||||
border_color: color::legacy::DARK_GREY,
|
||||
},
|
||||
Form::Invalid => text_input::Appearance {
|
||||
background: iced::Background::Color(color::legacy::FOREGROUND),
|
||||
border_radius: 5.0,
|
||||
border_width: 1.0,
|
||||
border_color: color::legacy::ALERT,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn focused(&self, style: &Self::Style) -> text_input::Appearance {
|
||||
text_input::Appearance {
|
||||
..self.active(style)
|
||||
}
|
||||
}
|
||||
|
||||
fn placeholder_color(&self, _style: &Self::Style) -> iced::Color {
|
||||
iced::Color::from_rgb(0.7, 0.7, 0.7)
|
||||
}
|
||||
|
||||
fn value_color(&self, _style: &Self::Style) -> iced::Color {
|
||||
iced::Color::from_rgb(0.3, 0.3, 0.3)
|
||||
}
|
||||
|
||||
fn selection_color(&self, _style: &Self::Style) -> iced::Color {
|
||||
iced::Color::from_rgb(0.8, 0.8, 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub enum ProgressBar {
|
||||
#[default]
|
||||
Simple,
|
||||
}
|
||||
|
||||
impl progress_bar::StyleSheet for Theme {
|
||||
type Style = ProgressBar;
|
||||
fn appearance(&self, _style: &Self::Style) -> progress_bar::Appearance {
|
||||
progress_bar::Appearance {
|
||||
background: iced::Color::TRANSPARENT.into(),
|
||||
bar: color::GREEN.into(),
|
||||
border_radius: 10.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,5 @@
|
||||
/// from hecjr idea on Discord
|
||||
use iced::{
|
||||
widget::{Column, Row},
|
||||
Element,
|
||||
};
|
||||
use crate::widget::*;
|
||||
|
||||
pub trait Collection<'a, Message>: Sized {
|
||||
fn push(self, element: impl Into<Element<'a, Message>>) -> Self;
|
||||
Loading…
x
Reference in New Issue
Block a user