ui: wallet connection selector/creator modal, separate modal content for connection creation, move settings into wallet
This commit is contained in:
parent
8d66087d68
commit
f142ae110a
21 changed files with 514 additions and 359 deletions
|
@ -319,7 +319,11 @@ impl Modal {
|
|||
// Draw title content.
|
||||
let title_resp = ui.allocate_ui_at_rect(rect, |ui| {
|
||||
ui.vertical_centered_justified(|ui| {
|
||||
ui.add_space(Self::DEFAULT_MARGIN);
|
||||
ui.add_space(Self::DEFAULT_MARGIN + if !View::is_desktop() {
|
||||
1.0
|
||||
} else {
|
||||
0.0
|
||||
});
|
||||
ui.label(RichText::new(self.title.as_ref().unwrap())
|
||||
.size(19.0)
|
||||
.color(Colors::title(true))
|
||||
|
|
|
@ -12,33 +12,22 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use egui::{Align, Id, Layout, RichText, Rounding};
|
||||
use url::Url;
|
||||
use egui::{Align, Layout, RichText, Rounding};
|
||||
|
||||
use crate::AppConfig;
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{CARET_RIGHT, CHECK_CIRCLE, COMPUTER_TOWER, DOTS_THREE_CIRCLE, GLOBE_SIMPLE, PENCIL, PLUS_CIRCLE, POWER, TRASH, X_CIRCLE};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Modal, NodeSetup, View};
|
||||
use crate::gui::views::types::{ModalContainer, ModalPosition, TextEditOptions};
|
||||
use crate::gui::views::modals::ExternalConnectionModal;
|
||||
use crate::gui::views::types::{ModalContainer, ModalPosition};
|
||||
use crate::node::{Node, NodeConfig};
|
||||
use crate::wallet::{ConnectionsConfig, ExternalConnection};
|
||||
|
||||
/// Network connections content.
|
||||
pub struct ConnectionsContent {
|
||||
/// Flag to check if [`Modal`] was just opened to focus on input field.
|
||||
first_modal_launch: bool,
|
||||
/// External connection URL value for [`Modal`].
|
||||
ext_node_url_edit: String,
|
||||
/// External connection API secret value for [`Modal`].
|
||||
ext_node_secret_edit: String,
|
||||
/// Flag to show URL format error at [`Modal`].
|
||||
ext_node_url_error: bool,
|
||||
/// Editing external connection identifier for [`Modal`].
|
||||
ext_conn_id_edit: Option<i64>,
|
||||
|
||||
/// Flag to check connections availability.
|
||||
check_connections: bool,
|
||||
/// External connection [`Modal`] content.
|
||||
ext_conn_modal: ExternalConnectionModal,
|
||||
|
||||
/// [`Modal`] identifiers allowed at this ui container.
|
||||
modal_ids: Vec<&'static str>
|
||||
|
@ -46,15 +35,11 @@ pub struct ConnectionsContent {
|
|||
|
||||
impl Default for ConnectionsContent {
|
||||
fn default() -> Self {
|
||||
ExternalConnection::check_ext_conn_availability(None);
|
||||
Self {
|
||||
first_modal_launch: true,
|
||||
ext_node_url_edit: "".to_string(),
|
||||
ext_node_secret_edit: "".to_string(),
|
||||
ext_node_url_error: false,
|
||||
ext_conn_id_edit: None,
|
||||
check_connections: true,
|
||||
ext_conn_modal: ExternalConnectionModal::new(None),
|
||||
modal_ids: vec![
|
||||
Self::NETWORK_EXT_CONNECTION_MODAL
|
||||
ExternalConnectionModal::NETWORK_ID
|
||||
],
|
||||
}
|
||||
}
|
||||
|
@ -70,18 +55,17 @@ impl ModalContainer for ConnectionsContent {
|
|||
modal: &Modal,
|
||||
cb: &dyn PlatformCallbacks) {
|
||||
match modal.id {
|
||||
Self::NETWORK_EXT_CONNECTION_MODAL => self.ext_conn_modal_ui(ui, modal, cb),
|
||||
ExternalConnectionModal::NETWORK_ID => {
|
||||
self.ext_conn_modal.ui(ui, cb, modal, |_| {});
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConnectionsContent {
|
||||
/// External connection [`Modal`] identifier.
|
||||
pub const NETWORK_EXT_CONNECTION_MODAL: &'static str = "network_ext_connection_modal";
|
||||
|
||||
/// Draw connections content.
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) {
|
||||
// Draw modal content for current ui container.
|
||||
self.current_modal_ui(ui, cb);
|
||||
|
||||
ui.add_space(2.0);
|
||||
|
@ -93,11 +77,7 @@ impl ConnectionsContent {
|
|||
|
||||
// Check connections availability.
|
||||
if saved_chain_type != AppConfig::chain_type() {
|
||||
self.check_connections = true;
|
||||
}
|
||||
if self.check_connections {
|
||||
ExternalConnection::start_ext_conn_availability_check();
|
||||
self.check_connections = false;
|
||||
ExternalConnection::check_ext_conn_availability(None);
|
||||
}
|
||||
|
||||
// Show integrated node info content.
|
||||
|
@ -127,7 +107,19 @@ impl ConnectionsContent {
|
|||
for (index, conn) in ext_conn_list.iter().enumerate() {
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
// Draw connection list item.
|
||||
self.ext_conn_item_ui(ui, conn, index, ext_conn_list.len(), cb);
|
||||
let len = ext_conn_list.len();
|
||||
Self::ext_conn_item_ui(ui, conn, index, len, |ui| {
|
||||
// Draw buttons for non-default connections.
|
||||
if conn.url != ExternalConnection::DEFAULT_MAIN_URL {
|
||||
let button_rounding = View::item_rounding(index, len, true);
|
||||
View::item_button(ui, button_rounding, TRASH, None, || {
|
||||
ConnectionsConfig::remove_ext_conn(conn.id);
|
||||
});
|
||||
View::item_button(ui, Rounding::default(), PENCIL, None, || {
|
||||
self.show_add_ext_conn_modal(Some(conn.clone()), cb);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -191,12 +183,11 @@ impl ConnectionsContent {
|
|||
}
|
||||
|
||||
/// Draw external connection item content.
|
||||
fn ext_conn_item_ui(&mut self,
|
||||
ui: &mut egui::Ui,
|
||||
conn: &ExternalConnection,
|
||||
index: usize,
|
||||
len: usize,
|
||||
cb: &dyn PlatformCallbacks) {
|
||||
pub fn ext_conn_item_ui(ui: &mut egui::Ui,
|
||||
conn: &ExternalConnection,
|
||||
index: usize,
|
||||
len: usize,
|
||||
buttons_ui: impl FnOnce(&mut egui::Ui)) {
|
||||
// Setup layout size.
|
||||
let mut rect = ui.available_rect_before_wrap();
|
||||
rect.set_height(52.0);
|
||||
|
@ -208,16 +199,8 @@ impl ConnectionsContent {
|
|||
|
||||
ui.vertical(|ui| {
|
||||
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
|
||||
// Draw buttons for non-default connections.
|
||||
if conn.url != ExternalConnection::DEFAULT_MAIN_URL {
|
||||
let button_rounding = View::item_rounding(index, len, true);
|
||||
View::item_button(ui, button_rounding, TRASH, None, || {
|
||||
ConnectionsConfig::remove_ext_conn(conn.id);
|
||||
});
|
||||
View::item_button(ui, Rounding::default(), PENCIL, None, || {
|
||||
self.show_add_ext_conn_modal(Some(conn), cb);
|
||||
});
|
||||
}
|
||||
// Draw provided buttons.
|
||||
buttons_ui(ui);
|
||||
|
||||
let layout_size = ui.available_size();
|
||||
ui.allocate_ui_with_layout(layout_size, Layout::left_to_right(Align::Center), |ui| {
|
||||
|
@ -249,123 +232,14 @@ impl ConnectionsContent {
|
|||
|
||||
/// Show [`Modal`] to add external connection.
|
||||
pub fn show_add_ext_conn_modal(&mut self,
|
||||
conn: Option<&ExternalConnection>,
|
||||
conn: Option<ExternalConnection>,
|
||||
cb: &dyn PlatformCallbacks) {
|
||||
// Setup values.
|
||||
self.first_modal_launch = true;
|
||||
self.ext_node_url_error = false;
|
||||
if let Some(c) = conn {
|
||||
self.ext_node_url_edit = c.url.to_owned();
|
||||
self.ext_node_secret_edit = c.secret.clone().unwrap_or("".to_string());
|
||||
self.ext_conn_id_edit = Some(c.id);
|
||||
} else {
|
||||
self.ext_node_url_edit = "".to_string();
|
||||
self.ext_node_secret_edit = "".to_string();
|
||||
self.ext_conn_id_edit = None;
|
||||
}
|
||||
self.ext_conn_modal = ExternalConnectionModal::new(conn);
|
||||
// Show modal.
|
||||
Modal::new(Self::NETWORK_EXT_CONNECTION_MODAL)
|
||||
Modal::new(ExternalConnectionModal::NETWORK_ID)
|
||||
.position(ModalPosition::CenterTop)
|
||||
.title(t!("wallets.add_node"))
|
||||
.show();
|
||||
cb.show_keyboard();
|
||||
}
|
||||
|
||||
/// Draw external connection [`Modal`] content.
|
||||
pub fn ext_conn_modal_ui(&mut self,
|
||||
ui: &mut egui::Ui,
|
||||
modal: &Modal,
|
||||
cb: &dyn PlatformCallbacks) {
|
||||
ui.add_space(6.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("wallets.node_url"))
|
||||
.size(17.0)
|
||||
.color(Colors::gray()));
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Draw node URL text edit.
|
||||
let url_edit_id = Id::from(modal.id).with(self.ext_conn_id_edit);
|
||||
let mut url_edit_opts = TextEditOptions::new(url_edit_id).paste().no_focus();
|
||||
if self.first_modal_launch {
|
||||
self.first_modal_launch = false;
|
||||
url_edit_opts.focus = true;
|
||||
}
|
||||
View::text_edit(ui, cb, &mut self.ext_node_url_edit, &mut url_edit_opts);
|
||||
ui.add_space(8.0);
|
||||
|
||||
ui.label(RichText::new(t!("wallets.node_secret"))
|
||||
.size(17.0)
|
||||
.color(Colors::gray()));
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Draw node API secret text edit.
|
||||
let secret_edit_id = Id::from(modal.id).with(self.ext_conn_id_edit).with("node_secret");
|
||||
let mut secret_edit_opts = TextEditOptions::new(secret_edit_id).paste().no_focus();
|
||||
View::text_edit(ui, cb, &mut self.ext_node_secret_edit, &mut secret_edit_opts);
|
||||
|
||||
// Show error when specified URL is not valid.
|
||||
if self.ext_node_url_error {
|
||||
ui.add_space(12.0);
|
||||
ui.label(RichText::new(t!("wallets.invalid_url"))
|
||||
.size(17.0)
|
||||
.color(Colors::red()));
|
||||
}
|
||||
ui.add_space(12.0);
|
||||
});
|
||||
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
||||
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.cancel"), Colors::white_or_black(false), || {
|
||||
// Close modal.
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
});
|
||||
});
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
// Add connection button callback.
|
||||
let mut on_add = || {
|
||||
if !self.ext_node_url_edit.starts_with("http") {
|
||||
self.ext_node_url_edit = format!("http://{}", self.ext_node_url_edit)
|
||||
}
|
||||
let error = Url::parse(self.ext_node_url_edit.as_str()).is_err();
|
||||
self.ext_node_url_error = error;
|
||||
if !error {
|
||||
let url = self.ext_node_url_edit.to_owned();
|
||||
let secret = if self.ext_node_secret_edit.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(self.ext_node_secret_edit.to_owned())
|
||||
};
|
||||
|
||||
// Update or create new connection.
|
||||
let mut ext_conn = ExternalConnection::new(url, secret);
|
||||
if let Some(id) = self.ext_conn_id_edit {
|
||||
ext_conn.id = id;
|
||||
}
|
||||
self.ext_conn_id_edit = None;
|
||||
ConnectionsConfig::add_ext_conn(ext_conn);
|
||||
self.check_connections = true;
|
||||
|
||||
// Close modal.
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
}
|
||||
};
|
||||
|
||||
// Add connection on Enter button press.
|
||||
View::on_enter_key(ui, || {
|
||||
(on_add)();
|
||||
});
|
||||
|
||||
View::button(ui, t!("modal.save"), Colors::white_or_black(false), on_add);
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -206,7 +206,7 @@ impl NetworkContent {
|
|||
View::title_button_big(ui, DOTS_THREE_OUTLINE_VERTICAL, |_| {
|
||||
AppConfig::toggle_show_connections_network_panel();
|
||||
if AppConfig::show_connections_network_panel() {
|
||||
ExternalConnection::start_ext_conn_availability_check();
|
||||
ExternalConnection::check_ext_conn_availability(None);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -33,4 +33,5 @@ pub use content::*;
|
|||
mod connections;
|
||||
pub use connections::*;
|
||||
|
||||
pub mod types;
|
||||
pub mod types;
|
||||
pub mod modals;
|
166
src/gui/views/network/modals/ext_conn.rs
Normal file
166
src/gui/views/network/modals/ext_conn.rs
Normal file
|
@ -0,0 +1,166 @@
|
|||
// Copyright 2024 The Grim Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use egui::{Id, RichText};
|
||||
use url::Url;
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Modal, View};
|
||||
use crate::gui::views::types::TextEditOptions;
|
||||
use crate::wallet::{ConnectionsConfig, ExternalConnection};
|
||||
|
||||
/// Content to create or update external wallet connection.
|
||||
pub struct ExternalConnectionModal {
|
||||
/// Flag to check if [`Modal`] was just opened to focus on input field.
|
||||
first_modal_launch: bool,
|
||||
/// External connection URL value for [`Modal`].
|
||||
ext_node_url_edit: String,
|
||||
/// External connection API secret value for [`Modal`].
|
||||
ext_node_secret_edit: String,
|
||||
/// Flag to show URL format error at [`Modal`].
|
||||
ext_node_url_error: bool,
|
||||
/// Editing external connection identifier for [`Modal`].
|
||||
ext_conn_id: Option<i64>,
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl ExternalConnectionModal {
|
||||
/// Network [`Modal`] identifier.
|
||||
pub const NETWORK_ID: &'static str = "net_ext_conn_modal";
|
||||
/// Wallet [`Modal`] identifier.
|
||||
pub const WALLET_ID: &'static str = "wallet_ext_conn_modal";
|
||||
|
||||
/// Create new instance from optional provided connection to update.
|
||||
pub fn new(conn: Option<ExternalConnection>) -> Self {
|
||||
let (ext_node_url_edit, ext_node_secret_edit, ext_conn_id) = if let Some(c) = conn {
|
||||
(c.url, c.secret.unwrap_or("".to_string()), Some(c.id))
|
||||
} else {
|
||||
("".to_string(), "".to_string(), None)
|
||||
};
|
||||
Self {
|
||||
first_modal_launch: true,
|
||||
ext_node_url_edit,
|
||||
ext_node_secret_edit,
|
||||
ext_node_url_error: false,
|
||||
ext_conn_id,
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw external connection [`Modal`] content.
|
||||
pub fn ui(&mut self,
|
||||
ui: &mut egui::Ui,
|
||||
cb: &dyn PlatformCallbacks,
|
||||
modal: &Modal,
|
||||
on_save: impl Fn(ExternalConnection)) {
|
||||
ui.add_space(6.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("wallets.node_url"))
|
||||
.size(17.0)
|
||||
.color(Colors::gray()));
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Draw node URL text edit.
|
||||
let url_edit_id = Id::from(modal.id).with(self.ext_conn_id);
|
||||
let mut url_edit_opts = TextEditOptions::new(url_edit_id).paste().no_focus();
|
||||
if self.first_modal_launch {
|
||||
self.first_modal_launch = false;
|
||||
url_edit_opts.focus = true;
|
||||
}
|
||||
View::text_edit(ui, cb, &mut self.ext_node_url_edit, &mut url_edit_opts);
|
||||
ui.add_space(8.0);
|
||||
|
||||
ui.label(RichText::new(t!("wallets.node_secret"))
|
||||
.size(17.0)
|
||||
.color(Colors::gray()));
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Draw node API secret text edit.
|
||||
let secret_edit_id = Id::from(modal.id).with(self.ext_conn_id).with("node_secret");
|
||||
let mut secret_edit_opts = TextEditOptions::new(secret_edit_id).paste().no_focus();
|
||||
View::text_edit(ui, cb, &mut self.ext_node_secret_edit, &mut secret_edit_opts);
|
||||
|
||||
// Show error when specified URL is not valid.
|
||||
if self.ext_node_url_error {
|
||||
ui.add_space(12.0);
|
||||
ui.label(RichText::new(t!("wallets.invalid_url"))
|
||||
.size(17.0)
|
||||
.color(Colors::red()));
|
||||
}
|
||||
ui.add_space(12.0);
|
||||
});
|
||||
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
||||
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.cancel"), Colors::white_or_black(false), || {
|
||||
// Close modal.
|
||||
self.ext_node_url_edit = "".to_string();
|
||||
self.ext_node_secret_edit = "".to_string();
|
||||
self.ext_node_url_error = false;
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
});
|
||||
});
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
// Add connection button callback.
|
||||
let mut on_add = || {
|
||||
if !self.ext_node_url_edit.starts_with("http") {
|
||||
self.ext_node_url_edit = format!("http://{}", self.ext_node_url_edit)
|
||||
}
|
||||
let error = Url::parse(self.ext_node_url_edit.as_str()).is_err();
|
||||
self.ext_node_url_error = error;
|
||||
if !error {
|
||||
let url = self.ext_node_url_edit.to_owned();
|
||||
let secret = if self.ext_node_secret_edit.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(self.ext_node_secret_edit.to_owned())
|
||||
};
|
||||
|
||||
// Update or create new connection.
|
||||
let mut ext_conn = ExternalConnection::new(url, secret);
|
||||
if let Some(id) = self.ext_conn_id {
|
||||
ext_conn.id = id;
|
||||
}
|
||||
ConnectionsConfig::add_ext_conn(ext_conn.clone());
|
||||
ExternalConnection::check_ext_conn_availability(Some(ext_conn.id));
|
||||
on_save(ext_conn);
|
||||
|
||||
// Close modal.
|
||||
self.ext_node_url_edit = "".to_string();
|
||||
self.ext_node_secret_edit = "".to_string();
|
||||
self.ext_node_url_error = false;
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
}
|
||||
};
|
||||
View::on_enter_key(ui, || {
|
||||
(on_add)();
|
||||
});
|
||||
View::button(ui, if self.ext_conn_id.is_some() {
|
||||
t!("modal.save")
|
||||
} else {
|
||||
t!("modal.add")
|
||||
}, Colors::white_or_black(false), on_add);
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
}
|
||||
}
|
16
src/gui/views/network/modals/mod.rs
Normal file
16
src/gui/views/network/modals/mod.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2024 The Grim Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
mod ext_conn;
|
||||
pub use ext_conn::*;
|
|
@ -110,7 +110,11 @@ impl TitlePanel {
|
|||
ui.vertical_centered(|ui| {
|
||||
match content {
|
||||
TitleContentType::Title(text) => {
|
||||
ui.add_space(13.0);
|
||||
ui.add_space(13.0 + if !View::is_desktop() {
|
||||
1.0
|
||||
} else {
|
||||
0.0
|
||||
});
|
||||
View::ellipsize_text(ui, text, 19.0, Colors::title(true));
|
||||
}
|
||||
TitleContentType::WithSubTitle(text, subtitle, animate) => {
|
||||
|
|
|
@ -23,6 +23,7 @@ use crate::gui::platform::PlatformCallbacks;
|
|||
use crate::gui::views::{Modal, Content, TitlePanel, View};
|
||||
use crate::gui::views::types::{ModalContainer, ModalPosition, TextEditOptions, TitleContentType, TitleType};
|
||||
use crate::gui::views::wallets::creation::WalletCreation;
|
||||
use crate::gui::views::wallets::modals::WalletConnectionModal;
|
||||
use crate::gui::views::wallets::types::WalletTabType;
|
||||
use crate::gui::views::wallets::WalletContent;
|
||||
use crate::wallet::{Wallet, WalletList};
|
||||
|
@ -34,9 +35,12 @@ pub struct WalletsContent {
|
|||
|
||||
/// Password to open wallet for [`Modal`].
|
||||
pass_edit: String,
|
||||
/// Flag to check if wrong password was entered.
|
||||
/// Flag to check if wrong password was entered at [`Modal`].
|
||||
wrong_pass: bool,
|
||||
|
||||
/// Wallet connection selection content.
|
||||
conn_modal_content: Option<WalletConnectionModal>,
|
||||
|
||||
/// Selected [`Wallet`] content.
|
||||
wallet_content: WalletContent,
|
||||
/// Wallet creation content.
|
||||
|
@ -58,12 +62,14 @@ impl Default for WalletsContent {
|
|||
wallets: WalletList::default(),
|
||||
pass_edit: "".to_string(),
|
||||
wrong_pass: false,
|
||||
conn_modal_content: None,
|
||||
wallet_content: WalletContent::default(),
|
||||
creation_content: WalletCreation::default(),
|
||||
show_wallets_at_dual_panel: AppConfig::show_wallets_at_dual_panel(),
|
||||
modal_ids: vec![
|
||||
OPEN_WALLET_MODAL,
|
||||
WalletCreation::NAME_PASS_MODAL
|
||||
WalletCreation::NAME_PASS_MODAL,
|
||||
WalletConnectionModal::ID,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -83,6 +89,18 @@ impl ModalContainer for WalletsContent {
|
|||
WalletCreation::NAME_PASS_MODAL => {
|
||||
self.creation_content.name_pass_modal_ui(ui, modal, cb)
|
||||
},
|
||||
WalletConnectionModal::ID => {
|
||||
if let Some(content) = self.conn_modal_content.as_mut() {
|
||||
content.ui(ui, modal, cb, |id| {
|
||||
let list = self.wallets.list();
|
||||
for w in list {
|
||||
if self.wallets.selected_id == Some(w.get_config().id) {
|
||||
w.update_ext_conn_id(id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -384,6 +402,7 @@ impl WalletsContent {
|
|||
let id = config.id;
|
||||
let is_selected = self.wallets.selected_id == Some(id);
|
||||
let current = is_selected && wallet.is_open();
|
||||
|
||||
// Draw round background.
|
||||
let mut rect = ui.available_rect_before_wrap();
|
||||
rect.set_height(78.0);
|
||||
|
@ -405,17 +424,21 @@ impl WalletsContent {
|
|||
self.wallets.select(Some(id));
|
||||
self.show_open_wallet_modal(cb);
|
||||
});
|
||||
// Show button to select connection if not syncing.
|
||||
if !wallet.syncing() {
|
||||
View::item_button(ui, Rounding::default(), GLOBE, None, || {
|
||||
self.wallets.select(Some(id));
|
||||
self.show_connection_selector_modal(wallet);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if !is_selected {
|
||||
// Show button to select opened wallet.
|
||||
View::item_button(ui, View::item_rounding(0, 1, true), CARET_RIGHT, None, || {
|
||||
// Reset wallet content.
|
||||
self.wallet_content = WalletContent::default();
|
||||
// Select wallet.
|
||||
self.wallets.select(Some(id));
|
||||
self.wallet_content = WalletContent::default();
|
||||
});
|
||||
}
|
||||
|
||||
// Show button to close opened wallet.
|
||||
if !wallet.is_closing() {
|
||||
View::item_button(ui, if !is_selected {
|
||||
|
@ -492,8 +515,19 @@ impl WalletsContent {
|
|||
});
|
||||
}
|
||||
|
||||
/// Show [`Modal`] to select connection for the wallet.
|
||||
fn show_connection_selector_modal(&mut self, wallet: &Wallet) {
|
||||
let ext_conn = wallet.get_current_ext_conn();
|
||||
self.conn_modal_content = Some(WalletConnectionModal::new(ext_conn));
|
||||
// Show modal.
|
||||
Modal::new(WalletConnectionModal::ID)
|
||||
.position(ModalPosition::CenterTop)
|
||||
.title(t!("wallets.conn_method"))
|
||||
.show();
|
||||
}
|
||||
|
||||
/// Show [`Modal`] to open selected wallet.
|
||||
pub fn show_open_wallet_modal(&mut self, cb: &dyn PlatformCallbacks) {
|
||||
fn show_open_wallet_modal(&mut self, cb: &dyn PlatformCallbacks) {
|
||||
// Reset modal values.
|
||||
self.pass_edit = String::from("");
|
||||
self.wrong_pass = false;
|
||||
|
|
|
@ -23,7 +23,7 @@ use crate::gui::views::{Modal, Content, View};
|
|||
use crate::gui::views::types::{ModalPosition, TextEditOptions};
|
||||
use crate::gui::views::wallets::creation::MnemonicSetup;
|
||||
use crate::gui::views::wallets::creation::types::Step;
|
||||
use crate::gui::views::wallets::setup::ConnectionSetup;
|
||||
use crate::gui::views::wallets::settings::ConnectionSettings;
|
||||
use crate::node::Node;
|
||||
use crate::wallet::{ExternalConnection, Wallet};
|
||||
use crate::wallet::types::PhraseMode;
|
||||
|
@ -43,7 +43,7 @@ pub struct WalletCreation {
|
|||
/// Mnemonic phrase setup content.
|
||||
pub(crate) mnemonic_setup: MnemonicSetup,
|
||||
/// Network setup content.
|
||||
pub(crate) network_setup: ConnectionSetup
|
||||
pub(crate) network_setup: ConnectionSettings
|
||||
}
|
||||
|
||||
impl Default for WalletCreation {
|
||||
|
@ -54,7 +54,7 @@ impl Default for WalletCreation {
|
|||
name_edit: String::from(""),
|
||||
pass_edit: String::from(""),
|
||||
mnemonic_setup: MnemonicSetup::default(),
|
||||
network_setup: ConnectionSetup::default()
|
||||
network_setup: ConnectionSettings::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -304,7 +304,7 @@ impl WalletCreation {
|
|||
|
||||
// Check external connections availability on connection setup.
|
||||
if self.step == Some(Step::SetupConnection) {
|
||||
ExternalConnection::start_ext_conn_availability_check();
|
||||
ExternalConnection::check_ext_conn_availability(None);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
mod modals;
|
||||
mod creation;
|
||||
mod setup;
|
||||
|
||||
mod content;
|
||||
pub use content::*;
|
||||
|
|
154
src/gui/views/wallets/modals/connection.rs
Normal file
154
src/gui/views/wallets/modals/connection.rs
Normal file
|
@ -0,0 +1,154 @@
|
|||
// Copyright 2024 The Grim Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use egui::{RichText, ScrollArea};
|
||||
use egui::scroll_area::ScrollBarVisibility;
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{CHECK, CHECK_FAT, PLUS_CIRCLE};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{ConnectionsContent, Modal, View};
|
||||
use crate::gui::views::modals::ExternalConnectionModal;
|
||||
use crate::wallet::{ConnectionsConfig, ExternalConnection};
|
||||
|
||||
/// Wallet connection content.
|
||||
pub struct WalletConnectionModal {
|
||||
/// Current external connection.
|
||||
pub ext_conn: Option<ExternalConnection>,
|
||||
|
||||
/// Flag to show connection creation.
|
||||
show_conn_creation: bool,
|
||||
|
||||
add_ext_conn_content: ExternalConnectionModal
|
||||
}
|
||||
|
||||
impl WalletConnectionModal {
|
||||
/// Identifier for [`Modal`].
|
||||
pub const ID: &'static str = "select_connection_modal";
|
||||
|
||||
/// Create from provided wallet connection.
|
||||
pub fn new(ext_conn: Option<ExternalConnection>) -> Self {
|
||||
ExternalConnection::check_ext_conn_availability(None);
|
||||
Self {
|
||||
ext_conn,
|
||||
show_conn_creation: false,
|
||||
add_ext_conn_content: ExternalConnectionModal::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw [`Modal`] content.
|
||||
pub fn ui(&mut self,
|
||||
ui: &mut egui::Ui,
|
||||
modal: &Modal,
|
||||
cb: &dyn PlatformCallbacks,
|
||||
on_select: impl Fn(Option<i64>)) {
|
||||
ui.add_space(4.0);
|
||||
|
||||
// Draw external connection creation content.
|
||||
if self.show_conn_creation {
|
||||
self.add_ext_conn_content.ui(ui, cb, modal, |conn| {
|
||||
on_select(Some(conn.id));
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let ext_conn_list = ConnectionsConfig::ext_conn_list();
|
||||
ScrollArea::vertical()
|
||||
.max_height(if ext_conn_list.len() < 4 {
|
||||
330.0
|
||||
} else {
|
||||
323.0
|
||||
})
|
||||
.id_source("integrated_node")
|
||||
.scroll_bar_visibility(ScrollBarVisibility::AlwaysHidden)
|
||||
.auto_shrink([false; 2])
|
||||
.show(ui, |ui| {
|
||||
ui.add_space(2.0);
|
||||
|
||||
// Show integrated node selection.
|
||||
ConnectionsContent::integrated_node_item_ui(ui, |ui| {
|
||||
let is_current_method = self.ext_conn.is_none();
|
||||
if !is_current_method {
|
||||
View::item_button(ui, View::item_rounding(0, 1, true), CHECK, None, || {
|
||||
self.ext_conn = None;
|
||||
on_select(None);
|
||||
modal.close();
|
||||
});
|
||||
} else {
|
||||
ui.add_space(14.0);
|
||||
ui.label(RichText::new(CHECK_FAT).size(20.0).color(Colors::green()));
|
||||
ui.add_space(14.0);
|
||||
}
|
||||
});
|
||||
|
||||
// Show button to add new external node connection.
|
||||
ui.add_space(8.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("wallets.ext_conn"))
|
||||
.size(16.0)
|
||||
.color(Colors::gray()));
|
||||
ui.add_space(6.0);
|
||||
let add_node_text = format!("{} {}", PLUS_CIRCLE, t!("wallets.add_node"));
|
||||
View::button(ui, add_node_text, Colors::button(), || {
|
||||
self.show_conn_creation = true;
|
||||
});
|
||||
});
|
||||
ui.add_space(4.0);
|
||||
|
||||
if !ext_conn_list.is_empty() {
|
||||
ui.add_space(8.0);
|
||||
for (index, conn) in ext_conn_list.iter().enumerate() {
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
// Draw external connection item.
|
||||
let len = ext_conn_list.len();
|
||||
ConnectionsContent::ext_conn_item_ui(ui, conn, index, len, |ui| {
|
||||
// Draw button to select connection.
|
||||
let is_current_method = if let Some(c) = self.ext_conn.as_ref() {
|
||||
c.id == conn.id
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if !is_current_method {
|
||||
let button_rounding = View::item_rounding(index, len, true);
|
||||
View::item_button(ui, button_rounding, CHECK, None, || {
|
||||
self.ext_conn = Some(conn.clone());
|
||||
on_select(Some(conn.id));
|
||||
modal.close();
|
||||
});
|
||||
} else {
|
||||
ui.add_space(12.0);
|
||||
ui.label(RichText::new(CHECK_FAT)
|
||||
.size(20.0)
|
||||
.color(Colors::green()));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
ui.add_space(4.0);
|
||||
});
|
||||
|
||||
ui.add_space(2.0);
|
||||
View::horizontal_line(ui, Colors::stroke());
|
||||
ui.add_space(6.0);
|
||||
|
||||
// Show button to close modal.
|
||||
ui.vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.cancel"), Colors::white_or_black(false), || {
|
||||
modal.close();
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2023 The Grim Developers
|
||||
// Copyright 2024 The Grim Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -13,10 +13,4 @@
|
|||
// limitations under the License.
|
||||
|
||||
mod connection;
|
||||
pub use connection::ConnectionSetup;
|
||||
|
||||
mod common;
|
||||
pub use common::CommonSetup;
|
||||
|
||||
mod recovery;
|
||||
pub use recovery::RecoverySetup;
|
||||
pub use connection::*;
|
|
@ -24,8 +24,9 @@ use crate::gui::icons::{ARROWS_CLOCKWISE, BRIDGE, CHAT_CIRCLE_TEXT, CHECK, CHECK
|
|||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{CameraContent, Modal, Content, View};
|
||||
use crate::gui::views::types::{ModalPosition, QrScanResult, TextEditOptions};
|
||||
use crate::gui::views::wallets::{WalletTransactions, WalletMessages, WalletTransport, WalletSettings};
|
||||
use crate::gui::views::wallets::{WalletTransactions, WalletMessages, WalletTransport};
|
||||
use crate::gui::views::wallets::types::{GRIN, WalletTab, WalletTabType};
|
||||
use crate::gui::views::wallets::settings::WalletSettings;
|
||||
use crate::node::Node;
|
||||
use crate::wallet::{Wallet, WalletConfig};
|
||||
use crate::wallet::types::{WalletAccount, WalletData};
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
pub mod types;
|
||||
pub mod settings;
|
||||
|
||||
mod txs;
|
||||
pub use txs::WalletTransactions;
|
||||
|
@ -23,8 +24,5 @@ pub use messages::WalletMessages;
|
|||
mod transport;
|
||||
pub use transport::WalletTransport;
|
||||
|
||||
mod settings;
|
||||
pub use settings::WalletSettings;
|
||||
|
||||
mod content;
|
||||
pub use content::WalletContent;
|
|
@ -21,8 +21,8 @@ use crate::gui::views::{Modal, View};
|
|||
use crate::gui::views::types::{ModalPosition, TextEditOptions};
|
||||
use crate::wallet::Wallet;
|
||||
|
||||
/// Common wallet setup content.
|
||||
pub struct CommonSetup {
|
||||
/// Common wallet settings content.
|
||||
pub struct CommonSettings {
|
||||
/// Wallet name [`Modal`] value.
|
||||
name_edit: String,
|
||||
|
||||
|
@ -46,7 +46,7 @@ const PASS_EDIT_MODAL: &'static str = "wallet_pass_edit_modal";
|
|||
/// Identifier for minimum confirmations [`Modal`].
|
||||
const MIN_CONFIRMATIONS_EDIT_MODAL: &'static str = "wallet_min_conf_edit_modal";
|
||||
|
||||
impl Default for CommonSetup {
|
||||
impl Default for CommonSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
name_edit: "".to_string(),
|
||||
|
@ -59,7 +59,7 @@ impl Default for CommonSetup {
|
|||
}
|
||||
}
|
||||
|
||||
impl CommonSetup {
|
||||
impl CommonSettings {
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui, wallet: &mut Wallet, cb: &dyn PlatformCallbacks) {
|
||||
// Show modal content for this ui container.
|
||||
self.modal_content_ui(ui, wallet, cb);
|
|
@ -12,61 +12,47 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use egui::{Align, Id, Layout, RichText};
|
||||
use url::Url;
|
||||
use egui::{Align, Layout, RichText};
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{CHECK, CHECK_CIRCLE, CHECK_FAT, DOTS_THREE_CIRCLE, GLOBE, GLOBE_SIMPLE, PLUS_CIRCLE, X_CIRCLE};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{ConnectionsContent, Modal, View};
|
||||
use crate::gui::views::types::{ModalContainer, ModalPosition, TextEditOptions};
|
||||
use crate::gui::views::modals::ExternalConnectionModal;
|
||||
use crate::gui::views::types::{ModalContainer, ModalPosition};
|
||||
use crate::wallet::{ConnectionsConfig, ExternalConnection, Wallet};
|
||||
use crate::wallet::types::ConnectionMethod;
|
||||
|
||||
/// Wallet connection setup content.
|
||||
pub struct ConnectionSetup {
|
||||
/// Wallet connection settings content.
|
||||
pub struct ConnectionSettings {
|
||||
/// Selected connection method.
|
||||
pub method: ConnectionMethod,
|
||||
|
||||
/// Flag to check if modal was just opened.
|
||||
first_modal_launch: bool,
|
||||
/// External connection URL value for [`Modal`].
|
||||
ext_node_url_edit: String,
|
||||
/// External connection API secret value for [`Modal`].
|
||||
ext_node_secret_edit: String,
|
||||
/// Flag to show URL format error.
|
||||
ext_node_url_error: bool,
|
||||
|
||||
/// Current wallet external connection.
|
||||
curr_ext_conn: Option<ExternalConnection>,
|
||||
/// Flag to check connections availability.
|
||||
check_connections: bool,
|
||||
|
||||
/// External connection [`Modal`] content.
|
||||
ext_conn_modal: ExternalConnectionModal,
|
||||
|
||||
/// [`Modal`] identifiers allowed at this ui container.
|
||||
modal_ids: Vec<&'static str>
|
||||
}
|
||||
|
||||
/// Identifier for [`Modal`] to add external connection.
|
||||
pub const ADD_EXT_CONNECTION_MODAL: &'static str = "add_ext_connection_modal";
|
||||
|
||||
impl Default for ConnectionSetup {
|
||||
impl Default for ConnectionSettings {
|
||||
fn default() -> Self {
|
||||
ExternalConnection::check_ext_conn_availability(None);
|
||||
Self {
|
||||
method: ConnectionMethod::Integrated,
|
||||
first_modal_launch: true,
|
||||
ext_node_url_edit: "".to_string(),
|
||||
ext_node_secret_edit: "".to_string(),
|
||||
ext_node_url_error: false,
|
||||
curr_ext_conn: None,
|
||||
check_connections: true,
|
||||
ext_conn_modal: ExternalConnectionModal::new(None),
|
||||
modal_ids: vec![
|
||||
ADD_EXT_CONNECTION_MODAL
|
||||
ExternalConnectionModal::WALLET_ID
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ModalContainer for ConnectionSetup {
|
||||
impl ModalContainer for ConnectionSettings {
|
||||
fn modal_ids(&self) -> &Vec<&'static str> {
|
||||
&self.modal_ids
|
||||
}
|
||||
|
@ -76,13 +62,15 @@ impl ModalContainer for ConnectionSetup {
|
|||
modal: &Modal,
|
||||
cb: &dyn PlatformCallbacks) {
|
||||
match modal.id {
|
||||
ADD_EXT_CONNECTION_MODAL => self.add_ext_conn_modal_ui(ui, modal, cb),
|
||||
ExternalConnectionModal::WALLET_ID => {
|
||||
self.ext_conn_modal.ui(ui, cb, modal, |_| {});
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConnectionSetup {
|
||||
impl ConnectionSettings {
|
||||
/// Draw wallet creation setup content.
|
||||
pub fn create_ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) {
|
||||
self.ui(ui, None, cb);
|
||||
|
@ -184,12 +172,6 @@ impl ConnectionSetup {
|
|||
}
|
||||
}
|
||||
|
||||
// Check connections availability.
|
||||
if self.check_connections {
|
||||
ExternalConnection::start_ext_conn_availability_check();
|
||||
self.check_connections = false;
|
||||
}
|
||||
|
||||
if !ext_conn_list.is_empty() {
|
||||
ui.add_space(8.0);
|
||||
for (index, conn) in ext_conn_list.iter().enumerate() {
|
||||
|
@ -269,112 +251,12 @@ impl ConnectionSetup {
|
|||
|
||||
/// Show external connection adding [`Modal`].
|
||||
fn show_add_ext_conn_modal(&mut self, cb: &dyn PlatformCallbacks) {
|
||||
// Setup values for Modal.
|
||||
self.first_modal_launch = true;
|
||||
self.ext_node_url_edit = "".to_string();
|
||||
self.ext_node_secret_edit = "".to_string();
|
||||
self.ext_node_url_error = false;
|
||||
self.ext_conn_modal = ExternalConnectionModal::new(None);
|
||||
// Show modal.
|
||||
Modal::new(ADD_EXT_CONNECTION_MODAL)
|
||||
Modal::new(ExternalConnectionModal::WALLET_ID)
|
||||
.position(ModalPosition::CenterTop)
|
||||
.title(t!("wallets.add_node"))
|
||||
.show();
|
||||
cb.show_keyboard();
|
||||
}
|
||||
|
||||
/// Draw external connection adding [`Modal`] content.
|
||||
pub fn add_ext_conn_modal_ui(&mut self,
|
||||
ui: &mut egui::Ui,
|
||||
modal: &Modal,
|
||||
cb: &dyn PlatformCallbacks) {
|
||||
ui.add_space(6.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(t!("wallets.node_url"))
|
||||
.size(17.0)
|
||||
.color(Colors::gray()));
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Draw node URL text edit.
|
||||
let url_edit_id = Id::from(modal.id).with("node_url_edit");
|
||||
let mut url_edit_opts = TextEditOptions::new(url_edit_id).paste().no_focus();
|
||||
if self.first_modal_launch {
|
||||
self.first_modal_launch = false;
|
||||
url_edit_opts.focus = true;
|
||||
}
|
||||
View::text_edit(ui, cb, &mut self.ext_node_url_edit, &mut url_edit_opts);
|
||||
ui.add_space(8.0);
|
||||
|
||||
ui.label(RichText::new(t!("wallets.node_secret"))
|
||||
.size(17.0)
|
||||
.color(Colors::gray()));
|
||||
ui.add_space(8.0);
|
||||
|
||||
// Draw node API secret text edit.
|
||||
let secret_edit_id = Id::from(modal.id).with("node_secret_edit");
|
||||
let mut secret_edit_opts = TextEditOptions::new(secret_edit_id).paste().no_focus();
|
||||
View::text_edit(ui, cb, &mut self.ext_node_secret_edit, &mut secret_edit_opts);
|
||||
|
||||
// Show error when specified URL is not valid.
|
||||
if self.ext_node_url_error {
|
||||
ui.add_space(10.0);
|
||||
ui.label(RichText::new(t!("wallets.invalid_url"))
|
||||
.size(17.0)
|
||||
.color(Colors::red()));
|
||||
}
|
||||
ui.add_space(10.0);
|
||||
});
|
||||
|
||||
// Show modal buttons.
|
||||
ui.scope(|ui| {
|
||||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
||||
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.cancel"), Colors::white_or_black(false), || {
|
||||
// Close modal.
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
});
|
||||
});
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
// Add connection button callback.
|
||||
let mut on_add = || {
|
||||
if !self.ext_node_url_edit.starts_with("http") {
|
||||
self.ext_node_url_edit = format!("http://{}", self.ext_node_url_edit)
|
||||
}
|
||||
let error = Url::parse(self.ext_node_url_edit.as_str()).is_err();
|
||||
self.ext_node_url_error = error;
|
||||
if !error {
|
||||
// Add external connection.
|
||||
let url = self.ext_node_url_edit.to_owned();
|
||||
let secret = if self.ext_node_secret_edit.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(self.ext_node_secret_edit.to_owned())
|
||||
};
|
||||
let ext_conn = ExternalConnection::new(url.clone(), secret);
|
||||
ConnectionsConfig::add_ext_conn(ext_conn.clone());
|
||||
self.check_connections = true;
|
||||
|
||||
// Set added connection as current.
|
||||
self.method = ConnectionMethod::External(ext_conn.id);
|
||||
|
||||
// Close modal.
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
}
|
||||
};
|
||||
|
||||
// Add connection on Enter button press.
|
||||
View::on_enter_key(ui, || {
|
||||
(on_add)();
|
||||
});
|
||||
|
||||
View::button(ui, t!("modal.add"), Colors::white_or_black(false), on_add);
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -18,29 +18,27 @@ use egui::scroll_area::ScrollBarVisibility;
|
|||
use crate::gui::Colors;
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Content, View};
|
||||
use crate::gui::views::wallets::setup::{CommonSetup, ConnectionSetup, RecoverySetup};
|
||||
use crate::gui::views::wallets::wallet::types::{WalletTab, WalletTabType};
|
||||
use crate::gui::views::wallets::wallet::WalletContent;
|
||||
use crate::wallet::{ExternalConnection, Wallet};
|
||||
use crate::gui::views::wallets::settings::{CommonSettings, ConnectionSettings, RecoverySettings};
|
||||
use crate::gui::views::wallets::types::{WalletTab, WalletTabType};
|
||||
use crate::gui::views::wallets::WalletContent;
|
||||
use crate::wallet::Wallet;
|
||||
|
||||
/// Wallet settings tab content.
|
||||
pub struct WalletSettings {
|
||||
/// Common setup content.
|
||||
common_setup: CommonSetup,
|
||||
common_setup: CommonSettings,
|
||||
/// Connection setup content.
|
||||
conn_setup: ConnectionSetup,
|
||||
conn_setup: ConnectionSettings,
|
||||
/// Recovery setup content.
|
||||
recovery_setup: RecoverySetup
|
||||
recovery_setup: RecoverySettings
|
||||
}
|
||||
|
||||
impl Default for WalletSettings {
|
||||
fn default() -> Self {
|
||||
// Check external connections availability on opening.
|
||||
ExternalConnection::start_ext_conn_availability_check();
|
||||
Self {
|
||||
common_setup: CommonSetup::default(),
|
||||
conn_setup: ConnectionSetup::default(),
|
||||
recovery_setup: RecoverySetup::default()
|
||||
common_setup: CommonSettings::default(),
|
||||
conn_setup: ConnectionSettings::default(),
|
||||
recovery_setup: RecoverySettings::default()
|
||||
}
|
||||
}
|
||||
}
|
25
src/gui/views/wallets/wallet/settings/mod.rs
Normal file
25
src/gui/views/wallets/wallet/settings/mod.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2024 The Grim Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
mod content;
|
||||
pub use content::*;
|
||||
|
||||
mod connection;
|
||||
pub use connection::ConnectionSettings;
|
||||
|
||||
mod common;
|
||||
pub use common::CommonSettings;
|
||||
|
||||
mod recovery;
|
||||
pub use recovery::RecoverySettings;
|
|
@ -24,8 +24,8 @@ use crate::gui::views::types::{ModalPosition, TextEditOptions};
|
|||
use crate::node::Node;
|
||||
use crate::wallet::Wallet;
|
||||
|
||||
/// Wallet recovery setup content.
|
||||
pub struct RecoverySetup {
|
||||
/// Wallet recovery settings content.
|
||||
pub struct RecoverySettings {
|
||||
/// Wallet password [`Modal`] value.
|
||||
pass_edit: String,
|
||||
/// Flag to check if wrong password was entered.
|
||||
|
@ -40,7 +40,7 @@ const RECOVERY_PHRASE_MODAL: &'static str = "recovery_phrase_modal";
|
|||
/// Identifier to confirm wallet deletion [`Modal`].
|
||||
const DELETE_CONFIRMATION_MODAL: &'static str = "delete_wallet_confirmation_modal";
|
||||
|
||||
impl Default for RecoverySetup {
|
||||
impl Default for RecoverySettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
wrong_pass: false,
|
||||
|
@ -50,7 +50,7 @@ impl Default for RecoverySetup {
|
|||
}
|
||||
}
|
||||
|
||||
impl RecoverySetup {
|
||||
impl RecoverySettings {
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui, wallet: &mut Wallet, cb: &dyn PlatformCallbacks) {
|
||||
// Show modal content for this ui container.
|
||||
self.modal_content_ui(ui, wallet, cb);
|
|
@ -102,11 +102,11 @@ impl ConnectionsConfig {
|
|||
}
|
||||
|
||||
/// Set [`ExternalConnection`] availability flag.
|
||||
pub fn update_ext_conn_availability(id: i64, available: bool) {
|
||||
pub fn update_ext_conn_status(id: i64, available: Option<bool>) {
|
||||
let mut w_config = Settings::conn_config_to_update();
|
||||
for c in w_config.external.iter_mut() {
|
||||
if c.id == id {
|
||||
c.available = Some(available);
|
||||
c.available = available;
|
||||
w_config.save();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -49,8 +49,8 @@ impl ExternalConnection {
|
|||
|
||||
/// Check connection availability.
|
||||
fn check_conn_availability(&self) {
|
||||
// Check every connection at separate thread.
|
||||
let conn = self.clone();
|
||||
ConnectionsConfig::update_ext_conn_status(conn.id, None);
|
||||
std::thread::spawn(move || {
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
|
@ -84,29 +84,33 @@ impl ExternalConnection {
|
|||
let status = res.status().as_u16();
|
||||
// Available on 200 HTTP status code.
|
||||
if status == 200 {
|
||||
ConnectionsConfig::update_ext_conn_availability(conn.id, true);
|
||||
ConnectionsConfig::update_ext_conn_status(conn.id, Some(true));
|
||||
} else {
|
||||
ConnectionsConfig::update_ext_conn_availability(conn.id, false);
|
||||
ConnectionsConfig::update_ext_conn_status(conn.id, Some(false));
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
ConnectionsConfig::update_ext_conn_availability(conn.id, false);
|
||||
ConnectionsConfig::update_ext_conn_status(conn.id, Some(false));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ConnectionsConfig::update_ext_conn_availability(conn.id, false);
|
||||
ConnectionsConfig::update_ext_conn_status(conn.id, Some(false));
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/// Check external connections availability at another thread.
|
||||
pub fn start_ext_conn_availability_check() {
|
||||
/// Check external connections availability.
|
||||
pub fn check_ext_conn_availability(id: Option<i64>) {
|
||||
let conn_list = ConnectionsConfig::ext_conn_list();
|
||||
for conn in conn_list {
|
||||
// Check every connection at separate thread.
|
||||
conn.check_conn_availability();
|
||||
if let Some(id) = id {
|
||||
if id == conn.id {
|
||||
conn.check_conn_availability();
|
||||
}
|
||||
} else {
|
||||
conn.check_conn_availability();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue