ui: text edit refactoring

This commit is contained in:
ardocrat 2023-11-08 01:00:56 +03:00
parent 6788b0fe02
commit ced144476b
16 changed files with 314 additions and 615 deletions

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::{Align, Id, Layout, RichText, Rounding, TextStyle, Widget};
use egui::{Align, Id, Layout, RichText, Rounding};
use url::Url;
use crate::AppConfig;
@ -20,7 +20,7 @@ use crate::gui::Colors;
use crate::gui::icons::{CARET_RIGHT, CHECK_CIRCLE, COMPUTER_TOWER, DOTS_THREE_CIRCLE, PENCIL, POWER, TRASH, X_CIRCLE};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, NodeSetup, View};
use crate::gui::views::types::{ModalContainer, ModalPosition};
use crate::gui::views::types::{ModalContainer, ModalPosition, TextEditOptions};
use crate::node::{Node, NodeConfig};
use crate::wallet::{ConnectionsConfig, ExternalConnection};
@ -133,12 +133,12 @@ impl ConnectionsContent {
if !Node::is_running() {
// Draw button to start integrated node.
View::item_button(ui, Rounding::none(), POWER, Some(Colors::GREEN), || {
View::item_button(ui, Rounding::default(), POWER, Some(Colors::GREEN), || {
Node::start();
});
} else if !Node::is_starting() && !Node::is_stopping() && !Node::is_restarting() {
// Draw button to open closed wallet.
View::item_button(ui, Rounding::none(), POWER, Some(Colors::RED), || {
View::item_button(ui, Rounding::default(), POWER, Some(Colors::RED), || {
Node::stop(false);
});
}
@ -197,7 +197,7 @@ impl ConnectionsContent {
View::item_button(ui, button_rounding, TRASH, None, || {
ConnectionsConfig::remove_ext_conn(conn.id);
});
View::item_button(ui, Rounding::none(), PENCIL, None, || {
View::item_button(ui, Rounding::default(), PENCIL, None, || {
self.show_add_ext_conn_modal(Some(conn), cb);
});
}
@ -267,20 +267,13 @@ impl ConnectionsContent {
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(self.ext_conn_id_edit))
.font(TextStyle::Heading)
.desired_width(ui.available_width())
.cursor_at_end(true)
.ui(ui);
ui.add_space(8.0);
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_resp.request_focus();
}
if url_edit_resp.clicked() {
cb.show_keyboard();
url_edit_opts.focus = true;
}
View::text_edit(ui, cb, &mut self.ext_node_url_edit, url_edit_opts);
ui.label(RichText::new(t!("wallets.node_secret"))
.size(17.0)
@ -288,20 +281,13 @@ impl ConnectionsContent {
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();
}
let secret_edit_id = Id::from(modal.id).with(self.ext_conn_id_edit).with("node_secret");
let secret_edit_opts = TextEditOptions::new(secret_edit_id).paste().no_focus();
View::text_edit(ui, cb, &mut self.ext_node_secret_edit, secret_edit_opts);
// Show error when specified URL is not valid.
if self.ext_node_url_error {
ui.add_space(2.0);
ui.add_space(12.0);
ui.label(RichText::new(t!("wallets.invalid_url"))
.size(17.0)
.color(Colors::RED));

View file

@ -12,14 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::{Id, RichText, TextStyle, Widget};
use egui::{Id, RichText};
use crate::gui::Colors;
use crate::gui::icons::{CLOCK_COUNTDOWN, GRAPH, TIMER, WATCH};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, View};
use crate::gui::views::network::settings::NetworkSettings;
use crate::gui::views::types::{ModalContainer, ModalPosition};
use crate::gui::views::types::{ModalContainer, ModalPosition, TextEditOptions};
use crate::node::NodeConfig;
/// Dandelion server setup section content.
@ -165,16 +165,8 @@ impl DandelionSetup {
ui.add_space(8.0);
// Draw epoch text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.epoch_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(52.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let epoch_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.epoch_edit, epoch_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.epoch_edit.parse::<u16>().is_err() {
@ -250,16 +242,8 @@ impl DandelionSetup {
ui.add_space(8.0);
// Draw embargo text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.embargo_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(52.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let embargo_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.embargo_edit, embargo_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.embargo_edit.parse::<u16>().is_err() {
@ -335,16 +319,8 @@ impl DandelionSetup {
ui.add_space(8.0);
// Draw aggregation period text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.aggregation_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(42.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let aggregation_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.aggregation_edit, aggregation_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.aggregation_edit.parse::<u16>().is_err() {
@ -420,16 +396,8 @@ impl DandelionSetup {
ui.add_space(8.0);
// Draw stem phase probability text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.stem_prob_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(42.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let stem_prob_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.stem_prob_edit, stem_prob_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.stem_prob_edit.parse::<u8>().is_err() {

View file

@ -12,17 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::{Id, RichText, TextStyle, Widget};
use egui_extras::{Size, StripBuilder};
use egui::{Id, RichText};
use grin_core::global::ChainTypes;
use crate::AppConfig;
use crate::gui::Colors;
use crate::gui::icons::{CLIPBOARD_TEXT, CLOCK_CLOCKWISE, COMPUTER_TOWER, COPY, PLUG, POWER, SHIELD, SHIELD_SLASH};
use crate::gui::icons::{CLOCK_CLOCKWISE, COMPUTER_TOWER, PLUG, POWER, SHIELD, SHIELD_SLASH};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, NetworkContent, View};
use crate::gui::views::network::settings::NetworkSettings;
use crate::gui::views::types::{ModalContainer, ModalPosition};
use crate::gui::views::types::{ModalContainer, ModalPosition, TextEditOptions};
use crate::node::{Node, NodeConfig};
/// Integrated node general setup section content.
@ -286,15 +285,8 @@ impl NodeSetup {
ui.add_space(6.0);
// Draw API port text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.api_port_edit)
.font(TextStyle::Heading)
.desired_width(64.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let api_port_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.api_port_edit, api_port_edit_opts);
// Show error when specified port is unavailable or reminder to restart enabled node.
if !self.api_port_available_edit {
@ -390,49 +382,11 @@ impl NodeSetup {
};
ui.label(RichText::new(description).size(17.0).color(Colors::GRAY));
ui.add_space(8.0);
StripBuilder::new(ui)
.size(Size::exact(42.0))
.vertical(|mut strip| {
strip.strip(|builder| {
builder
.size(Size::remainder())
.size(Size::exact(48.0))
.size(Size::exact(48.0))
.horizontal(|mut strip| {
strip.cell(|ui| {
ui.add_space(2.0);
// Draw API secret token value text edit.
let edit = egui::TextEdit::singleline(&mut self.secret_edit)
.id(Id::from(modal.id))
.font(TextStyle::Button)
.cursor_at_end(true)
.ui(ui);
edit.request_focus();
if edit.clicked() {
cb.show_keyboard();
}
});
strip.cell(|ui| {
ui.vertical_centered(|ui| {
// Draw copy button.
let copy_icon = COPY.to_string();
View::button(ui, copy_icon, Colors::WHITE, || {
cb.copy_string_to_buffer(self.secret_edit.clone());
});
});
});
strip.cell(|ui| {
ui.vertical_centered(|ui| {
// Draw paste button.
let paste_icon = CLIPBOARD_TEXT.to_string();
View::button(ui, paste_icon, Colors::WHITE, || {
self.secret_edit = cb.get_string_from_buffer();
});
});
});
});
})
});
let secret_edit_opts = TextEditOptions::new(Id::from(modal.id)).copy().paste();
View::text_edit(ui, cb, &mut self.secret_edit, secret_edit_opts);
ui.add_space(6.0);
// Show reminder to restart enabled node.
if Node::is_running() {
@ -440,7 +394,7 @@ impl NodeSetup {
.size(16.0)
.color(Colors::GREEN)
);
ui.add_space(8.0);
ui.add_space(6.0);
}
ui.add_space(4.0);
});
@ -516,16 +470,8 @@ impl NodeSetup {
ui.add_space(8.0);
// Draw ftl value text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.ftl_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(52.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let ftl_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.ftl_edit, ftl_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.ftl_edit.parse::<u64>().is_err() {

View file

@ -12,17 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::{Align, Id, Layout, RichText, TextStyle, Widget};
use egui_extras::{Size, StripBuilder};
use egui::{Align, Id, Layout, RichText};
use grin_core::global::ChainTypes;
use crate::AppConfig;
use crate::gui::Colors;
use crate::gui::icons::{ARROW_FAT_LINE_UP, ARROW_FAT_LINES_DOWN, ARROW_FAT_LINES_UP, CLIPBOARD_TEXT, GLOBE_SIMPLE, HANDSHAKE, PLUG, PLUS_CIRCLE, PROHIBIT_INSET, TRASH};
use crate::gui::icons::{ARROW_FAT_LINE_UP, ARROW_FAT_LINES_DOWN, ARROW_FAT_LINES_UP, GLOBE_SIMPLE, HANDSHAKE, PLUG, PLUS_CIRCLE, PROHIBIT_INSET, TRASH};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, View};
use crate::gui::views::network::settings::NetworkSettings;
use crate::gui::views::types::{ModalContainer, ModalPosition};
use crate::gui::views::types::{ModalContainer, ModalPosition, TextEditOptions};
use crate::node::{NodeConfig, PeersConfig};
/// Type of peer.
@ -283,16 +282,8 @@ impl P2PSetup {
ui.add_space(8.0);
// Draw p2p port text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.port_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(64.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let text_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.port_edit, text_edit_opts);
// Show error when specified port is unavailable.
if !self.port_available_edit {
@ -389,6 +380,7 @@ impl P2PSetup {
};
View::button(ui, add_text, Colors::BUTTON, || {
// Setup values for modal.
self.is_correct_address_edit = true;
self.peer_edit = "".to_string();
// Select modal id.
let modal_id = match peer_type {
@ -425,50 +417,19 @@ impl P2PSetup {
};
ui.label(RichText::new(label_text).size(17.0).color(Colors::GRAY));
ui.add_space(8.0);
StripBuilder::new(ui)
.size(Size::exact(42.0))
.vertical(|mut strip| {
strip.strip(|builder| {
builder
.size(Size::remainder())
.size(Size::exact(48.0))
.horizontal(|mut strip| {
strip.cell(|ui| {
ui.add_space(2.0);
// Draw peer address text edit.
let text_edit = egui::TextEdit::singleline(&mut self.peer_edit)
.id(Id::from(modal.id))
.font(TextStyle::Button)
.desired_width(ui.available_width())
.cursor_at_end(true)
.ui(ui);
text_edit.request_focus();
if text_edit.clicked() {
cb.show_keyboard();
}
});
strip.cell(|ui| {
ui.vertical_centered(|ui| {
// Draw paste button.
let paste_icon = CLIPBOARD_TEXT.to_string();
View::button(ui, paste_icon, Colors::WHITE, || {
self.peer_edit = cb.get_string_from_buffer();
});
});
});
});
})
});
let peer_text_edit_opts = TextEditOptions::new(Id::from(modal.id)).paste();
View::text_edit(ui, cb, &mut self.peer_edit, peer_text_edit_opts);
// Show error when specified address is incorrect.
if !self.is_correct_address_edit {
ui.add_space(10.0);
ui.label(RichText::new(t!("network_settings.peer_address_error"))
.size(16.0)
.color(Colors::RED));
ui.add_space(6.0);
}
ui.add_space(4.0);
ui.add_space(12.0);
// Show modal buttons.
ui.scope(|ui| {
@ -572,16 +533,8 @@ impl P2PSetup {
ui.add_space(8.0);
// Draw ban window text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.ban_window_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(84.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let text_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.ban_window_edit, text_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.ban_window_edit.parse::<i64>().is_err() {
@ -658,16 +611,8 @@ impl P2PSetup {
ui.add_space(8.0);
// Draw maximum number of inbound peers text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.max_inbound_count)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(42.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let text_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.max_inbound_count, text_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.max_inbound_count.parse::<u32>().is_err() {
@ -744,16 +689,8 @@ impl P2PSetup {
ui.add_space(8.0);
// Draw maximum number of outbound peers text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.max_outbound_count)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(42.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let text_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.max_outbound_count, text_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.max_outbound_count.parse::<u32>().is_err() {
@ -834,16 +771,8 @@ impl P2PSetup {
ui.add_space(8.0);
// Draw maximum number of outbound peers text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.min_outbound_count)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(42.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let text_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.min_outbound_count, text_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.min_outbound_count.parse::<u32>().is_err() {

View file

@ -12,14 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::{Id, RichText, TextStyle, Widget};
use egui::{Id, RichText};
use crate::gui::Colors;
use crate::gui::icons::{BEZIER_CURVE, BOUNDING_BOX, CHART_SCATTER, CIRCLES_THREE, CLOCK_COUNTDOWN, HAND_COINS};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, View};
use crate::gui::views::network::settings::NetworkSettings;
use crate::gui::views::types::{ModalContainer, ModalPosition};
use crate::gui::views::types::{ModalContainer, ModalPosition, TextEditOptions};
use crate::node::NodeConfig;
/// Memory pool setup section content.
@ -169,16 +169,8 @@ impl PoolSetup {
ui.add_space(8.0);
// Draw fee base text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.fee_base_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(84.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let fee_base_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.fee_base_edit, fee_base_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.fee_base_edit.parse::<u64>().is_err() {
@ -254,16 +246,8 @@ impl PoolSetup {
ui.add_space(8.0);
// Draw reorg period text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.reorg_period_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(42.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let reorg_period_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.reorg_period_edit, reorg_period_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.reorg_period_edit.parse::<u32>().is_err() {
@ -339,16 +323,8 @@ impl PoolSetup {
ui.add_space(8.0);
// Draw pool size text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.pool_size_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(72.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let pool_size_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.pool_size_edit, pool_size_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.pool_size_edit.parse::<usize>().is_err() {
@ -424,16 +400,8 @@ impl PoolSetup {
ui.add_space(8.0);
// Draw stempool size text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.stempool_size_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(72.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let stem_pool_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.stempool_size_edit, stem_pool_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.stempool_size_edit.parse::<usize>().is_err() {
@ -509,16 +477,8 @@ impl PoolSetup {
ui.add_space(8.0);
// Draw tx weight text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.max_weight_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(72.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let mac_weight_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.max_weight_edit, mac_weight_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.max_weight_edit.parse::<u64>().is_err() {

View file

@ -12,14 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::{Id, RichText, TextStyle, Widget};
use egui::{Id, RichText};
use crate::gui::Colors;
use crate::gui::icons::{BARBELL, HARD_DRIVES, PLUG, POWER, TIMER};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, View};
use crate::gui::views::network::settings::NetworkSettings;
use crate::gui::views::types::{ModalContainer, ModalPosition};
use crate::gui::views::types::{ModalContainer, ModalPosition, TextEditOptions};
use crate::node::{Node, NodeConfig};
/// Stratum server setup section content.
@ -224,16 +224,8 @@ impl StratumSetup {
ui.add_space(8.0);
// Draw stratum port text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.stratum_port_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(64.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let text_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.stratum_port_edit, text_edit_opts);
// Show error when specified port is unavailable.
if !self.stratum_port_available_edit {
@ -327,16 +319,8 @@ impl StratumSetup {
ui.add_space(8.0);
// Draw attempt time text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.attempt_time_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(42.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let text_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.attempt_time_edit, text_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.attempt_time_edit.parse::<u32>().is_err() {
@ -413,16 +397,8 @@ impl StratumSetup {
ui.add_space(8.0);
// Draw share difficulty text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.min_share_diff_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(42.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let text_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.min_share_diff_edit, text_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.min_share_diff_edit.parse::<u64>().is_err() {

View file

@ -69,3 +69,62 @@ pub trait ModalContainer {
}
}
}
/// Options for [`egui::TextEdit`] view.
pub struct TextEditOptions {
/// View identifier.
pub id: egui::Id,
/// Flag to check if horizontal centering is needed.
pub h_center: bool,
/// Flag to check if initial focus on field is needed.
pub focus: bool,
/// Flag to hide letters and draw button to show/hide letters.
pub password: bool,
/// Flag to show copy button.
pub copy: bool,
/// Flag to show paste button.
pub paste: bool
}
impl TextEditOptions {
pub fn new(id: egui::Id) -> Self {
Self {
id,
h_center: false,
focus: true,
password: false,
copy: false,
paste: false,
}
}
/// Center text horizontally.
pub fn h_center(mut self) -> Self {
self.h_center = true;
self
}
/// Disable initial focus.
pub fn no_focus(mut self) -> Self {
self.focus = false;
self
}
/// Hide letters and draw button to show/hide letters.
pub fn password(mut self) -> Self {
self.password = true;
self
}
/// Show button to copy text.
pub fn copy(mut self) -> Self {
self.copy = true;
self
}
/// Show button to paste text.
pub fn paste(mut self) -> Self {
self.paste = true;
self
}
}

View file

@ -14,14 +14,16 @@
use std::sync::atomic::{AtomicI32, Ordering};
use egui::{Button, CursorIcon, PointerState, Rect, Response, RichText, Sense, Spinner, Widget};
use egui::{Align, Button, CursorIcon, Layout, PointerState, Rect, Response, RichText, Sense, Spinner, TextStyle, Vec2, Widget};
use egui::epaint::{CircleShape, Color32, FontId, RectShape, Rounding, Stroke};
use egui::epaint::text::TextWrapping;
use egui::text::{LayoutJob, TextFormat};
use lazy_static::lazy_static;
use crate::gui::Colors;
use crate::gui::icons::{CHECK_SQUARE, SQUARE};
use crate::gui::icons::{CHECK_SQUARE, CLIPBOARD_TEXT, COPY, EYE, EYE_SLASH, SQUARE};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::types::TextEditOptions;
pub struct View;
@ -129,8 +131,8 @@ impl View {
ui.style_mut().visuals.widgets.hovered.bg_stroke = Self::HOVER_STROKE;
ui.style_mut().visuals.widgets.active.bg_stroke = Self::DEFAULT_STROKE;
// Disable rounding.
ui.style_mut().visuals.widgets.hovered.rounding = Rounding::none();
ui.style_mut().visuals.widgets.active.rounding = Rounding::none();
ui.style_mut().visuals.widgets.hovered.rounding = Rounding::default();
ui.style_mut().visuals.widgets.active.rounding = Rounding::default();
// Disable expansion.
ui.style_mut().visuals.widgets.hovered.expansion = 0.0;
ui.style_mut().visuals.widgets.active.expansion = 0.0;
@ -276,6 +278,87 @@ impl View {
});
}
/// Default height of [`egui::TextEdit`] view.
const TEXT_EDIT_HEIGHT: f32 = 37.0;
/// Draw [`egui::TextEdit`] widget.
pub fn text_edit(ui: &mut egui::Ui,
cb: &dyn PlatformCallbacks,
value: &mut String,
options: TextEditOptions) {
let mut layout_rect = ui.available_rect_before_wrap();
layout_rect.set_height(Self::TEXT_EDIT_HEIGHT);
ui.allocate_ui_with_layout(layout_rect.size(), Layout::right_to_left(Align::Center), |ui| {
// Setup password button.
let mut show_pass = false;
if options.password {
// Set password button state value.
let show_pass_id = egui::Id::new(options.id).with("_show_pass");
show_pass = ui.data(|data| {
data.get_temp(show_pass_id)
}).unwrap_or(true);
// Draw button to show/hide current password.
let eye_icon = if show_pass { EYE } else { EYE_SLASH };
let mut changed = false;
View::button(ui, eye_icon.to_string(), Colors::WHITE, || {
show_pass = !show_pass;
changed = true;
});
// Save state if changed.
if changed {
ui.data_mut(|data| {
data.insert_temp(show_pass_id, show_pass);
});
}
ui.add_space(8.0);
}
// Setup copy button.
if options.copy {
let copy_icon = COPY.to_string();
View::button(ui, copy_icon, Colors::WHITE, || {
cb.copy_string_to_buffer(value.clone());
});
ui.add_space(8.0);
}
// Setup paste button.
if options.paste {
let paste_icon = CLIPBOARD_TEXT.to_string();
View::button(ui, paste_icon, Colors::WHITE, || {
*value = cb.get_string_from_buffer();
});
ui.add_space(8.0);
}
let layout_size = ui.available_size();
ui.allocate_ui_with_layout(layout_size, Layout::left_to_right(Align::Center), |ui| {
// Setup text edit size.
let mut edit_rect = ui.available_rect_before_wrap();
edit_rect.set_height(Self::TEXT_EDIT_HEIGHT);
// Show text edit.
let text_edit_resp = egui::TextEdit::singleline(value)
.id(options.id)
.margin(Vec2::new(2.0, 0.0))
.font(TextStyle::Heading)
.min_size(edit_rect.size())
.horizontal_align(if options.h_center { Align::Center } else { Align::Min })
.vertical_align(Align::Center)
.password(show_pass)
.ui(ui);
// Show keyboard on click.
if text_edit_resp.clicked() {
cb.show_keyboard();
}
// Setup focus on input field.
if options.focus {
text_edit_resp.request_focus();
cb.show_keyboard();
}
});
});
}
/// Calculate item background/button rounding based on item index.
pub fn item_rounding(index: usize, len: usize, is_button: bool) -> Rounding {
let corners = if is_button {

View file

@ -12,15 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::{Align, Align2, Layout, Margin, RichText, Rounding, ScrollArea, TextStyle, Widget};
use egui_extras::{Size, StripBuilder};
use egui::{Align, Align2, Id, Layout, Margin, RichText, Rounding, ScrollArea, Widget};
use crate::AppConfig;
use crate::gui::Colors;
use crate::gui::icons::{ARROW_LEFT, CARET_RIGHT, COMPUTER_TOWER, EYE, EYE_SLASH, FOLDER_LOCK, FOLDER_OPEN, GEAR, GLOBE, GLOBE_SIMPLE, LOCK_KEY, PLUS, SIDEBAR_SIMPLE, SPINNER, SUITCASE, WARNING_CIRCLE};
use crate::gui::icons::{ARROW_LEFT, CARET_RIGHT, COMPUTER_TOWER, FOLDER_LOCK, FOLDER_OPEN, GEAR, GLOBE, GLOBE_SIMPLE, LOCK_KEY, PLUS, SIDEBAR_SIMPLE, SPINNER, SUITCASE, WARNING_CIRCLE};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, Root, TitlePanel, View};
use crate::gui::views::types::{ModalContainer, ModalPosition, TitleContentType, TitleType};
use crate::gui::views::types::{ModalContainer, ModalPosition, TextEditOptions, TitleContentType, TitleType};
use crate::gui::views::wallets::creation::WalletCreation;
use crate::gui::views::wallets::types::WalletTabType;
use crate::gui::views::wallets::WalletContent;
@ -33,8 +32,6 @@ pub struct WalletsContent {
/// Password to open wallet for [`Modal`].
pass_edit: String,
/// Flag to show/hide password at [`egui::TextEdit`] field.
hide_pass: bool,
/// Flag to check if wrong password was entered.
wrong_pass: bool,
@ -58,7 +55,6 @@ impl Default for WalletsContent {
Self {
wallets: WalletList::default(),
pass_edit: "".to_string(),
hide_pass: true,
wrong_pass: false,
wallet_content: WalletContent::default(),
creation_content: WalletCreation::default(),
@ -407,7 +403,7 @@ impl WalletsContent {
// Show button to close opened wallet.
if !wallet.is_closing() {
View::item_button(ui, if !is_selected {
Rounding::none()
Rounding::default()
} else {
View::item_rounding(0, 1, true)
}, LOCK_KEY, None, || {
@ -510,7 +506,6 @@ impl WalletsContent {
/// Show [`Modal`] to open selected wallet.
pub fn show_open_wallet_modal(&mut self, cb: &dyn PlatformCallbacks) {
// Reset modal values.
self.hide_pass = true;
self.pass_edit = String::from("");
self.wrong_pass = false;
// Show modal.
@ -531,42 +526,11 @@ impl WalletsContent {
ui.label(RichText::new(t!("wallets.pass"))
.size(17.0)
.color(Colors::GRAY));
ui.add_space(10.0);
ui.add_space(8.0);
StripBuilder::new(ui)
.size(Size::exact(34.0))
.vertical(|mut strip| {
strip.strip(|builder| {
builder
.size(Size::remainder())
.size(Size::exact(48.0))
.horizontal(|mut strip| {
strip.cell(|ui| {
// Draw wallet password text edit.
let pass_resp = egui::TextEdit::singleline(&mut self.pass_edit)
.id(ui.id().with("wallet_pass_edit"))
.font(TextStyle::Heading)
.desired_width(ui.available_width())
.cursor_at_end(true)
.password(self.hide_pass)
.ui(ui);
pass_resp.request_focus();
if pass_resp.clicked() {
cb.show_keyboard();
}
});
strip.cell(|ui| {
ui.vertical_centered(|ui| {
// Draw button to show/hide password.
let eye_icon = if self.hide_pass { EYE } else { EYE_SLASH };
View::button(ui, eye_icon.to_string(), Colors::WHITE, || {
self.hide_pass = !self.hide_pass;
});
});
});
});
})
});
// Show password input.
let pass_edit_opts = TextEditOptions::new(Id::from(modal.id)).password();
View::text_edit(ui, cb, &mut self.pass_edit, pass_edit_opts);
// Show information when password is empty.
if self.pass_edit.is_empty() {
@ -607,7 +571,6 @@ impl WalletsContent {
// Clear values.
self.pass_edit = "".to_string();
self.wrong_pass = false;
self.hide_pass = true;
// Close modal.
cb.hide_keyboard();
modal.close();

View file

@ -20,7 +20,7 @@ use crate::gui::Colors;
use crate::gui::icons::{CHECK, EYE, EYE_SLASH, FOLDER_PLUS, SHARE_FAT};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, Root, View};
use crate::gui::views::types::ModalPosition;
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;
@ -32,14 +32,12 @@ pub struct WalletCreation {
/// Wallet creation step.
step: Option<Step>,
/// Flag to check if [`Modal`] just was opened to focus on first field.
/// Flag to check if wallet creation [`Modal`] was just opened to focus on first field.
modal_just_opened: bool,
/// Wallet name value.
name_edit: String,
/// Password to encrypt created wallet.
pass_edit: String,
/// Flag to show/hide password at [`egui::TextEdit`] field.
hide_pass: bool,
/// Mnemonic phrase setup content.
pub(crate) mnemonic_setup: MnemonicSetup,
@ -54,7 +52,6 @@ impl Default for WalletCreation {
modal_just_opened: true,
name_edit: String::from(""),
pass_edit: String::from(""),
hide_pass: true,
mnemonic_setup: MnemonicSetup::default(),
network_setup: ConnectionSetup::default()
}
@ -313,7 +310,6 @@ impl WalletCreation {
/// Start wallet creation from showing [`Modal`] to enter name and password.
pub fn show_name_pass_modal(&mut self, cb: &dyn PlatformCallbacks) {
// Reset modal values.
self.hide_pass = true;
self.modal_just_opened = true;
self.name_edit = String::from("");
self.pass_edit = String::from("");
@ -338,68 +334,25 @@ impl WalletCreation {
ui.add_space(8.0);
// Show wallet name text edit.
let name_resp = egui::TextEdit::singleline(&mut self.name_edit)
.id(Id::from(modal.id).with("wallet_name_edit"))
.font(TextStyle::Heading)
.desired_width(ui.available_width())
.cursor_at_end(true)
.ui(ui);
ui.add_space(8.0);
if name_resp.clicked() {
cb.show_keyboard();
}
// Check if modal was just opened to show focus on name text input.
let mut name_edit_opts = TextEditOptions::new(Id::from(modal.id).with("name"))
.no_focus();
if self.modal_just_opened {
self.modal_just_opened = false;
cb.show_keyboard();
name_resp.request_focus();
name_edit_opts.focus = true;
}
View::text_edit(ui, cb, &mut self.name_edit, name_edit_opts);
ui.add_space(8.0);
ui.label(RichText::new(t!("wallets.pass"))
.size(17.0)
.color(Colors::GRAY));
ui.add_space(8.0);
StripBuilder::new(ui)
.size(Size::exact(34.0))
.vertical(|mut strip| {
strip.strip(|builder| {
builder
.size(Size::remainder())
.size(Size::exact(48.0))
.horizontal(|mut strip| {
strip.cell(|ui| {
ui.add_space(2.0);
// Draw wallet password text edit.
let pass_resp = egui::TextEdit::singleline(&mut self.pass_edit)
.id(Id::from(modal.id).with("wallet_pass_edit"))
.font(TextStyle::Heading)
.desired_width(ui.available_width())
.cursor_at_end(true)
.password(self.hide_pass)
.ui(ui);
if pass_resp.clicked() {
cb.show_keyboard();
}
// Hide keyboard if input fields has no focus.
if !pass_resp.has_focus() && !name_resp.has_focus() {
cb.hide_keyboard();
}
});
strip.cell(|ui| {
ui.vertical_centered(|ui| {
// Draw button to show/hide password.
let eye_icon = if self.hide_pass { EYE } else { EYE_SLASH };
View::button(ui, eye_icon.to_string(), Colors::WHITE, || {
self.hide_pass = !self.hide_pass;
});
});
});
});
})
});
let pass_text_edit_opts = TextEditOptions::new(Id::from(modal.id).with("pass"))
.password()
.no_focus();
View::text_edit(ui, cb, &mut self.pass_edit, pass_text_edit_opts);
ui.add_space(12.0);
});

View file

@ -12,13 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::{Id, RichText, TextStyle, Widget};
use egui::{Id, RichText};
use crate::gui::Colors;
use crate::gui::icons::PENCIL;
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, Root, View};
use crate::gui::views::types::{ModalContainer, ModalPosition};
use crate::gui::views::types::{ModalContainer, ModalPosition, TextEditOptions};
use crate::wallet::Mnemonic;
use crate::wallet::types::{PhraseMode, PhraseSize};
@ -265,16 +265,8 @@ impl MnemonicSetup {
ui.add_space(8.0);
// Draw word value text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.word_edit)
.id(Id::from(modal.id).with(self.word_num_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() {
cb.show_keyboard();
}
let text_edit_opts = TextEditOptions::new(Id::from(modal.id).with(self.word_num_edit));
View::text_edit(ui, cb, &mut self.word_edit, text_edit_opts);
// Show error when specified word is not valid.
if !self.valid_word_edit {

View file

@ -18,7 +18,7 @@ use crate::gui::Colors;
use crate::gui::icons::{CLOCK_COUNTDOWN, EYE, EYE_SLASH, PASSWORD, PENCIL};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, View};
use crate::gui::views::types::ModalPosition;
use crate::gui::views::types::{ModalPosition, TextEditOptions};
use crate::wallet::Wallet;
/// Common wallet setup content.
@ -31,13 +31,9 @@ pub struct CommonSetup {
/// Flag to check if wrong password was entered.
wrong_pass: bool,
/// Current wallet password [`Modal`] value.
current_pass_edit: String,
/// Flag to show/hide old password at [`egui::TextEdit`] field.
hide_current_pass: bool,
old_pass_edit: String,
/// New wallet password [`Modal`] value.
new_pass_edit: String,
/// Flag to show/hide new password at [`egui::TextEdit`] field.
hide_new_pass: bool,
/// Minimum confirmations number value.
min_confirmations_edit: String
@ -56,10 +52,8 @@ impl Default for CommonSetup {
name_edit: "".to_string(),
first_edit_pass_opening: true,
wrong_pass: false,
current_pass_edit: "".to_string(),
hide_current_pass: true,
old_pass_edit: "".to_string(),
new_pass_edit: "".to_string(),
hide_new_pass: true,
min_confirmations_edit: "".to_string()
}
}
@ -106,10 +100,8 @@ impl CommonSetup {
View::button(ui, pass_text, Colors::BUTTON, || {
// Setup modal values.
self.first_edit_pass_opening = true;
self.current_pass_edit = "".to_string();
self.old_pass_edit = "".to_string();
self.new_pass_edit = "".to_string();
self.hide_current_pass = true;
self.hide_new_pass = true;
self.wrong_pass = false;
// Show wallet password modal.
Modal::new(PASS_EDIT_MODAL)
@ -187,17 +179,10 @@ impl CommonSetup {
.color(Colors::GRAY));
ui.add_space(8.0);
// Draw wallet name edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.name_edit)
.id(Id::from(modal.id).with(wallet.get_config().id))
.font(TextStyle::Heading)
.desired_width(ui.available_width())
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
// Show wallet name text edit.
let name_edit_id = Id::from(modal.id).with(wallet.get_config().id);
let name_edit_opts = TextEditOptions::new(name_edit_id);
View::text_edit(ui, cb, &mut self.name_edit, name_edit_opts);
ui.add_space(12.0);
});
@ -248,83 +233,41 @@ impl CommonSetup {
ui.label(RichText::new(t!("wallets.current_pass"))
.size(17.0)
.color(Colors::GRAY));
ui.add_space(6.0);
ui.add_space(8.0);
let mut rect = ui.available_rect_before_wrap();
rect.set_height(34.0);
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
// Draw button to show/hide current password.
let eye_icon = if self.hide_current_pass { EYE } else { EYE_SLASH };
View::button(ui, eye_icon.to_string(), Colors::WHITE, || {
self.hide_current_pass = !self.hide_current_pass;
});
let layout_size = ui.available_size();
ui.allocate_ui_with_layout(layout_size, Layout::left_to_right(Align::Center), |ui| {
// Draw current wallet password text edit.
let old_pass_resp = egui::TextEdit::singleline(&mut self.current_pass_edit)
.id(Id::from(modal.id).with(wallet_id).with("old_pass"))
.font(TextStyle::Heading)
.desired_width(ui.available_width())
.cursor_at_end(true)
.password(self.hide_current_pass)
.ui(ui);
if old_pass_resp.clicked() {
cb.show_keyboard();
}
// Setup focus on input field on first modal opening.
// Draw old password text edit.
let pass_edit_id = Id::from(modal.id).with(wallet_id).with("old_pass");
let mut pass_edit_opts = TextEditOptions::new(pass_edit_id).password().no_focus();
if self.first_edit_pass_opening {
self.first_edit_pass_opening = false;
old_pass_resp.request_focus();
pass_edit_opts.focus = true;
}
});
});
ui.add_space(6.0);
View::text_edit(ui, cb, &mut self.old_pass_edit, pass_edit_opts);
ui.add_space(8.0);
ui.label(RichText::new(t!("wallets.new_pass"))
.size(17.0)
.color(Colors::GRAY));
ui.add_space(6.0);
ui.add_space(8.0);
let mut new_rect = ui.available_rect_before_wrap();
new_rect.set_height(34.0);
ui.allocate_ui_with_layout(new_rect.size(), Layout::right_to_left(Align::Center), |ui| {
// Draw button to show/hide new password.
let eye_icon = if self.hide_new_pass { EYE } else { EYE_SLASH };
View::button(ui, eye_icon.to_string(), Colors::WHITE, || {
self.hide_new_pass = !self.hide_new_pass;
});
let layout_size = ui.available_size();
ui.allocate_ui_with_layout(layout_size, Layout::left_to_right(Align::Center), |ui| {
// Draw new wallet password text edit.
let new_pass_resp = egui::TextEdit::singleline(&mut self.new_pass_edit)
.id(Id::from(modal.id).with(wallet_id).with("new_pass"))
.font(TextStyle::Heading)
.desired_width(ui.available_width())
.cursor_at_end(true)
.password(self.hide_new_pass)
.ui(ui);
if new_pass_resp.clicked() {
cb.show_keyboard();
}
});
});
// Draw new password text edit.
let new_pass_edit_id = Id::from(modal.id).with(wallet_id).with("new_pass");
let new_pass_edit_opts = TextEditOptions::new(new_pass_edit_id).password().no_focus();
View::text_edit(ui, cb, &mut self.new_pass_edit, new_pass_edit_opts);
// Show information when password is empty.
if self.current_pass_edit.is_empty() || self.new_pass_edit.is_empty() {
ui.add_space(8.0);
if self.old_pass_edit.is_empty() || self.new_pass_edit.is_empty() {
ui.add_space(10.0);
ui.label(RichText::new(t!("wallets.pass_empty"))
.size(17.0)
.color(Colors::INACTIVE_TEXT));
} else if self.wrong_pass {
ui.add_space(8.0);
ui.add_space(10.0);
ui.label(RichText::new(t!("wallets.wrong_pass"))
.size(17.0)
.color(Colors::RED));
}
ui.add_space(10.0);
ui.add_space(12.0);
});
// Show modal buttons.
@ -346,17 +289,13 @@ impl CommonSetup {
if self.new_pass_edit.is_empty() {
return;
}
let old_pass = self.current_pass_edit.clone();
let old_pass = self.old_pass_edit.clone();
let new_pass = self.new_pass_edit.clone();
match wallet.change_password(old_pass, new_pass) {
Ok(_) => {
// Clear values.
self.first_edit_pass_opening = true;
self.current_pass_edit = "".to_string();
// Clear password values.
self.old_pass_edit = "".to_string();
self.new_pass_edit = "".to_string();
self.hide_current_pass = true;
self.hide_new_pass = true;
self.wrong_pass = false;
// Close modal.
cb.hide_keyboard();
modal.close();
@ -391,16 +330,8 @@ impl CommonSetup {
ui.add_space(8.0);
// Minimum amount of confirmations text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.min_confirmations_edit)
.id(Id::from(modal.id))
.font(TextStyle::Heading)
.desired_width(48.0)
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
let text_edit_opts = TextEditOptions::new(Id::from(modal.id)).h_center();
View::text_edit(ui, cb, &mut self.min_confirmations_edit, text_edit_opts);
// Show error when specified value is not valid or reminder to restart enabled node.
if self.min_confirmations_edit.parse::<u64>().is_err() {

View file

@ -12,14 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::{Align, Id, Layout, RichText, Rounding, TextStyle, Widget};
use egui::{Align, Id, Layout, RichText, Rounding, Widget};
use url::Url;
use crate::gui::Colors;
use crate::gui::icons::{CHECK, CHECK_CIRCLE, CHECK_FAT, COMPUTER_TOWER, DOTS_THREE_CIRCLE, GLOBE, PLUS_CIRCLE, POWER, X_CIRCLE};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, View};
use crate::gui::views::types::{ModalContainer, ModalPosition};
use crate::gui::views::types::{ModalContainer, ModalPosition, TextEditOptions};
use crate::node::{Node, NodeConfig};
use crate::wallet::{ConnectionsConfig, ExternalConnection, Wallet};
use crate::wallet::types::ConnectionMethod;
@ -165,7 +165,7 @@ impl ConnectionSetup {
// Show button to add new external node connection.
let add_node_text = format!("{} {}", PLUS_CIRCLE, t!("wallets.add_node"));
View::button(ui, add_node_text, Colors::GOLD, || {
View::button(ui, add_node_text, Colors::WHITE, || {
self.show_add_ext_conn_modal(cb);
});
ui.add_space(12.0);
@ -207,7 +207,7 @@ impl ConnectionSetup {
if !Node::is_running() {
// Draw button to start integrated node.
View::item_button(ui, Rounding::none(), POWER, Some(Colors::GREEN), || {
View::item_button(ui, Rounding::default(), POWER, Some(Colors::GREEN), || {
Node::start();
});
}
@ -326,20 +326,14 @@ impl ConnectionSetup {
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))
.font(TextStyle::Heading)
.desired_width(ui.available_width())
.cursor_at_end(true)
.ui(ui);
ui.add_space(8.0);
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_resp.request_focus();
}
if url_edit_resp.clicked() {
cb.show_keyboard();
url_edit_opts.focus = true;
}
View::text_edit(ui, cb, &mut self.ext_node_url_edit, url_edit_opts);
ui.add_space(8.0);
ui.label(RichText::new(t!("wallets.node_secret"))
.size(17.0)
@ -347,25 +341,18 @@ impl ConnectionSetup {
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();
}
let secret_edit_id = Id::from(modal.id).with("node_secret_edit");
let secret_edit_opts = TextEditOptions::new(secret_edit_id).paste().no_focus();
View::text_edit(ui, cb, &mut self.ext_node_secret_edit, secret_edit_opts);
// Show error when specified URL is not valid.
if self.ext_node_url_error {
ui.add_space(2.0);
ui.add_space(10.0);
ui.label(RichText::new(t!("wallets.invalid_url"))
.size(17.0)
.color(Colors::RED));
}
ui.add_space(12.0);
ui.add_space(10.0);
});
// Show modal buttons.

View file

@ -12,15 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::{Align, Id, Layout, RichText, TextStyle, Widget};
use egui::{Id, RichText, Widget};
use grin_chain::SyncStatus;
use grin_util::ZeroingString;
use crate::gui::Colors;
use crate::gui::icons::{EYE, EYE_SLASH, STETHOSCOPE, TRASH, WRENCH};
use crate::gui::icons::{EYE, STETHOSCOPE, TRASH, WRENCH};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, View};
use crate::gui::views::types::ModalPosition;
use crate::gui::views::types::{ModalPosition, TextEditOptions};
use crate::node::Node;
use crate::wallet::Wallet;
@ -30,8 +30,6 @@ pub struct RecoverySetup {
pass_edit: String,
/// Flag to check if wrong password was entered.
wrong_pass: bool,
/// Flag to show/hide old password at [`egui::TextEdit`] field.
hide_pass: bool,
/// Recovery phrase value.
recovery_phrase: Option<ZeroingString>,
@ -46,7 +44,6 @@ impl Default for RecoverySetup {
fn default() -> Self {
Self {
wrong_pass: false,
hide_pass: false,
pass_edit: "".to_string(),
recovery_phrase: None,
}
@ -153,7 +150,6 @@ impl RecoverySetup {
// Setup modal values.
self.pass_edit = "".to_string();
self.wrong_pass = false;
self.hide_pass = true;
self.recovery_phrase = None;
// Show recovery phrase modal.
Modal::new(RECOVERY_PHRASE_MODAL)
@ -176,7 +172,7 @@ impl RecoverySetup {
.size(17.0)
.color(Colors::BLACK));
});
ui.add_space(6.0);
ui.add_space(10.0);
ui.vertical_centered_justified(|ui| {
View::button(ui, t!("close"), Colors::WHITE, || {
self.recovery_phrase = None;
@ -188,50 +184,29 @@ impl RecoverySetup {
ui.label(RichText::new(t!("wallets.pass"))
.size(17.0)
.color(Colors::GRAY));
ui.add_space(6.0);
ui.add_space(8.0);
});
let mut rect = ui.available_rect_before_wrap();
rect.set_height(34.0);
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
// Draw button to show/hide current password.
let eye_icon = if self.hide_pass { EYE } else { EYE_SLASH };
View::button(ui, eye_icon.to_string(), Colors::WHITE, || {
self.hide_pass = !self.hide_pass;
});
let layout_size = ui.available_size();
ui.allocate_ui_with_layout(layout_size, Layout::left_to_right(Align::Center), |ui| {
// Draw current wallet password text edit.
let pass_resp = egui::TextEdit::singleline(&mut self.pass_edit)
.id(Id::from(modal.id).with(wallet.get_config().id).with("recovery_phrase"))
.font(TextStyle::Heading)
.desired_width(ui.available_width())
.cursor_at_end(true)
.password(self.hide_pass)
.ui(ui);
if pass_resp.clicked() {
cb.show_keyboard();
}
pass_resp.request_focus();
});
});
let pass_edit_id = Id::from(modal.id).with(wallet.get_config().id);
let pass_edit_opts = TextEditOptions::new(pass_edit_id).password();
View::text_edit(ui, cb, &mut self.pass_edit, pass_edit_opts);
// Show information when password is empty.
ui.vertical_centered(|ui| {
if self.pass_edit.is_empty() {
ui.add_space(8.0);
ui.add_space(10.0);
ui.label(RichText::new(t!("wallets.pass_empty"))
.size(17.0)
.color(Colors::INACTIVE_TEXT));
} else if self.wrong_pass {
ui.add_space(8.0);
ui.add_space(10.0);
ui.label(RichText::new(t!("wallets.wrong_pass"))
.size(17.0)
.color(Colors::RED));
}
ui.add_space(10.0);
});
ui.add_space(12.0);
// Show modal buttons.
ui.scope(|ui| {
@ -277,7 +252,7 @@ impl RecoverySetup {
.size(17.0)
.color(Colors::TEXT));
});
ui.add_space(10.0);
ui.add_space(12.0);
// Show modal buttons.
ui.scope(|ui| {

View file

@ -14,16 +14,16 @@
use std::time::Duration;
use egui::{Align, Id, Layout, Margin, RichText, Rounding, ScrollArea, TextStyle, Widget};
use egui::{Align, Id, Layout, Margin, RichText, Rounding, ScrollArea, Widget};
use grin_chain::SyncStatus;
use grin_core::core::amount_to_hr_string;
use crate::AppConfig;
use crate::gui::Colors;
use crate::gui::icons::{CHECK, CHECK_FAT, CREDIT_CARD, DOWNLOAD, FILE_ARCHIVE, GEAR_FINE, LIST, PACKAGE, PLUS, POWER, REPEAT, UPLOAD, WALLET};
use crate::gui::icons::{CHECK, CHECK_FAT, DOWNLOAD, FILE_ARCHIVE, GEAR_FINE, LIST, PACKAGE, PLUS, POWER, REPEAT, UPLOAD, WALLET};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, Root, View};
use crate::gui::views::types::ModalPosition;
use crate::gui::views::types::{ModalPosition, TextEditOptions};
use crate::gui::views::wallets::{WalletInfo, WalletReceive, WalletSend, WalletSettings};
use crate::gui::views::wallets::types::{WalletTab, WalletTabType};
use crate::node::Node;
@ -285,28 +285,19 @@ impl WalletContent {
ui.add_space(8.0);
// Draw account name edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.account_label_edit)
.id(Id::from(modal.id).with(wallet.get_config().id))
.font(TextStyle::Heading)
.desired_width(ui.available_width())
.cursor_at_end(true)
.ui(ui);
text_edit_resp.request_focus();
if text_edit_resp.clicked() {
cb.show_keyboard();
}
ui.add_space(8.0);
let text_edit_id = Id::from(modal.id).with(wallet.get_config().id);
let text_edit_opts = TextEditOptions::new(text_edit_id);
View::text_edit(ui, cb, &mut self.account_label_edit, text_edit_opts);
// Show error occurred during account creation..
if self.account_creation_error {
ui.add_space(2.0);
ui.add_space(12.0);
ui.label(RichText::new(t!("error"))
.size(17.0)
.color(Colors::RED));
}
});
ui.add_space(12.0);
});
// Show modal buttons.
ui.scope(|ui| {

View file

@ -192,7 +192,7 @@ fn tx_item_ui(ui: &mut egui::Ui,
if !is_cancelling && !tx.confirmed && tx.tx_type != TxLogEntryType::TxReceivedCancelled
&& tx.tx_type != TxLogEntryType::TxSentCancelled {
View::item_button(ui, Rounding::none(), PROHIBIT, Some(Colors::RED), || {
View::item_button(ui, Rounding::default(), PROHIBIT, Some(Colors::RED), || {
wallet.cancel(tx.id);
//TODO: Cancel tx
});