wallets: fix wallet mutability, wallet connection change, optimize wallet lists for different chain types
This commit is contained in:
parent
3635b7abe6
commit
d466cb1d9c
10 changed files with 133 additions and 60 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue