wallets: fix wallet mutability, wallet connection change, optimize wallet lists for different chain types

This commit is contained in:
ardocrat 2023-08-11 17:29:25 +03:00
parent 3635b7abe6
commit d466cb1d9c
10 changed files with 133 additions and 60 deletions

View file

@ -14,6 +14,7 @@
use egui::{Align, Align2, Layout, Margin, RichText, Rounding, ScrollArea, TextStyle, Widget};
use egui_extras::{Size, StripBuilder};
use grin_core::global::ChainTypes;
use crate::AppConfig;
use crate::gui::Colors;
@ -95,10 +96,8 @@ impl WalletsContent {
// Draw modal content for current ui container.
self.current_modal_ui(ui, frame, cb);
let wallets = self.wallets.list();
let empty_list = wallets.is_empty();
// Setup wallet content flags.
let empty_list = self.wallets.is_current_list_empty();
let create_wallet = self.creation_content.can_go_back();
let show_wallet = self.wallets.is_selected_open();
@ -140,9 +139,15 @@ impl WalletsContent {
self.wallets.add(wallet);
});
} else {
for mut wallet in wallets.clone() {
let chain_type = AppConfig::chain_type();
let list = if chain_type == ChainTypes::Mainnet {
&mut self.wallets.main_list
} else {
&mut self.wallets.test_list
};
for wallet in list.iter_mut() {
// Show content for selected wallet.
if self.wallets.is_selected(wallet.config.id) {
if self.wallets.selected_id == Some(wallet.config.id) {
// Setup wallet content width.
let mut rect = ui.available_rect_before_wrap();
let mut width = ui.available_width();
@ -152,7 +157,7 @@ impl WalletsContent {
rect.set_width(width);
// Show wallet content.
ui.allocate_ui_at_rect(rect, |ui| {
self.wallet_content.ui(ui, frame, &mut wallet, cb);
self.wallet_content.ui(ui, frame, wallet, cb);
});
break;
}
@ -201,7 +206,7 @@ impl WalletsContent {
// Show list of wallets.
let scroll =
self.wallet_list_ui(ui, wallets, dual_panel, show_creation_button, cb);
self.wallet_list_ui(ui, dual_panel, show_creation_button, cb);
if show_creation_button {
// Setup right margin for button.
@ -296,7 +301,6 @@ impl WalletsContent {
/// Draw list of wallets. Returns `true` if scroller is showing.
fn wallet_list_ui(&mut self,
ui: &mut egui::Ui,
wallets: Vec<Wallet>,
dual_panel: bool,
show_creation_btn: bool,
cb: &dyn PlatformCallbacks) -> bool {
@ -324,9 +328,10 @@ impl WalletsContent {
rect.set_width(width);
ui.allocate_ui(rect.size(), |ui| {
for mut wallet in wallets {
let list = self.wallets.list().clone();
for wallet in &list {
// Draw wallet list item.
self.wallet_item_ui(ui, &mut wallet, cb);
self.wallet_item_ui(ui, wallet, cb);
ui.add_space(5.0);
}
// Add space for wallet creation button.
@ -345,10 +350,10 @@ impl WalletsContent {
/// Draw wallet list item.
fn wallet_item_ui(&mut self,
ui: &mut egui::Ui,
wallet: &mut Wallet,
wallet: &Wallet,
cb: &dyn PlatformCallbacks) {
let id = wallet.config.id;
let is_selected = self.wallets.is_selected(id);
let is_selected = self.wallets.selected_id == Some(id);
let is_current = wallet.is_open() && is_selected;
// Draw round background.

View file

@ -20,7 +20,7 @@ use crate::gui::icons::{GLOBE, GLOBE_SIMPLE};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, View};
use crate::gui::views::types::{ModalContainer, ModalPosition};
use crate::wallet::{ConnectionsConfig, ExternalConnection};
use crate::wallet::{ConnectionsConfig, ExternalConnection, Wallet};
use crate::wallet::types::ConnectionMethod;
/// Wallet node connection method setup content.
@ -77,12 +77,51 @@ impl ModalContainer for ConnectionSetup {
}
impl ConnectionSetup {
//TODO: Setup for provided wallet
// pub fn new() -> Self {
// Self { method: ConnectionMethod::Integrated }
// }
/// Draw wallet creation setup content.
pub fn create_ui(&mut self,
ui: &mut egui::Ui,
frame: &mut eframe::Frame,
cb: &dyn PlatformCallbacks) {
self.ui(ui, frame, cb);
}
pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) {
/// Draw existing wallet connection setup content.
pub fn wallet_ui(&mut self,
ui: &mut egui::Ui,
frame: &mut eframe::Frame,
wallet: &mut Wallet,
cb: &dyn PlatformCallbacks) {
// Setup connection value from provided wallet.
match wallet.config.ext_conn_id {
None => self.method = ConnectionMethod::Integrated,
Some(id) => self.method = ConnectionMethod::External(id)
}
// Draw setup content.
self.ui(ui, frame, cb);
// Setup wallet connection value after change.
match self.method {
ConnectionMethod::Integrated => {
if wallet.config.ext_conn_id.is_some() {
wallet.config.ext_conn_id = None;
wallet.config.save();
}
}
ConnectionMethod::External(id) => {
if wallet.config.ext_conn_id != Some(id) {
wallet.config.ext_conn_id = Some(id);
wallet.config.save();
}
}
}
}
/// Draw connection setup content.
fn ui(&mut self,
ui: &mut egui::Ui,
frame: &mut eframe::Frame,
cb: &dyn PlatformCallbacks) {
// Draw modal content for current ui container.
self.current_modal_ui(ui, frame, cb);

View file

@ -60,11 +60,12 @@ impl WalletContent {
.show_inside(ui, |ui| {
ui.vertical_centered(|ui| {
// Setup tabs width.
let mut rect = ui.available_rect_before_wrap();
let mut width = f32::min(ui.available_width(), Root::SIDE_PANEL_WIDTH * 2.0);
if width == 0.0 {
let available_width = ui.available_width();
if available_width == 0.0 {
return;
}
let mut rect = ui.available_rect_before_wrap();
let width = f32::min(available_width, Root::SIDE_PANEL_WIDTH * 2.0);
rect.set_width(width);
// Draw wallet tabs.
@ -90,11 +91,12 @@ impl WalletContent {
.show_inside(ui, |ui| {
ui.vertical_centered(|ui| {
// Setup tab content width.
let mut rect = ui.available_rect_before_wrap();
let mut width = f32::min(ui.available_width(), Root::SIDE_PANEL_WIDTH * 2.0);
if width == 0.0 {
let available_width = ui.available_width();
if available_width == 0.0 {
return;
}
let mut rect = ui.available_rect_before_wrap();
let width = f32::min(available_width, Root::SIDE_PANEL_WIDTH * 2.0);
rect.set_width(width);
// Draw current tab content.

View file

@ -30,7 +30,7 @@ impl WalletTab for WalletInfo {
fn ui(&mut self,
ui: &mut egui::Ui,
frame: &mut eframe::Frame,
wallet: &Wallet,
wallet: &mut Wallet,
cb: &dyn PlatformCallbacks) {
WalletContent::loading_ui(ui, frame, wallet);
}

View file

@ -25,6 +25,10 @@ impl WalletTab for WalletReceive {
WalletTabType::Receive
}
fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, wallet: &Wallet, cb: &dyn PlatformCallbacks) {
fn ui(&mut self,
ui: &mut egui::Ui,
frame: &mut eframe::Frame,
wallet: &mut Wallet,
cb: &dyn PlatformCallbacks) {
}
}

View file

@ -25,6 +25,10 @@ impl WalletTab for WalletSend {
WalletTabType::Send
}
fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, wallet: &Wallet, cb: &dyn PlatformCallbacks) {
fn ui(&mut self,
ui: &mut egui::Ui,
frame: &mut eframe::Frame,
wallet: &mut Wallet,
cb: &dyn PlatformCallbacks) {
}
}

View file

@ -13,12 +13,16 @@
// limitations under the License.
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::wallets::setup::ConnectionSetup;
use crate::gui::views::wallets::wallet::types::{WalletTab, WalletTabType};
use crate::wallet::Wallet;
/// Wallet settings tab content.
#[derive(Default)]
pub struct WalletSettings;
pub struct WalletSettings {
/// Connection setup content.
conn_setup: ConnectionSetup
}
impl WalletTab for WalletSettings {
fn get_type(&self) -> WalletTabType {
@ -28,7 +32,8 @@ impl WalletTab for WalletSettings {
fn ui(&mut self,
ui: &mut egui::Ui,
frame: &mut eframe::Frame,
wallet: &Wallet,
wallet: &mut Wallet,
cb: &dyn PlatformCallbacks) {
self.conn_setup.wallet_ui(ui, frame, wallet, cb);
}
}

View file

@ -21,7 +21,7 @@ pub trait WalletTab {
fn ui(&mut self,
ui: &mut egui::Ui,
frame: &mut eframe::Frame,
wallet: &Wallet,
wallet: &mut Wallet,
cb: &dyn PlatformCallbacks);
}

View file

@ -109,7 +109,7 @@ impl WalletConfig {
}
/// Save wallet config.
fn save(&self) {
pub fn save(&self) {
let config_path = Self::get_config_file_path(self.chain_type, self.id);
Settings::write_to_file(self, config_path);
}

View file

@ -20,56 +20,70 @@ use crate::wallet::{Wallet, WalletConfig};
/// Wrapper for [`Wallet`] list.
pub struct WalletList {
/// List of wallets.
list: Vec<Wallet>,
/// List of wallets for [`ChainTypes::Mainnet`].
pub main_list: Vec<Wallet>,
/// List of wallets for [`ChainTypes::Testnet`].
pub test_list: Vec<Wallet>,
/// Selected [`Wallet`] identifier.
selected_id: Option<i64>,
pub selected_id: Option<i64>,
}
impl Default for WalletList {
fn default() -> Self {
Self {
list: Self::init(),
selected_id: None
}
let (main_list, test_list) = Self::init();
Self { main_list, test_list, selected_id: None }
}
}
impl WalletList {
/// Initialize [`Wallet`] list from base directory.
fn init() -> Vec<Wallet> {
let mut wallets = Vec::new();
/// Initialize [`Wallet`] lists for [`ChainTypes::Mainnet`] and [`ChainTypes::Testnet`].
fn init() -> (Vec<Wallet>, Vec<Wallet>) {
let mut main_wallets = Vec::new();
let mut test_wallets = Vec::new();
let chain_types = vec![ChainTypes::Mainnet, ChainTypes::Testnet];
for chain in chain_types {
// initialize wallets from base directory.
let wallets_dir = WalletConfig::get_base_path(chain);
// Load wallets from base directory.
for dir in wallets_dir.read_dir().unwrap() {
let wallet_dir = dir.unwrap().path();
if wallet_dir.is_dir() {
let wallet = Wallet::init(wallet_dir);
if let Some(w) = wallet {
wallets.push(w);
if chain == ChainTypes::Testnet {
test_wallets.push(w);
} else if chain == ChainTypes::Mainnet {
main_wallets.push(w);
}
}
}
}
}
// Sort wallets by id.
wallets.sort_by_key(|w| w.config.id);
wallets
main_wallets.sort_by_key(|w| w.config.id);
test_wallets.sort_by_key(|w| w.config.id);
(main_wallets, test_wallets)
}
/// Get wallet list for current [`ChainTypes`].
pub fn list(&self) -> Vec<Wallet> {
/// Get [`Wallet`] list for current [`ChainTypes`].
pub fn list(&self) -> &Vec<Wallet> {
let chain_type = AppConfig::chain_type();
self.list.iter().cloned()
.filter(|w| w.config.chain_type == chain_type)
.collect::<Vec<Wallet>>()
if chain_type == ChainTypes::Mainnet {
&self.main_list
} else {
&self.test_list
}
}
/// Add created [`Wallet`] to the list.
pub fn add(&mut self, wallet: Wallet) {
self.selected_id = Some(wallet.config.id);
self.list.insert(0, wallet);
let chain_type = AppConfig::chain_type();
let list = if chain_type == ChainTypes::Mainnet {
&mut self.main_list
} else {
&mut self.test_list
};
list.insert(0, wallet);
}
/// Select [`Wallet`] with provided identifier.
@ -79,7 +93,7 @@ impl WalletList {
/// Get selected [`Wallet`] name.
pub fn selected_name(&self) -> String {
for w in &self.list {
for w in self.list() {
if Some(w.config.id) == self.selected_id {
return w.config.name.to_owned()
}
@ -87,14 +101,9 @@ impl WalletList {
t!("wallets.unlocked")
}
/// Check if [`Wallet`] is selected for provided identifier.
pub fn is_selected(&self, id: i64) -> bool {
return Some(id) == self.selected_id;
}
/// Check if selected [`Wallet`] is open.
pub fn is_selected_open(&self) -> bool {
for w in &self.list {
for w in self.list() {
if Some(w.config.id) == self.selected_id {
return w.is_open()
}
@ -102,9 +111,14 @@ impl WalletList {
false
}
/// Check if current list is empty.
pub fn is_current_list_empty(&self) -> bool {
self.list().is_empty()
}
/// Open selected [`Wallet`].
pub fn open_selected(&mut self, password: String) -> Result<(), Error> {
for w in self.list.iter_mut() {
pub fn open_selected(&self, password: String) -> Result<(), Error> {
for w in self.list() {
if Some(w.config.id) == self.selected_id {
return w.open(password.clone());
}