ui: modal show method refactoring, mnemonic word input, update translations

This commit is contained in:
ardocrat 2023-07-23 11:48:28 +03:00
parent 952796abff
commit 2f5011c36f
14 changed files with 376 additions and 226 deletions

View file

@ -4,7 +4,6 @@ continue: Continue
complete: Complete complete: Complete
wallets: wallets:
title: Wallets title: Wallets
new: New wallet
create_desc: Create or import existing wallet from saved recovery phrase. create_desc: Create or import existing wallet from saved recovery phrase.
add: Add wallet add: Add wallet
name: 'Name:' name: 'Name:'
@ -13,13 +12,12 @@ wallets:
pass_empty: Enter password for wallet pass_empty: Enter password for wallet
create: Create create: Create
recover: Restore recover: Restore
saved_phrase: Saved phrase
words_count: 'Words count:' words_count: 'Words count:'
word_number: 'Word #%{number}' enter_word: 'Enter word #%{number}:'
word_empty: 'Enter word #%{number} from your recovery phrase'
not_valid_word: Entered word is not valid not_valid_word: Entered word is not valid
create_phrase_desc: Safely write down and save your recovery phrase. create_phrase_desc: Safely write down and save your recovery phrase.
restore_phrase_desc: Enter words from your saved recovery phrase. restore_phrase_desc: Enter words from your saved recovery phrase.
conf_phrase_desc: Select words in the same order as they are displayed in your recovery phrase.
setup_conn_desc: Choose wallet connection method. setup_conn_desc: Choose wallet connection method.
network: network:
self: Network self: Network

View file

@ -4,7 +4,6 @@ continue: Продолжить
complete: Завершить complete: Завершить
wallets: wallets:
title: Кошельки title: Кошельки
new: Новый кошелёк
create_desc: Создайте или импортируйте существующий кошелёк из сохранённой фразы восстановления. create_desc: Создайте или импортируйте существующий кошелёк из сохранённой фразы восстановления.
add: Добавить кошелёк add: Добавить кошелёк
name: 'Название:' name: 'Название:'
@ -13,13 +12,12 @@ wallets:
pass_empty: Введите пароль для кошелька pass_empty: Введите пароль для кошелька
create: Создать create: Создать
recover: Восстановить recover: Восстановить
saved_phrase: Сохранённая фраза
words_count: 'Количество слов:' words_count: 'Количество слов:'
word_number: 'Слово #%{number}' enter_word: 'Введите слово #%{number}:'
word_empty: 'Введите слово #%{number} из вашей фразы восстановления'
not_valid_word: Введено недопустимое слово not_valid_word: Введено недопустимое слово
create_phrase_desc: Безопасно запишите и сохраните свою фразу восстановления. create_phrase_desc: Безопасно запишите и сохраните вашу фразу восстановления.
restore_phrase_desc: Введите слова из вашей сохранённой фразы восстановления. restore_phrase_desc: Введите слова из вашей сохранённой фразы восстановления.
conf_phrase_desc: Выберите слова в таком же порядке, как они отображены в вашей фразе восстановления.
setup_conn_desc: Выберите способ подключения кошелька setup_conn_desc: Выберите способ подключения кошелька
network: network:
self: Сеть self: Сеть

View file

@ -114,16 +114,16 @@ impl Modal {
self.closeable.load(Ordering::Relaxed) self.closeable.load(Ordering::Relaxed)
} }
/// Set title text on Modal creation. /// Set title text on [`Modal`] creation.
pub fn title(mut self, title: String) -> Self { pub fn title(mut self, title: String) -> Self {
self.title = Some(title.to_uppercase()); self.title = Some(title.to_uppercase());
self self
} }
/// Set [`Modal`] instance to show at ui. /// Set [`Modal`] instance into state to show at ui.
pub fn show(modal: Modal) { pub fn show(self) {
let mut w_nav = MODAL_STATE.write().unwrap(); let mut w_nav = MODAL_STATE.write().unwrap();
w_nav.modal = Some(modal); w_nav.modal = Some(self);
} }
/// Remove [`Modal`] from [`MODAL_STATE`] if it's showing and can be closed. /// Remove [`Modal`] from [`MODAL_STATE`] if it's showing and can be closed.

View file

