wallet + ui: external connection API token support, update translations
This commit is contained in:
parent
08c202519e
commit
cf834f86fc
6 changed files with 158 additions and 40 deletions
|
@ -21,7 +21,9 @@ wallets:
|
|||
setup_conn_desc: Choose how your wallet connects to the network.
|
||||
conn_method: Connection method
|
||||
ext_conn: 'External connections:'
|
||||
add_node_url: Add node URL
|
||||
add_node: Add node
|
||||
node_url: 'Node URL:'
|
||||
node_secret: 'API Secret (optional):'
|
||||
invalid_url: Entered URL is invalid
|
||||
open: Open the wallet
|
||||
wrong_pass: Entered password is wrong
|
||||
|
|
|
@ -21,7 +21,9 @@ wallets:
|
|||
setup_conn_desc: Выберите способ подключения вашего кошелька к сети.
|
||||
conn_method: Способ подключения
|
||||
ext_conn: 'Внешние подключения:'
|
||||
add_node_url: Добавить URL узла
|
||||
add_node: Добавить узел
|
||||
node_url: 'URL узла:'
|
||||
node_secret: 'API токен (необязательно):'
|
||||
invalid_url: Введенный URL-адрес недействителен
|
||||
open: Открыть кошелёк
|
||||
wrong_pass: Введён неправильный пароль
|
||||
|
|
|
@ -19,16 +19,21 @@ use crate::AppConfig;
|
|||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{GLOBE, GLOBE_SIMPLE};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::{Modal, View};
|
||||
use crate::gui::views::{Modal, ModalPosition, View};
|
||||
use crate::gui::views::wallets::setup::ConnectionMethod;
|
||||
use crate::wallet::ExternalConnection;
|
||||
|
||||
/// Wallet node connection method setup content.
|
||||
pub struct ConnectionSetup {
|
||||
/// Selected connection method.
|
||||
method: ConnectionMethod,
|
||||
|
||||
/// Flag to check if modal was just opened.
|
||||
first_modal_launch: bool,
|
||||
/// External node connection URL value for [`Modal`].
|
||||
ext_node_url_edit: String,
|
||||
/// External node connection API secret value for [`Modal`].
|
||||
ext_node_secret_edit: String,
|
||||
/// Flag to show URL format error.
|
||||
ext_node_url_error: bool,
|
||||
}
|
||||
|
@ -37,7 +42,9 @@ impl Default for ConnectionSetup {
|
|||
fn default() -> Self {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -82,25 +89,28 @@ impl ConnectionSetup {
|
|||
ui.add_space(6.0);
|
||||
|
||||
// Show button to add new external node connection.
|
||||
let add_node_text = format!("{} {}", GLOBE_SIMPLE, t!("wallets.add_node_url"));
|
||||
let add_node_text = format!("{} {}", GLOBE_SIMPLE, t!("wallets.add_node"));
|
||||
View::button(ui, add_node_text, Colors::GOLD, || {
|
||||
// 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;
|
||||
// Show modal.
|
||||
Modal::new(Self::ADD_CONNECTION_URL_MODAL)
|
||||
.title(t!("wallets.ext_conn"))
|
||||
.position(ModalPosition::CenterTop)
|
||||
.title(t!("wallets.add_node"))
|
||||
.show();
|
||||
cb.show_keyboard();
|
||||
});
|
||||
ui.add_space(12.0);
|
||||
|
||||
// Show external nodes URLs selection.
|
||||
for conn in AppConfig::external_nodes_urls() {
|
||||
for conn in AppConfig::external_connections() {
|
||||
View::radio_value(ui,
|
||||
&mut self.method,
|
||||
ConnectionMethod::External(conn.clone()),
|
||||
conn);
|
||||
ConnectionMethod::External(conn.url.clone()),
|
||||
conn.url);
|
||||
ui.add_space(12.0);
|
||||
}
|
||||
});
|
||||
|
@ -111,15 +121,41 @@ impl ConnectionSetup {
|
|||
pub fn modal_ui(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||
ui.add_space(6.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
// Draw external node URL text edit.
|
||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.ext_node_url_edit)
|
||||
.id(Id::from(modal.id))
|
||||
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_resp = egui::TextEdit::singleline(&mut self.ext_node_url_edit)
|
||||
.id(Id::from(modal.id).with("node_url_edit"))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(ui.available_width())
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
text_edit_resp.request_focus();
|
||||
if text_edit_resp.clicked() {
|
||||
ui.add_space(8.0);
|
||||
if self.first_modal_launch {
|
||||
self.first_modal_launch = false;
|
||||
url_edit_resp.request_focus();
|
||||
}
|
||||
if url_edit_resp.clicked() {
|
||||
cb.show_keyboard();
|
||||
}
|
||||
|
||||
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_resp = egui::TextEdit::singleline(&mut self.ext_node_secret_edit)
|
||||
.id(Id::from(modal.id).with("node_secret_edit"))
|
||||
.font(TextStyle::Heading)
|
||||
.desired_width(ui.available_width())
|
||||
.cursor_at_end(true)
|
||||
.ui(ui);
|
||||
ui.add_space(8.0);
|
||||
if secret_edit_resp.clicked() {
|
||||
cb.show_keyboard();
|
||||
}
|
||||
|
||||
|
@ -138,18 +174,6 @@ impl ConnectionSetup {
|
|||
// Setup spacing between buttons.
|
||||
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
||||
|
||||
// Add button callback.
|
||||
let on_add = || {
|
||||
let error = Url::parse(self.ext_node_url_edit.as_str()).is_err();
|
||||
self.ext_node_url_error = error;
|
||||
if !error {
|
||||
AppConfig::add_external_node_url(self.ext_node_url_edit.clone());
|
||||
// Close modal.
|
||||
cb.hide_keyboard();
|
||||
modal.close();
|
||||
}
|
||||
};
|
||||
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||
|
@ -159,6 +183,35 @@ impl ConnectionSetup {
|
|||
});
|
||||
});
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
// Add connection button callback.
|
||||
let mut on_add = || {
|
||||
let error = Url::parse(self.ext_node_url_edit.as_str()).is_err();
|
||||
self.ext_node_url_error = error;
|
||||
if !error {
|
||||
// Save 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);
|
||||
AppConfig::add_external_connection(ext_conn);
|
||||
|
||||
// Set added method as current.
|
||||
self.method = ConnectionMethod::External(url);
|
||||
|
||||
// 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, on_add);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -24,7 +24,7 @@ use serde::{Deserialize, Serialize};
|
|||
use serde::de::DeserializeOwned;
|
||||
|
||||
use crate::node::NodeConfig;
|
||||
use crate::wallet::Wallets;
|
||||
use crate::wallet::{ExternalConnection, Wallets};
|
||||
|
||||
lazy_static! {
|
||||
/// Static settings state to be accessible globally.
|
||||
|
@ -34,9 +34,6 @@ lazy_static! {
|
|||
/// Application configuration file name.
|
||||
const APP_CONFIG_FILE_NAME: &'static str = "app.toml";
|
||||
|
||||
/// Default external node URL.
|
||||
const DEFAULT_EXTERNAL_NODE_URL: &'static str = "https://grinnnode.live:3413";
|
||||
|
||||
/// Common application settings.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct AppConfig {
|
||||
|
@ -44,8 +41,8 @@ pub struct AppConfig {
|
|||
pub auto_start_node: bool,
|
||||
/// Chain type for node and wallets.
|
||||
chain_type: ChainTypes,
|
||||
/// URLs of external nodes for wallets.
|
||||
external_nodes_urls: Vec<String>
|
||||
/// URLs of external connections for wallets.
|
||||
external_connections: Vec<ExternalConnection>
|
||||
}
|
||||
|
||||
impl Default for AppConfig {
|
||||
|
@ -53,8 +50,8 @@ impl Default for AppConfig {
|
|||
Self {
|
||||
auto_start_node: false,
|
||||
chain_type: ChainTypes::default(),
|
||||
external_nodes_urls: vec![
|
||||
DEFAULT_EXTERNAL_NODE_URL.to_string()
|
||||
external_connections: vec![
|
||||
ExternalConnection::default()
|
||||
],
|
||||
}
|
||||
}
|
||||
|
@ -121,19 +118,41 @@ impl AppConfig {
|
|||
w_app_config.save();
|
||||
}
|
||||
|
||||
/// Get external nodes URLs.
|
||||
pub fn external_nodes_urls() -> Vec<String> {
|
||||
/// Get external connections for the wallet.
|
||||
pub fn external_connections() -> Vec<ExternalConnection> {
|
||||
let r_config = Settings::app_config_to_read();
|
||||
r_config.external_nodes_urls.clone()
|
||||
r_config.external_connections.clone()
|
||||
}
|
||||
|
||||
/// Add external node URL.
|
||||
pub fn add_external_node_url(address: String) {
|
||||
/// Save external connection for the wallet in app config.
|
||||
pub fn add_external_connection(conn: ExternalConnection) {
|
||||
let mut w_config = Settings::app_config_to_update();
|
||||
w_config.external_nodes_urls.insert(0, address);
|
||||
let mut exists = false;
|
||||
for mut c in w_config.external_connections.iter_mut() {
|
||||
// Update connection if URL exists.
|
||||
if c.url == conn.url {
|
||||
c.secret = conn.secret.clone();
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Create new connection if URL not exists.
|
||||
if !exists {
|
||||
w_config.external_connections.insert(0, conn);
|
||||
}
|
||||
w_config.save();
|
||||
}
|
||||
|
||||
/// Get external node connection secret from provided URL.
|
||||
pub fn get_external_connection_secret(url: String) -> Option<String> {
|
||||
let r_config = Settings::app_config_to_read();
|
||||
for c in &r_config.external_connections {
|
||||
if c.url == url {
|
||||
return c.secret.clone();
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Main application directory name.
|
||||
|
|
|
@ -21,4 +21,7 @@ mod wallets;
|
|||
pub use wallets::{Wallet, Wallets};
|
||||
|
||||
mod config;
|
||||
pub use config::*;
|
||||
pub use config::*;
|
||||
|
||||
mod types;
|
||||
pub use types::*;
|
39
src/wallet/types.rs
Normal file
39
src/wallet/types.rs
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Copyright 2023 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 serde_derive::{Deserialize, Serialize};
|
||||
|
||||
/// External node connection for the wallet.
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct ExternalConnection {
|
||||
/// Node URL.
|
||||
pub url: String,
|
||||
/// Optional API secret key.
|
||||
pub secret: Option<String>
|
||||
}
|
||||
|
||||
impl ExternalConnection {
|
||||
/// Default external node URL.
|
||||
const DEFAULT_EXTERNAL_NODE_URL: &'static str = "https://grinnnode.live:3413";
|
||||
|
||||
pub fn new(url: String, secret: Option<String>) -> Self {
|
||||
Self { url, secret }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ExternalConnection {
|
||||
fn default() -> Self {
|
||||
Self { url: Self::DEFAULT_EXTERNAL_NODE_URL.to_string(), secret: None }
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue