From f142ae110a5982c39ce564b3eb91ecddeb56caa0 Mon Sep 17 00:00:00 2001 From: ardocrat Date: Wed, 10 Jul 2024 18:54:23 +0300 Subject: [PATCH] ui: wallet connection selector/creator modal, separate modal content for connection creation, move settings into wallet --- src/gui/views/modal.rs | 6 +- src/gui/views/network/connections.rs | 198 ++++-------------- src/gui/views/network/content.rs | 2 +- src/gui/views/network/mod.rs | 3 +- src/gui/views/network/modals/ext_conn.rs | 166 +++++++++++++++ src/gui/views/network/modals/mod.rs | 16 ++ src/gui/views/title_panel.rs | 6 +- src/gui/views/wallets/content.rs | 48 ++++- src/gui/views/wallets/creation/creation.rs | 8 +- src/gui/views/wallets/mod.rs | 2 +- src/gui/views/wallets/modals/connection.rs | 154 ++++++++++++++ .../views/wallets/{setup => modals}/mod.rs | 10 +- src/gui/views/wallets/wallet/content.rs | 3 +- src/gui/views/wallets/wallet/mod.rs | 4 +- .../{setup => wallet/settings}/common.rs | 8 +- .../{setup => wallet/settings}/connection.rs | 156 ++------------ .../{settings.rs => settings/content.rs} | 22 +- src/gui/views/wallets/wallet/settings/mod.rs | 25 +++ .../{setup => wallet/settings}/recovery.rs | 8 +- src/wallet/connections/config.rs | 4 +- src/wallet/connections/external.rs | 24 ++- 21 files changed, 514 insertions(+), 359 deletions(-) create mode 100644 src/gui/views/network/modals/ext_conn.rs create mode 100644 src/gui/views/network/modals/mod.rs create mode 100644 src/gui/views/wallets/modals/connection.rs rename src/gui/views/wallets/{setup => modals}/mod.rs (77%) rename src/gui/views/wallets/{setup => wallet/settings}/common.rs (99%) rename src/gui/views/wallets/{setup => wallet/settings}/connection.rs (61%) rename src/gui/views/wallets/wallet/{settings.rs => settings/content.rs} (82%) create mode 100644 src/gui/views/wallets/wallet/settings/mod.rs rename src/gui/views/wallets/{setup => wallet/settings}/recovery.rs (98%) diff --git a/src/gui/views/modal.rs b/src/gui/views/modal.rs index 5917a3c..c60dbe2 100644 --- a/src/gui/views/modal.rs +++ b/src/gui/views/modal.rs @@ -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)) diff --git a/src/gui/views/network/connections.rs b/src/gui/views/network/connections.rs index c14be5b..b7cabad 100644 --- a/src/gui/views/network/connections.rs +++ b/src/gui/views/network/connections.rs @@ -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, - - /// 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, 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); - }); - } } \ No newline at end of file diff --git a/src/gui/views/network/content.rs b/src/gui/views/network/content.rs index 240474f..23ad918 100644 --- a/src/gui/views/network/content.rs +++ b/src/gui/views/network/content.rs @@ -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); } }); } diff --git a/src/gui/views/network/mod.rs b/src/gui/views/network/mod.rs index 59ca12f..c68cf08 100644 --- a/src/gui/views/network/mod.rs +++ b/src/gui/views/network/mod.rs @@ -33,4 +33,5 @@ pub use content::*; mod connections; pub use connections::*; -pub mod types; \ No newline at end of file +pub mod types; +pub mod modals; \ No newline at end of file diff --git a/src/gui/views/network/modals/ext_conn.rs b/src/gui/views/network/modals/ext_conn.rs new file mode 100644 index 0000000..62ba6e7 --- /dev/null +++ b/src/gui/views/network/modals/ext_conn.rs @@ -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, +} + + + +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) -> 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); + }); + } +} \ No newline at end of file diff --git a/src/gui/views/network/modals/mod.rs b/src/gui/views/network/modals/mod.rs new file mode 100644 index 0000000..5ec63fe --- /dev/null +++ b/src/gui/views/network/modals/mod.rs @@ -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::*; \ No newline at end of file diff --git a/src/gui/views/title_panel.rs b/src/gui/views/title_panel.rs index 8d8e930..3a83ef4 100644 --- a/src/gui/views/title_panel.rs +++ b/src/gui/views/title_panel.rs @@ -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) => { diff --git a/src/gui/views/wallets/content.rs b/src/gui/views/wallets/content.rs index 174c49d..e64c5c6 100644 --- a/src/gui/views/wallets/content.rs +++ b/src/gui/views/wallets/content.rs @@ -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, + /// 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; diff --git a/src/gui/views/wallets/creation/creation.rs b/src/gui/views/wallets/creation/creation.rs index 5e712ac..b638b90 100644 --- a/src/gui/views/wallets/creation/creation.rs +++ b/src/gui/views/wallets/creation/creation.rs @@ -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); } }); } diff --git a/src/gui/views/wallets/mod.rs b/src/gui/views/wallets/mod.rs index 8af920c..bef81f5 100644 --- a/src/gui/views/wallets/mod.rs +++ b/src/gui/views/wallets/mod.rs @@ -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::*; diff --git a/src/gui/views/wallets/modals/connection.rs b/src/gui/views/wallets/modals/connection.rs new file mode 100644 index 0000000..bc26042 --- /dev/null +++ b/src/gui/views/wallets/modals/connection.rs @@ -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, + + /// 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) -> 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)) { + 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); + } +} \ No newline at end of file diff --git a/src/gui/views/wallets/setup/mod.rs b/src/gui/views/wallets/modals/mod.rs similarity index 77% rename from src/gui/views/wallets/setup/mod.rs rename to src/gui/views/wallets/modals/mod.rs index 6391118..511957c 100644 --- a/src/gui/views/wallets/setup/mod.rs +++ b/src/gui/views/wallets/modals/mod.rs @@ -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; \ No newline at end of file +pub use connection::*; \ No newline at end of file diff --git a/src/gui/views/wallets/wallet/content.rs b/src/gui/views/wallets/wallet/content.rs index 69244a8..1de3632 100644 --- a/src/gui/views/wallets/wallet/content.rs +++ b/src/gui/views/wallets/wallet/content.rs @@ -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}; diff --git a/src/gui/views/wallets/wallet/mod.rs b/src/gui/views/wallets/wallet/mod.rs index 0c93bc9..0c82d31 100644 --- a/src/gui/views/wallets/wallet/mod.rs +++ b/src/gui/views/wallets/wallet/mod.rs @@ -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; \ No newline at end of file diff --git a/src/gui/views/wallets/setup/common.rs b/src/gui/views/wallets/wallet/settings/common.rs similarity index 99% rename from src/gui/views/wallets/setup/common.rs rename to src/gui/views/wallets/wallet/settings/common.rs index 4f63e6d..e312e70 100644 --- a/src/gui/views/wallets/setup/common.rs +++ b/src/gui/views/wallets/wallet/settings/common.rs @@ -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); diff --git a/src/gui/views/wallets/setup/connection.rs b/src/gui/views/wallets/wallet/settings/connection.rs similarity index 61% rename from src/gui/views/wallets/setup/connection.rs rename to src/gui/views/wallets/wallet/settings/connection.rs index c6b4f69..88b8178 100644 --- a/src/gui/views/wallets/setup/connection.rs +++ b/src/gui/views/wallets/wallet/settings/connection.rs @@ -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, - /// 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); - }); - } } \ No newline at end of file diff --git a/src/gui/views/wallets/wallet/settings.rs b/src/gui/views/wallets/wallet/settings/content.rs similarity index 82% rename from src/gui/views/wallets/wallet/settings.rs rename to src/gui/views/wallets/wallet/settings/content.rs index bec083b..085ff9b 100644 --- a/src/gui/views/wallets/wallet/settings.rs +++ b/src/gui/views/wallets/wallet/settings/content.rs @@ -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() } } } diff --git a/src/gui/views/wallets/wallet/settings/mod.rs b/src/gui/views/wallets/wallet/settings/mod.rs new file mode 100644 index 0000000..a976b6d --- /dev/null +++ b/src/gui/views/wallets/wallet/settings/mod.rs @@ -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; \ No newline at end of file diff --git a/src/gui/views/wallets/setup/recovery.rs b/src/gui/views/wallets/wallet/settings/recovery.rs similarity index 98% rename from src/gui/views/wallets/setup/recovery.rs rename to src/gui/views/wallets/wallet/settings/recovery.rs index 40e29c2..969e2cd 100644 --- a/src/gui/views/wallets/setup/recovery.rs +++ b/src/gui/views/wallets/wallet/settings/recovery.rs @@ -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); diff --git a/src/wallet/connections/config.rs b/src/wallet/connections/config.rs index 9562aec..8b54e8a 100644 --- a/src/wallet/connections/config.rs +++ b/src/wallet/connections/config.rs @@ -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) { 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; } diff --git a/src/wallet/connections/external.rs b/src/wallet/connections/external.rs index da33747..917d1dc 100644 --- a/src/wallet/connections/external.rs +++ b/src/wallet/connections/external.rs @@ -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) { 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(); + } } } } \ No newline at end of file