@ -134,10 +134,10 @@ impl NetworkSettings {
t!("network_settings.reset_settings")); t!("network_settings.reset_settings"));
View::button(ui, button_text, Colors::GOLD, || { View::button(ui, button_text, Colors::GOLD, || {
// Show modal to confirm settings reset. // Show modal to confirm settings reset.
let reset_modal = Modal::new(Self::RESET_SETTINGS_MODAL) Modal::new(Self::RESET_SETTINGS_MODAL)
.position(ModalPosition::Center) .position(ModalPosition::Center)
.title(t!("modal.confirmation")); .title(t!("modal.confirmation"))
Modal::show(reset_modal); .show();
}); });
// Show reminder to restart enabled node. // Show reminder to restart enabled node.
@ -200,10 +200,10 @@ impl NetworkSettings {
pub fn show_node_restart_required_modal() { pub fn show_node_restart_required_modal() {
if Node::is_running() { if Node::is_running() {
// Show modal to apply changes by node restart. // Show modal to apply changes by node restart.
let port_modal = Modal::new(Self::NODE_RESTART_REQUIRED_MODAL) Modal::new(Self::NODE_RESTART_REQUIRED_MODAL)
.position(ModalPosition::Center) .position(ModalPosition::Center)
.title(t!("network.settings")); .title(t!("network.settings"))
Modal::show(port_modal); .show();
} }
} }

View file

@ -113,10 +113,10 @@ impl DandelionSetup {
// Setup values for modal. // Setup values for modal.
self.epoch_edit = epoch; self.epoch_edit = epoch;
// Show epoch setup modal. // Show epoch setup modal.
let epoch_modal = Modal::new(Self::EPOCH_MODAL) Modal::new(Self::EPOCH_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(epoch_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);
@ -198,11 +198,10 @@ impl DandelionSetup {
// Setup values for modal. // Setup values for modal.
self.embargo_edit = embargo; self.embargo_edit = embargo;
// Show embargo setup modal. // Show embargo setup modal.
let embargo_modal = Modal::new(Self::EMBARGO_MODAL) Modal::new(Self::EMBARGO_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(embargo_modal); .show();
cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);
} }
@ -283,10 +282,10 @@ impl DandelionSetup {
// Setup values for modal. // Setup values for modal.
self.aggregation_edit = agg; self.aggregation_edit = agg;
// Show aggregation setup modal. // Show aggregation setup modal.
let aggregation_modal = Modal::new(Self::AGGREGATION_MODAL) Modal::new(Self::AGGREGATION_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(aggregation_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);
@ -368,10 +367,10 @@ impl DandelionSetup {
// Setup values for modal. // Setup values for modal.
self.stem_prob_edit = stem_prob; self.stem_prob_edit = stem_prob;
// Show stem probability setup modal. // Show stem probability setup modal.
let embargo_modal = Modal::new(Self::STEM_PROBABILITY_MODAL) Modal::new(Self::STEM_PROBABILITY_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(embargo_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);

View file

@ -221,10 +221,10 @@ impl NodeSetup {
self.api_port_available_edit = self.is_api_port_available; self.api_port_available_edit = self.is_api_port_available;
// Show API port modal. // Show API port modal.
let port_modal = Modal::new(Self::API_PORT_MODAL) Modal::new(Self::API_PORT_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(port_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);
@ -335,10 +335,10 @@ impl NodeSetup {
// Setup values for modal. // Setup values for modal.
self.secret_edit = secret_value.unwrap_or("".to_string()); self.secret_edit = secret_value.unwrap_or("".to_string());
// Show secret edit modal. // Show secret edit modal.
let port_modal = Modal::new(modal_id) Modal::new(modal_id)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(port_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
} }
@ -455,11 +455,11 @@ impl NodeSetup {
View::button(ui, format!("{} {}", CLOCK_CLOCKWISE, ftl.clone()), Colors::BUTTON, || { View::button(ui, format!("{} {}", CLOCK_CLOCKWISE, ftl.clone()), Colors::BUTTON, || {
// Setup values for modal. // Setup values for modal.
self.ftl_edit = ftl; self.ftl_edit = ftl;
// Show stratum port modal. // Show ftl value setup modal.
let ftl_modal = Modal::new(Self::FTL_MODAL) Modal::new(Self::FTL_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(ftl_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);
@ -478,7 +478,7 @@ impl NodeSetup {
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
// Draw stratum port text edit. // Draw ftl value text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.ftl_edit) let text_edit_resp = egui::TextEdit::singleline(&mut self.ftl_edit)
.id(Id::from(modal.id)) .id(Id::from(modal.id))
.font(TextStyle::Heading) .font(TextStyle::Heading)

View file

@ -212,15 +212,15 @@ impl P2PSetup {
self.port_edit = port; self.port_edit = port;
self.port_available_edit = self.is_port_available; self.port_available_edit = self.is_port_available;
// Show p2p port modal. // Show p2p port modal.
let port_modal = Modal::new(Self::PORT_MODAL) Modal::new(Self::PORT_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(port_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);
// Show error when stratum server port is unavailable. // Show error when p2p port is unavailable.
if !self.is_port_available { if !self.is_port_available {
ui.add_space(6.0); ui.add_space(6.0);
ui.label(RichText::new(t!("network_settings.port_unavailable")) ui.label(RichText::new(t!("network_settings.port_unavailable"))
@ -371,10 +371,10 @@ impl P2PSetup {
_ => Self::DNS_SEEDS_TITLE.to_string() _ => Self::DNS_SEEDS_TITLE.to_string()
}; };
// Show modal to add peer. // Show modal to add peer.
let peer_modal = Modal::new(modal_id) Modal::new(modal_id)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(modal_title); .title(modal_title)
Modal::show(peer_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
} }
@ -580,10 +580,10 @@ impl P2PSetup {
// Setup values for modal. // Setup values for modal.
self.ban_window_edit = ban_window; self.ban_window_edit = ban_window;
// Show ban window period setup modal. // Show ban window period setup modal.
let ban_modal = Modal::new(Self::BAN_WINDOW_MODAL) Modal::new(Self::BAN_WINDOW_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(ban_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);
@ -671,10 +671,10 @@ impl P2PSetup {
// Setup values for modal. // Setup values for modal.
self.max_inbound_count = max_inbound; self.max_inbound_count = max_inbound;
// Show maximum number of inbound peers setup modal. // Show maximum number of inbound peers setup modal.
let max_inbound_modal = Modal::new(Self::MAX_INBOUND_MODAL) Modal::new(Self::MAX_INBOUND_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(max_inbound_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);
@ -757,10 +757,10 @@ impl P2PSetup {
// Setup values for modal. // Setup values for modal.
self.max_outbound_count = max_outbound; self.max_outbound_count = max_outbound;
// Show maximum number of outbound peers setup modal. // Show maximum number of outbound peers setup modal.
let max_outbound = Modal::new(Self::MAX_OUTBOUND_MODAL) Modal::new(Self::MAX_OUTBOUND_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(max_outbound); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);
@ -843,10 +843,10 @@ impl P2PSetup {
// Setup values for modal. // Setup values for modal.
self.min_outbound_count = min_outbound; self.min_outbound_count = min_outbound;
// Show maximum number of outbound peers setup modal. // Show maximum number of outbound peers setup modal.
let min_outbound = Modal::new(Self::MIN_OUTBOUND_MODAL) Modal::new(Self::MIN_OUTBOUND_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(min_outbound); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);

View file

@ -115,10 +115,10 @@ impl PoolSetup {
// Setup values for modal. // Setup values for modal.
self.fee_base_edit = fee; self.fee_base_edit = fee;
// Show fee setup modal. // Show fee setup modal.
let fee_modal = Modal::new(Self::FEE_BASE_MODAL) Modal::new(Self::FEE_BASE_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(fee_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);
@ -200,10 +200,10 @@ impl PoolSetup {
// Setup values for modal. // Setup values for modal.
self.reorg_period_edit = period; self.reorg_period_edit = period;
// Show reorg period setup modal. // Show reorg period setup modal.
let reorg_modal = Modal::new(Self::REORG_PERIOD_MODAL) Modal::new(Self::REORG_PERIOD_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(reorg_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);
@ -285,10 +285,10 @@ impl PoolSetup {
// Setup values for modal. // Setup values for modal.
self.pool_size_edit = size; self.pool_size_edit = size;
// Show pool size setup modal. // Show pool size setup modal.
let size_modal = Modal::new(Self::POOL_SIZE_MODAL) Modal::new(Self::POOL_SIZE_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(size_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);
@ -370,10 +370,10 @@ impl PoolSetup {
// Setup values for modal. // Setup values for modal.
self.stempool_size_edit = size; self.stempool_size_edit = size;
// Show stempool size setup modal. // Show stempool size setup modal.
let stem_modal = Modal::new(Self::STEMPOOL_SIZE_MODAL) Modal::new(Self::STEMPOOL_SIZE_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(stem_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);
@ -455,10 +455,10 @@ impl PoolSetup {
// Setup values for modal. // Setup values for modal.
self.max_weight_edit = weight; self.max_weight_edit = weight;
// Show total tx weight setup modal. // Show total tx weight setup modal.
let weight_modal = Modal::new(Self::MAX_WEIGHT_MODAL) Modal::new(Self::MAX_WEIGHT_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(weight_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);

View file

@ -163,10 +163,10 @@ impl StratumSetup {
self.stratum_port_edit = port; self.stratum_port_edit = port;
self.stratum_port_available_edit = self.is_port_available; self.stratum_port_available_edit = self.is_port_available;
// Show stratum port modal. // Show stratum port modal.
let port_modal = Modal::new(Self::STRATUM_PORT_MODAL) Modal::new(Self::STRATUM_PORT_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(port_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(12.0); ui.add_space(12.0);
@ -270,10 +270,10 @@ impl StratumSetup {
self.attempt_time_edit = time; self.attempt_time_edit = time;
// Show attempt time modal. // Show attempt time modal.
let time_modal = Modal::new(Self::ATTEMPT_TIME_MODAL) Modal::new(Self::ATTEMPT_TIME_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(time_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);
@ -293,7 +293,7 @@ impl StratumSetup {
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
// Draw stratum port text edit. // Draw attempt time text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.attempt_time_edit) let text_edit_resp = egui::TextEdit::singleline(&mut self.attempt_time_edit)
.id(Id::from(modal.id)) .id(Id::from(modal.id))
.font(TextStyle::Heading) .font(TextStyle::Heading)
@ -360,11 +360,11 @@ impl StratumSetup {
// Setup values for modal. // Setup values for modal.
self.min_share_diff_edit = diff; self.min_share_diff_edit = diff;
// Show attempt time modal. // Show share difficulty setup modal.
let diff_modal = Modal::new(Self::MIN_SHARE_DIFF_MODAL) Modal::new(Self::MIN_SHARE_DIFF_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("network_settings.change_value")); .title(t!("network_settings.change_value"))
Modal::show(diff_modal); .show();
cb.show_keyboard(); cb.show_keyboard();
}); });
ui.add_space(6.0); ui.add_space(6.0);
@ -379,7 +379,7 @@ impl StratumSetup {
.color(Colors::GRAY)); .color(Colors::GRAY));
ui.add_space(8.0); ui.add_space(8.0);
// Draw stratum port text edit. // Draw share difficulty text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.min_share_diff_edit) let text_edit_resp = egui::TextEdit::singleline(&mut self.min_share_diff_edit)
.id(Id::from(modal.id)) .id(Id::from(modal.id))
.font(TextStyle::Heading) .font(TextStyle::Heading)

View file

@ -142,8 +142,9 @@ impl Root {
/// Show exit confirmation modal. /// Show exit confirmation modal.
pub fn show_exit_modal() { pub fn show_exit_modal() {
let exit_modal = Modal::new(Self::EXIT_MODAL_ID).title(t!("modal.confirmation")); Modal::new(Self::EXIT_MODAL_ID)
Modal::show(exit_modal); .title(t!("modal.confirmation"))
.show();
} }
/// Draw exit confirmation modal content. /// Draw exit confirmation modal content.

View file

@ -66,11 +66,11 @@ impl Default for WalletCreation {
impl WalletCreation { impl WalletCreation {
/// Wallet name/password input modal identifier. /// Wallet name/password input modal identifier.
pub const MODAL_ID: &'static str = "create_wallet_modal"; pub const NAME_PASS_MODAL: &'static str = "name_pass_modal";
pub fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) { pub fn ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) {
// Show wallet creation step description and confirmation panel. // Show wallet creation step description and confirmation bottom panel.
if self.can_go_back() { if self.step.is_some() {
egui::TopBottomPanel::bottom("wallet_creation_step_panel") egui::TopBottomPanel::bottom("wallet_creation_step_panel")
.frame(egui::Frame { .frame(egui::Frame {
stroke: View::DEFAULT_STROKE, stroke: View::DEFAULT_STROKE,
@ -85,36 +85,55 @@ impl WalletCreation {
.show_inside(ui, |ui| { .show_inside(ui, |ui| {
ui.vertical_centered(|ui| { ui.vertical_centered(|ui| {
if let Some(step) = &self.step { if let Some(step) = &self.step {
// Setup step description text. // Setup step description text and availability.
let step_text = match step { let (step_text, step_available) = match step {
Step::EnterMnemonic => { Step::EnterMnemonic => {
let mode = &self.mnemonic_setup.mnemonic.mode; let mode = &self.mnemonic_setup.mnemonic.mode;
let size_value = self.mnemonic_setup.mnemonic.size.value(); let size_value = self.mnemonic_setup.mnemonic.size.value();
if mode == &PhraseMode::Generate { let text = if mode == &PhraseMode::Generate {
t!("wallets.create_phrase_desc", "number" => size_value) t!("wallets.create_phrase_desc", "number" => size_value)
} else { } else {
t!("wallets.restore_phrase_desc", "number" => size_value) t!("wallets.restore_phrase_desc", "number" => size_value)
} };
let available = !self
.mnemonic_setup
.mnemonic
.words
.contains(&"".to_string());
(text, available)
} }
Step::ConfirmMnemonic => t!("wallets.conf_phrase_desc"), Step::ConfirmMnemonic => {
Step::SetupConnection => t!("wallets.setup_conn_desc") let text = t!("wallets.restore_phrase_desc");
let available = !self
.mnemonic_setup
.mnemonic
.confirm_words
.contains(&"".to_string());
(text, available)
},
Step::SetupConnection => (t!("wallets.setup_conn_desc"), true)
}; };
// Show step description. // Show step description.
ui.label(RichText::new(step_text).size(16.0).color(Colors::GRAY)); ui.label(RichText::new(step_text).size(16.0).color(Colors::GRAY));
ui.add_space(4.0);
// Setup next step button text. // Show next step button if there are no empty words.
let (next_text, color) = if step == &Step::SetupConnection {
(format!("{} {}", CHECK, t!("complete")), Colors::GOLD) if step_available {
} else { // Setup button text.
let text = format!("{} {}", SHARE_FAT, t!("continue")); let (next_text, color) = if step == &Step::SetupConnection {
(text, Colors::WHITE) (format!("{} {}", CHECK, t!("complete")), Colors::GOLD)
}; } else {
// Show next step button. let text = format!("{} {}", SHARE_FAT, t!("continue"));
View::button(ui, next_text.to_uppercase(), color, || { (text, Colors::WHITE)
self.forward(); };
});
ui.add_space(4.0); ui.add_space(4.0);
// Show button.
View::button(ui, next_text.to_uppercase(), color, || {
self.forward();
});
ui.add_space(4.0);
}
} }
}); });
}); });
@ -165,16 +184,18 @@ impl WalletCreation {
ui.add_space(8.0); ui.add_space(8.0);
let add_text = format!("{} {}", PLUS_CIRCLE, t!("wallets.add")); let add_text = format!("{} {}", PLUS_CIRCLE, t!("wallets.add"));
View::button(ui, add_text, Colors::BUTTON, || { View::button(ui, add_text, Colors::BUTTON, || {
Self::show_modal(); self.show_name_pass_modal();
}); });
}); });
} }
Some(step) => { Some(step) => {
match step { match step {
Step::EnterMnemonic => { Step::EnterMnemonic => {
self.mnemonic_setup.enter_ui(ui, cb); self.mnemonic_setup.ui(ui);
}
Step::ConfirmMnemonic => {
self.mnemonic_setup.confirm_ui(ui);
} }
Step::ConfirmMnemonic => {}
Step::SetupConnection => {} Step::SetupConnection => {}
} }
} }
@ -230,10 +251,17 @@ impl WalletCreation {
} }
/// Start wallet creation from showing [`Modal`] to enter name and password. /// Start wallet creation from showing [`Modal`] to enter name and password.
pub fn show_modal() { pub fn show_name_pass_modal(&mut self) {
Modal::show(Modal::new(Self::MODAL_ID) // Reset modal values.
self.hide_pass = false;
self.modal_just_opened = true;
self.name_edit = "".to_string();
self.pass_edit = "".to_string();
// Show modal.
Modal::new(Self::NAME_PASS_MODAL)
.position(ModalPosition::CenterTop) .position(ModalPosition::CenterTop)
.title(t!("wallets.add"))); .title(t!("wallets.add"))
.show();
} }
/// Draw wallet creation [`Modal`] content. /// Draw wallet creation [`Modal`] content.
@ -332,11 +360,6 @@ impl WalletCreation {
ui.columns(2, |columns| { ui.columns(2, |columns| {
columns[0].vertical_centered_justified(|ui| { columns[0].vertical_centered_justified(|ui| {
View::button(ui, t!("modal.cancel"), Colors::WHITE, || { View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
// Clear values.
self.hide_pass = false;
self.modal_just_opened = true;
self.name_edit = "".to_string();
self.pass_edit = "".to_string();
// Close modal. // Close modal.
cb.hide_keyboard(); cb.hide_keyboard();
modal.close(); modal.close();

View file

@ -12,35 +12,46 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use egui::{RichText, ScrollArea}; use egui::{Id, RichText, ScrollArea, TextStyle, Widget};
use crate::gui::Colors; use crate::gui::Colors;
use crate::gui::icons::PENCIL; use crate::gui::icons::PENCIL;
use crate::gui::platform::PlatformCallbacks; use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Root, View}; use crate::gui::views::{Modal, ModalPosition, Root, View};
use crate::gui::views::wallets::creation::types::{Mnemonic, PhraseMode, PhraseSize}; use crate::gui::views::wallets::creation::types::{Mnemonic, PhraseMode, PhraseSize};
/// Mnemonic phrase setup content. /// Mnemonic phrase setup content.
pub struct MnemonicSetup { pub struct MnemonicSetup {
/// Current mnemonic phrase. /// Current mnemonic phrase.
pub(crate) mnemonic: Mnemonic, pub(crate) mnemonic: Mnemonic,
/// Word value for [`Modal`].
/// Current word number to edit at [`Modal`].
word_num_edit: usize,
/// Entered word value for [`Modal`].
word_edit: String, word_edit: String,
/// Flag to check if entered word is valid.
valid_word_edit: bool
} }
impl Default for MnemonicSetup { impl Default for MnemonicSetup {
fn default() -> Self { fn default() -> Self {
Self { Self {
mnemonic: Mnemonic::default(), mnemonic: Mnemonic::default(),
word_num_edit: 0,
word_edit: "".to_string(), word_edit: "".to_string(),
valid_word_edit: true
} }
} }
} }
impl MnemonicSetup { impl MnemonicSetup {
pub fn enter_ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) { /// Identifier for word input [`Modal`].
pub const WORD_INPUT_MODAL: &'static str = "word_input_modal";
/// Draw content for input step.
pub fn ui(&mut self, ui: &mut egui::Ui) {
ScrollArea::vertical() ScrollArea::vertical()
.id_source("mnemonic_words_list") .id_source("input_mnemonic_words_list")
.auto_shrink([false; 2]) .auto_shrink([false; 2])
.show(ui, |ui| { .show(ui, |ui| {
ui.add_space(10.0); ui.add_space(10.0);
@ -53,7 +64,23 @@ impl MnemonicSetup {
ui.add_space(6.0); ui.add_space(6.0);
// Show words setup. // Show words setup.
self.word_list_ui(ui); self.word_list_ui(ui, self.mnemonic.mode == PhraseMode::Import);
});
}
/// Draw content for confirmation step.
pub fn confirm_ui(&mut self, ui: &mut egui::Ui) {
ui.add_space(4.0);
ui.vertical_centered(|ui| {
ui.label(RichText::new(t!("wallets.saved_phrase")).size(16.0).color(Colors::GRAY));
});
ui.add_space(6.0);
ScrollArea::vertical()
.id_source("confirm_mnemonic_words_list")
.auto_shrink([false; 2])
.show(ui, |ui| {
// Show words setup.
self.word_list_ui(ui, true);
}); });
} }
@ -89,125 +116,103 @@ impl MnemonicSetup {
// Show mnemonic phrase size setup. // Show mnemonic phrase size setup.
let mut size = self.mnemonic.size.clone(); let mut size = self.mnemonic.size.clone();
ui.columns(5, |columns| { ui.columns(5, |columns| {
columns[0].vertical_centered(|ui| { for (index, word) in PhraseSize::VALUES.iter().enumerate() {
let words12 = PhraseSize::Words12; columns[index].vertical_centered(|ui| {
let text = words12.value().to_string(); let text = word.value().to_string();
View::radio_value(ui, &mut size, words12, text); View::radio_value(ui, &mut size, word.clone(), text);
}); });
columns[1].vertical_centered(|ui| { }
let words15 = PhraseSize::Words15;
let text = words15.value().to_string();
View::radio_value(ui, &mut size, words15, text);
});
columns[2].vertical_centered(|ui| {
let words18 = PhraseSize::Words18;
let text = words18.value().to_string();
View::radio_value(ui, &mut size, words18, text);
});
columns[3].vertical_centered(|ui| {
let words21 = PhraseSize::Words21;
let text = words21.value().to_string();
View::radio_value(ui, &mut size, words21, text);
});
columns[4].vertical_centered(|ui| {
let words24 = PhraseSize::Words24;
let text = words24.value().to_string();
View::radio_value(ui, &mut size, words24, text);
});
}); });
if size != self.mnemonic.size { if size != self.mnemonic.size {
self.mnemonic.set_size(size); self.mnemonic.set_size(size);
} }
} }
/// Calculate word list columns count based on available ui width. /// Draw list of words for mnemonic phrase.
fn calc_columns_count(ui: &mut egui::Ui) -> usize { fn word_list_ui(&mut self, ui: &mut egui::Ui, edit_words: bool) {
let w = ui.available_width(); ui.add_space(6.0);
let min_panel_w = Root::SIDE_PANEL_MIN_WIDTH - 12.0;
let double_min_panel_w = min_panel_w * 2.0;
if w >= min_panel_w * 1.5 && w < double_min_panel_w {
3
} else if w >= double_min_panel_w {
4
} else {
2
}
}
/// Draw word list for mnemonic phrase.
fn word_list_ui(&self, ui: &mut egui::Ui) {
ui.scope(|ui| { ui.scope(|ui| {
// Setup spacing between columns. // Setup spacing between columns.
ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 6.0); ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 6.0);
if self.mnemonic.mode == PhraseMode::Generate { // Select list of words based on current mode and edit flag.
ui.add_space(6.0) let words = match self.mnemonic.mode {
} PhraseMode::Generate => {
if edit_words {
self.mnemonic.confirm_words.clone()
} else {
self.mnemonic.words.clone()
}
}
PhraseMode::Import => self.mnemonic.words.clone()
};
let mut word_number = 0; let mut word_number = 0;
let cols = Self::calc_columns_count(ui); let cols = list_columns_count(ui);
let _ = self.mnemonic.words.chunks(cols).map(|chunk| { let _ = words.chunks(cols).map(|chunk| {
let size = chunk.len(); let size = chunk.len();
word_number += 1; word_number += 1;
if size > 1 { if size > 1 {
ui.columns(cols, |columns| { ui.columns(cols, |columns| {
columns[0].horizontal(|ui| { columns[0].horizontal(|ui| {
self.word_item_ui(ui, word_number, chunk, 0); let word = chunk.get(0).unwrap();
self.word_item_ui(ui, word_number, word, edit_words);
}); });
columns[1].horizontal(|ui| { columns[1].horizontal(|ui| {
word_number += 1; word_number += 1;
self.word_item_ui(ui, word_number, chunk, 1); let word = chunk.get(1).unwrap();
self.word_item_ui(ui, word_number, word, edit_words);
}); });
if size > 2 { if size > 2 {
columns[2].horizontal(|ui| { columns[2].horizontal(|ui| {
word_number += 1; word_number += 1;
self.word_item_ui(ui, word_number, chunk, 2); let word = chunk.get(2).unwrap();
self.word_item_ui(ui, word_number, word, edit_words);
}); });
} }
if size > 3 { if size > 3 {
columns[3].horizontal(|ui| { columns[3].horizontal(|ui| {
word_number += 1; word_number += 1;
self.word_item_ui(ui, word_number, chunk, 3); let word = chunk.get(3).unwrap();
self.word_item_ui(ui, word_number, word, edit_words);
}); });
} }
}); });
} else { } else {
ui.columns(cols, |columns| { ui.columns(cols, |columns| {
columns[0].horizontal(|ui| { columns[0].horizontal(|ui| {
self.word_item_ui(ui, word_number, chunk, 0); let word = chunk.get(0).unwrap();
self.word_item_ui(ui, word_number, word, edit_words);
}); });
}); });
ui.add_space(12.0);
} }
}).collect::<Vec<_>>(); }).collect::<Vec<_>>();
}); });
ui.add_space(6.0);
} }
/// Draw word item at given index from provided chunk. /// Draw word list item for current mode.
fn word_item_ui(&self, fn word_item_ui(&mut self, ui: &mut egui::Ui, word_number: usize, word: &String, edit: bool) {
ui: &mut egui::Ui, if edit {
word_number: usize, ui.add_space(6.0);
chunk: &[String], View::button(ui, PENCIL.to_string(), Colors::BUTTON, || {
index: usize) { // Setup modal values.
match self.mnemonic.mode { self.word_num_edit = word_number;
PhraseMode::Generate => { self.word_edit = word.clone();
ui.add_space(12.0); self.valid_word_edit = true;
let word = chunk.get(index).unwrap(); // Show word edit modal.
let text = format!("#{} {}", word_number, word); Modal::new(MnemonicSetup::WORD_INPUT_MODAL)
ui.label(RichText::new(text).size(17.0).color(Colors::BLACK)); .position(ModalPosition::CenterTop)
} .title(t!("wallets.saved_phrase"))
PhraseMode::Import => { .show();
let mut size = ui.available_size(); });
size.x = 90.0; ui.label(RichText::new(format!("#{} {}", word_number, word))
ui.allocate_ui(size, |ui| { .size(17.0)
View::button(ui, PENCIL.to_string(), Colors::BUTTON, || { .color(Colors::BLACK));
//TODO: open modal } else {
}); ui.add_space(12.0);
}); let text = format!("#{} {}", word_number, word);
ui.label(RichText::new(format!("#{}", word_number)) ui.label(RichText::new(text).size(17.0).color(Colors::BLACK));
.size(17.0)
.color(Colors::BLACK));
}
} }
} }
@ -215,4 +220,95 @@ impl MnemonicSetup {
pub fn reset(&mut self) { pub fn reset(&mut self) {
self.mnemonic = Mnemonic::default(); self.mnemonic = Mnemonic::default();
} }
/// Show word input [`Modal`] content.
pub fn 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.enter_word", "number" => self.word_num_edit))
.size(17.0)
.color(Colors::GRAY));
ui.add_space(8.0);
// Draw word value text edit.
let text_edit_resp = egui::TextEdit::singleline(&mut self.word_edit)
.id(Id::from(format!("{}{}", modal.id, 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();
}
// Show error when specified word is not valid.
if !self.valid_word_edit {
ui.add_space(12.0);
ui.label(RichText::new(t!("wallets.not_valid_word"))
.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, || {
// Close modal.
cb.hide_keyboard();
modal.close();
});
});
columns[1].vertical_centered_justified(|ui| {
View::button(ui, t!("continue"), Colors::WHITE, || {
// Check if word is valid.
let word_index = self.word_num_edit - 1;
if !self.mnemonic.is_valid_word(&self.word_edit, word_index) {
self.valid_word_edit = false;
return;
}
// Select list where to save word.
let words = match self.mnemonic.mode {
PhraseMode::Generate => &mut self.mnemonic.confirm_words,
PhraseMode::Import => &mut self.mnemonic.words
};
// Save word at list.
words.remove(word_index);
words.insert(word_index, self.word_edit.clone());
// Close modal or go to next word to edit.
let close_modal = words.len() == self.word_num_edit
|| !words.get(self.word_num_edit).unwrap().is_empty();
if close_modal {
cb.hide_keyboard();
modal.close();
} else {
self.word_num_edit += 1;
self.word_edit = "".to_string();
}
});
});
});
ui.add_space(6.0);
});
}
}
/// Calculate word list columns count based on available ui width.
fn list_columns_count(ui: &mut egui::Ui) -> usize {
let w = ui.available_width();
let min_panel_w = Root::SIDE_PANEL_MIN_WIDTH - 12.0;
let double_min_panel_w = min_panel_w * 2.0;
if w >= min_panel_w * 1.5 && w < double_min_panel_w {
3
} else if w >= double_min_panel_w {
4
} else {
2
}
} }

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use grin_keychain::mnemonic::from_entropy; use grin_keychain::mnemonic::{from_entropy, search};
use rand::{Rng, thread_rng}; use rand::{Rng, thread_rng};
/// Wallet creation step. /// Wallet creation step.
@ -20,7 +20,7 @@ use rand::{Rng, thread_rng};
pub enum Step { pub enum Step {
/// Mnemonic phrase input. /// Mnemonic phrase input.
EnterMnemonic, EnterMnemonic,
/// Mnemonic phrase confirmation for [`Mnemonic`]. /// Mnemonic phrase confirmation.
ConfirmMnemonic, ConfirmMnemonic,
/// Wallet connection setup. /// Wallet connection setup.
SetupConnection SetupConnection
@ -40,6 +40,14 @@ pub enum PhraseMode {
pub enum PhraseSize { Words12, Words15, Words18, Words21, Words24 } pub enum PhraseSize { Words12, Words15, Words18, Words21, Words24 }
impl PhraseSize { impl PhraseSize {
pub const VALUES: [PhraseSize; 5] = [
PhraseSize::Words12,
PhraseSize::Words15,
PhraseSize::Words18,
PhraseSize::Words21,
PhraseSize::Words24
];
/// Gen words count number. /// Gen words count number.
pub fn value(&self) -> usize { pub fn value(&self) -> usize {
match *self { match *self {
@ -69,8 +77,10 @@ pub struct Mnemonic {
pub(crate) mode: PhraseMode, pub(crate) mode: PhraseMode,
/// Size of phrase based on words count. /// Size of phrase based on words count.
pub(crate) size: PhraseSize, pub(crate) size: PhraseSize,
/// Words for phrase. /// Generated words.
pub(crate) words: Vec<String> pub(crate) words: Vec<String>,
/// Words to confirm the phrase.
pub(crate) confirm_words: Vec<String>
} }
impl Default for Mnemonic { impl Default for Mnemonic {
@ -78,7 +88,8 @@ impl Default for Mnemonic {
let size = PhraseSize::Words24; let size = PhraseSize::Words24;
let mode = PhraseMode::Generate; let mode = PhraseMode::Generate;
let words = Self::generate_words(&mode, &size); let words = Self::generate_words(&mode, &size);
Self { mode, size, words } let confirm_words = Self::empty_words(&size);
Self { mode, size, words, confirm_words }
} }
} }
@ -87,15 +98,28 @@ impl Mnemonic {
pub fn set_mode(&mut self, mode: PhraseMode) { pub fn set_mode(&mut self, mode: PhraseMode) {
self.mode = mode; self.mode = mode;
self.words = Self::generate_words(&self.mode, &self.size); self.words = Self::generate_words(&self.mode, &self.size);
self.confirm_words = Self::empty_words(&self.size);
} }
/// Change mnemonic phrase words [`PhraseSize`]. /// Change mnemonic phrase words [`PhraseSize`].
pub fn set_size(&mut self, size: PhraseSize) { pub fn set_size(&mut self, size: PhraseSize) {
self.size = size; self.size = size;
self.words = Self::generate_words(&self.mode, &self.size); self.words = Self::generate_words(&self.mode, &self.size);
self.confirm_words = Self::empty_words(&self.size);
} }
/// Setup words based on provided [`PhraseMode`] and [`PhraseSize`]. /// Check if provided word is in BIP39 format and equal to non-empty generated word at index.
pub fn is_valid_word(&self, word: &String, index: usize) -> bool {
let valid = search(word).is_ok();
let equal = if let Some(gen_word) = self.words.get(index) {
gen_word.is_empty() || gen_word == word
} else {
false
};
valid && equal
}
/// Generate list of words based on provided [`PhraseMode`] and [`PhraseSize`].
fn generate_words(mode: &PhraseMode, size: &PhraseSize) -> Vec<String> { fn generate_words(mode: &PhraseMode, size: &PhraseSize) -> Vec<String> {
match mode { match mode {
PhraseMode::Generate => { PhraseMode::Generate => {
@ -110,12 +134,17 @@ impl Mnemonic {
.collect::<Vec<String>>() .collect::<Vec<String>>()
}, },
PhraseMode::Import => { PhraseMode::Import => {
let mut words = Vec::with_capacity(size.value()); Self::empty_words(size)
for _ in 0..size.value() {
words.push("".to_string())
}
words
} }
} }
} }
/// Generate empty list of words based on provided [`PhraseSize`].
fn empty_words(size: &PhraseSize) -> Vec<String> {
let mut words = Vec::with_capacity(size.value());
for _ in 0..size.value() {
words.push("".to_string())
}
words
}
} }

View file

@ -20,7 +20,7 @@ use crate::gui::Colors;
use crate::gui::icons::{ARROW_LEFT, GEAR, GLOBE, PLUS}; use crate::gui::icons::{ARROW_LEFT, GEAR, GLOBE, PLUS};
use crate::gui::platform::PlatformCallbacks; use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, ModalContainer, Root, TitlePanel, TitleType, View}; use crate::gui::views::{Modal, ModalContainer, Root, TitlePanel, TitleType, View};
use crate::gui::views::wallets::creation::WalletCreation; use crate::gui::views::wallets::creation::{MnemonicSetup, WalletCreation};
use crate::gui::views::wallets::wallet::WalletContent; use crate::gui::views::wallets::wallet::WalletContent;
/// Wallets content. /// Wallets content.
@ -45,7 +45,8 @@ impl Default for Wallets {
item_content: None, item_content: None,
creation_content: WalletCreation::default(), creation_content: WalletCreation::default(),
modal_ids: vec![ modal_ids: vec![
WalletCreation::MODAL_ID WalletCreation::NAME_PASS_MODAL,
MnemonicSetup::WORD_INPUT_MODAL
] ]
} }
} }
@ -63,7 +64,12 @@ impl Wallets {
if self.can_draw_modal() { if self.can_draw_modal() {
Modal::ui(ui, |ui, modal| { Modal::ui(ui, |ui, modal| {
match modal.id { match modal.id {
WalletCreation::MODAL_ID => self.creation_content.modal_ui(ui, modal, cb), WalletCreation::NAME_PASS_MODAL => {
self.creation_content.modal_ui(ui, modal, cb);
},
MnemonicSetup::WORD_INPUT_MODAL => {
self.creation_content.mnemonic_setup.modal_ui(ui, modal, cb);
}
_ => {} _ => {}
} }
}); });
@ -72,9 +78,9 @@ impl Wallets {
// Show title panel. // Show title panel.
self.title_ui(ui, frame); self.title_ui(ui, frame);
// Show wallet content.
let is_wallet_panel_open = Self::is_dual_panel_mode(ui, frame) || self.list.is_empty(); let is_wallet_panel_open = Self::is_dual_panel_mode(ui, frame) || self.list.is_empty();
let wallet_panel_width = self.wallet_panel_width(ui, frame); let wallet_panel_width = self.wallet_panel_width(ui, frame);
// Show wallet content.
egui::SidePanel::right("wallet_panel") egui::SidePanel::right("wallet_panel")
.resizable(false) .resizable(false)
.min_width(wallet_panel_width) .min_width(wallet_panel_width)
@ -105,7 +111,7 @@ impl Wallets {
}); });
// Show wallet creation button if wallet panel is not open. // Show wallet creation button if wallet panel is not open.
if !is_wallet_panel_open { if !is_wallet_panel_open {
self.add_wallet_btn_ui(ui); self.create_wallet_btn_ui(ui);
} }
} }
} }
@ -114,7 +120,7 @@ impl Wallets {
fn title_ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) { fn title_ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) {
// Setup title text. // Setup title text.
let title_text = if self.creation_content.can_go_back() { let title_text = if self.creation_content.can_go_back() {
t!("wallets.new") t!("wallets.add")
} else { } else {
t!("wallets.title") t!("wallets.title")
}; };
@ -178,7 +184,7 @@ impl Wallets {
} }
/// Draw floating button to create the wallet. /// Draw floating button to create the wallet.
fn add_wallet_btn_ui(&self, ui: &mut egui::Ui) { fn create_wallet_btn_ui(&mut self, ui: &mut egui::Ui) {
egui::Window::new("create_wallet_button") egui::Window::new("create_wallet_button")
.title_bar(false) .title_bar(false)
.resizable(false) .resizable(false)
@ -187,7 +193,7 @@ impl Wallets {
.frame(egui::Frame::default()) .frame(egui::Frame::default())
.show(ui.ctx(), |ui| { .show(ui.ctx(), |ui| {
View::round_button(ui, PLUS, || { View::round_button(ui, PLUS, || {
WalletCreation::show_modal(); self.creation_content.show_name_pass_modal();
}); });
}); });
} }