2023-04-27 01:28:55 +03:00
|
|
|
// Copyright 2023 The Grim Developers
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2023-08-09 04:19:15 +03:00
|
|
|
use std::time::Duration;
|
|
|
|
|
2023-08-13 21:09:04 +03:00
|
|
|
use egui::{Margin, RichText};
|
2023-08-09 20:11:44 +03:00
|
|
|
use grin_chain::SyncStatus;
|
2023-07-29 00:17:54 +03:00
|
|
|
|
2023-08-09 20:11:44 +03:00
|
|
|
use crate::AppConfig;
|
2023-08-03 23:49:11 +03:00
|
|
|
use crate::gui::Colors;
|
2023-08-09 20:11:44 +03:00
|
|
|
use crate::gui::icons::{DOWNLOAD, GEAR_FINE, POWER, REPEAT, UPLOAD, WALLET};
|
2023-04-27 01:28:55 +03:00
|
|
|
use crate::gui::platform::PlatformCallbacks;
|
2023-08-09 02:22:16 +03:00
|
|
|
use crate::gui::views::{Root, View};
|
2023-08-03 23:49:11 +03:00
|
|
|
use crate::gui::views::wallets::{WalletInfo, WalletReceive, WalletSend, WalletSettings};
|
|
|
|
use crate::gui::views::wallets::types::{WalletTab, WalletTabType};
|
|
|
|
use crate::node::Node;
|
2023-08-09 02:22:16 +03:00
|
|
|
use crate::wallet::Wallet;
|
2023-04-27 01:28:55 +03:00
|
|
|
|
2023-08-03 04:11:25 +03:00
|
|
|
/// Selected and opened wallet content.
|
2023-07-21 04:17:57 +03:00
|
|
|
pub struct WalletContent {
|
2023-08-03 23:49:11 +03:00
|
|
|
/// Current tab content to show.
|
2023-08-13 21:09:04 +03:00
|
|
|
pub current_tab: Box<dyn WalletTab>,
|
2023-07-13 03:54:27 +03:00
|
|
|
}
|
2023-04-27 01:28:55 +03:00
|
|
|
|
2023-07-29 00:17:54 +03:00
|
|
|
impl Default for WalletContent {
|
|
|
|
fn default() -> Self {
|
2023-08-03 23:49:11 +03:00
|
|
|
Self { current_tab: Box::new(WalletInfo::default()) }
|
2023-04-27 01:28:55 +03:00
|
|
|
}
|
2023-07-13 03:54:27 +03:00
|
|
|
}
|
2023-04-27 01:28:55 +03:00
|
|
|
|
2023-07-21 04:17:57 +03:00
|
|
|
impl WalletContent {
|
2023-07-29 00:17:54 +03:00
|
|
|
pub fn ui(&mut self,
|
|
|
|
ui: &mut egui::Ui,
|
|
|
|
frame: &mut eframe::Frame,
|
2023-08-03 00:00:23 +03:00
|
|
|
wallet: &mut Wallet,
|
2023-07-29 00:17:54 +03:00
|
|
|
cb: &dyn PlatformCallbacks) {
|
2023-08-11 04:36:15 +03:00
|
|
|
// Show wallet tabs panel.
|
2023-08-03 23:49:11 +03:00
|
|
|
egui::TopBottomPanel::bottom("wallet_tabs")
|
|
|
|
.frame(egui::Frame {
|
|
|
|
fill: Colors::FILL,
|
|
|
|
inner_margin: Margin {
|
|
|
|
left: View::far_left_inset_margin(ui) + 4.0,
|
|
|
|
right: View::get_right_inset() + 4.0,
|
|
|
|
top: 4.0,
|
|
|
|
bottom: View::get_bottom_inset() + 4.0,
|
|
|
|
},
|
|
|
|
..Default::default()
|
|
|
|
})
|
2023-08-13 21:09:04 +03:00
|
|
|
.show_animated_inside(ui, !Self::block_navigation_on_sync(wallet), |ui| {
|
2023-08-11 04:36:15 +03:00
|
|
|
ui.vertical_centered(|ui| {
|
|
|
|
// Draw wallet tabs.
|
2023-08-15 21:20:20 +03:00
|
|
|
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
|
2023-08-11 04:36:15 +03:00
|
|
|
self.tabs_ui(ui);
|
|
|
|
});
|
|
|
|
});
|
2023-08-03 23:49:11 +03:00
|
|
|
});
|
|
|
|
|
2023-08-11 04:36:15 +03:00
|
|
|
// Show tab content panel.
|
2023-06-02 02:05:34 +03:00
|
|
|
egui::CentralPanel::default()
|
2023-07-13 03:54:27 +03:00
|
|
|
.frame(egui::Frame {
|
2023-06-02 02:05:34 +03:00
|
|
|
stroke: View::DEFAULT_STROKE,
|
2023-07-21 04:17:57 +03:00
|
|
|
fill: Colors::WHITE,
|
|
|
|
inner_margin: Margin {
|
|
|
|
left: View::far_left_inset_margin(ui) + 4.0,
|
2023-07-29 00:17:54 +03:00
|
|
|
right: View::get_right_inset() + 4.0,
|
2023-08-13 21:09:04 +03:00
|
|
|
top: 3.0,
|
2023-07-21 04:17:57 +03:00
|
|
|
bottom: 4.0,
|
|
|
|
},
|
2023-06-02 02:05:34 +03:00
|
|
|
..Default::default()
|
|
|
|
})
|
|
|
|
.show_inside(ui, |ui| {
|
2023-08-13 21:09:04 +03:00
|
|
|
self.current_tab.ui(ui, frame, wallet, cb);
|
2023-06-02 02:05:34 +03:00
|
|
|
});
|
2023-08-03 23:49:11 +03:00
|
|
|
|
2023-08-13 21:09:04 +03:00
|
|
|
// Refresh content after 1 second for synced wallet.
|
2023-08-11 01:20:41 +03:00
|
|
|
if wallet.get_data().is_some() {
|
2023-08-09 04:19:15 +03:00
|
|
|
ui.ctx().request_repaint_after(Duration::from_millis(1000));
|
2023-08-03 23:49:11 +03:00
|
|
|
} else {
|
|
|
|
ui.ctx().request_repaint();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Draw tab buttons in the bottom of the screen.
|
|
|
|
fn tabs_ui(&mut self, ui: &mut egui::Ui) {
|
|
|
|
ui.scope(|ui| {
|
|
|
|
// Setup spacing between tabs.
|
|
|
|
ui.style_mut().spacing.item_spacing = egui::vec2(4.0, 0.0);
|
|
|
|
// Setup vertical padding inside tab button.
|
|
|
|
ui.style_mut().spacing.button_padding = egui::vec2(0.0, 8.0);
|
|
|
|
|
|
|
|
// Draw tab buttons.
|
|
|
|
let current_type = self.current_tab.get_type();
|
|
|
|
ui.columns(4, |columns| {
|
|
|
|
columns[0].vertical_centered_justified(|ui| {
|
|
|
|
View::tab_button(ui, WALLET, current_type == WalletTabType::Info, || {
|
|
|
|
self.current_tab = Box::new(WalletInfo::default());
|
|
|
|
});
|
|
|
|
});
|
|
|
|
columns[1].vertical_centered_justified(|ui| {
|
|
|
|
View::tab_button(ui, DOWNLOAD, current_type == WalletTabType::Receive, || {
|
|
|
|
self.current_tab = Box::new(WalletReceive::default());
|
|
|
|
});
|
|
|
|
});
|
|
|
|
columns[2].vertical_centered_justified(|ui| {
|
|
|
|
View::tab_button(ui, UPLOAD, current_type == WalletTabType::Send, || {
|
|
|
|
self.current_tab = Box::new(WalletSend::default());
|
|
|
|
});
|
|
|
|
});
|
|
|
|
columns[3].vertical_centered_justified(|ui| {
|
2023-08-09 04:19:15 +03:00
|
|
|
View::tab_button(ui, GEAR_FINE, current_type == WalletTabType::Settings, || {
|
2023-08-03 23:49:11 +03:00
|
|
|
self.current_tab = Box::new(WalletSettings::default());
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2023-04-27 01:28:55 +03:00
|
|
|
}
|
2023-08-03 00:00:23 +03:00
|
|
|
|
2023-08-13 21:09:04 +03:00
|
|
|
/// Draw content when wallet is syncing and not ready to use, returns `true` at this case.
|
|
|
|
pub fn sync_ui(ui: &mut egui::Ui, frame: &mut eframe::Frame, wallet: &Wallet) -> bool {
|
|
|
|
if wallet.is_repairing() && !wallet.sync_error() {
|
|
|
|
Self::sync_progress_ui(ui, wallet);
|
|
|
|
return true;
|
|
|
|
} else if wallet.is_closing() {
|
|
|
|
Self::sync_progress_ui(ui, wallet);
|
2023-08-11 01:20:41 +03:00
|
|
|
return true;
|
2023-08-13 21:09:04 +03:00
|
|
|
} else if wallet.get_current_ext_conn_id().is_none() {
|
2023-08-09 20:11:44 +03:00
|
|
|
if !Node::is_running() || Node::is_stopping() {
|
|
|
|
let dual_panel_root = Root::is_dual_panel_mode(frame);
|
2023-08-11 01:20:41 +03:00
|
|
|
View::center_content(ui, 108.0, |ui| {
|
2023-08-09 20:11:44 +03:00
|
|
|
let text = t!("wallets.enable_node", "settings" => GEAR_FINE);
|
|
|
|
ui.label(RichText::new(text).size(16.0).color(Colors::INACTIVE_TEXT));
|
2023-08-09 02:22:16 +03:00
|
|
|
ui.add_space(8.0);
|
2023-08-09 20:11:44 +03:00
|
|
|
// Show button to enable integrated node at non-dual root panel mode
|
|
|
|
// or when network connections are not showing and node is not stopping
|
|
|
|
if (!dual_panel_root || AppConfig::show_connections_network_panel())
|
|
|
|
&& !Node::is_stopping() {
|
|
|
|
let enable_node_text = format!("{} {}", POWER, t!("network.enable_node"));
|
|
|
|
View::button(ui, enable_node_text, Colors::GOLD, || {
|
|
|
|
Node::start();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return true
|
2023-08-13 21:09:04 +03:00
|
|
|
} else if wallet.sync_error()
|
2023-08-11 01:20:41 +03:00
|
|
|
&& Node::get_sync_status() == Some(SyncStatus::NoSync) {
|
2023-08-13 21:09:04 +03:00
|
|
|
Self::sync_error_ui(ui, wallet);
|
2023-08-11 01:20:41 +03:00
|
|
|
return true;
|
|
|
|
} else if wallet.get_data().is_none() {
|
2023-08-13 21:09:04 +03:00
|
|
|
Self::sync_progress_ui(ui, wallet);
|
2023-08-09 02:22:16 +03:00
|
|
|
return true;
|
2023-08-09 20:11:44 +03:00
|
|
|
}
|
2023-08-13 21:09:04 +03:00
|
|
|
} else if wallet.sync_error() {
|
|
|
|
Self::sync_error_ui(ui, wallet);
|
|
|
|
return true;
|
2023-08-11 01:20:41 +03:00
|
|
|
} else if wallet.get_data().is_none() {
|
2023-08-13 21:09:04 +03:00
|
|
|
Self::sync_progress_ui(ui, wallet);
|
2023-08-09 20:11:44 +03:00
|
|
|
return true;
|
2023-08-03 23:49:11 +03:00
|
|
|
}
|
2023-08-09 02:22:16 +03:00
|
|
|
false
|
2023-08-03 23:49:11 +03:00
|
|
|
}
|
2023-08-09 20:11:44 +03:00
|
|
|
|
2023-08-13 21:09:04 +03:00
|
|
|
/// Draw wallet sync error content.
|
|
|
|
fn sync_error_ui(ui: &mut egui::Ui, wallet: &Wallet) {
|
2023-08-11 01:20:41 +03:00
|
|
|
View::center_content(ui, 108.0, |ui| {
|
|
|
|
let text = t!("wallets.wallet_loading_err", "settings" => GEAR_FINE);
|
|
|
|
ui.label(RichText::new(text).size(16.0).color(Colors::INACTIVE_TEXT));
|
|
|
|
ui.add_space(8.0);
|
|
|
|
let retry_text = format!("{} {}", REPEAT, t!("retry"));
|
|
|
|
View::button(ui, retry_text, Colors::GOLD, || {
|
2023-08-13 21:09:04 +03:00
|
|
|
wallet.retry_sync();
|
2023-08-11 01:20:41 +03:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-08-13 21:09:04 +03:00
|
|
|
/// Check when to block tabs navigation on sync progress.
|
|
|
|
pub fn block_navigation_on_sync(wallet: &Wallet) -> bool {
|
|
|
|
let sync_error = wallet.sync_error();
|
|
|
|
let integrated_node = wallet.get_current_ext_conn_id().is_none();
|
|
|
|
let integrated_node_ready = Node::get_sync_status() == Some(SyncStatus::NoSync);
|
|
|
|
let sync_after_opening = wallet.get_data().is_none() && !wallet.sync_error();
|
2023-08-14 03:17:54 +03:00
|
|
|
// Block navigation if wallet is repairing and integrated node is not launching
|
|
|
|
// and if wallet is closing or syncing after opening when there is no data to show.
|
2023-08-13 21:09:04 +03:00
|
|
|
(wallet.is_repairing() && (integrated_node_ready || !integrated_node) && !sync_error)
|
|
|
|
|| wallet.is_closing() || (sync_after_opening && !integrated_node)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Draw wallet sync progress content.
|
|
|
|
pub fn sync_progress_ui(ui: &mut egui::Ui, wallet: &Wallet) {
|
2023-08-09 20:11:44 +03:00
|
|
|
View::center_content(ui, 162.0, |ui| {
|
|
|
|
View::big_loading_spinner(ui);
|
|
|
|
ui.add_space(18.0);
|
2023-08-13 21:09:04 +03:00
|
|
|
// Setup sync progress text.
|
2023-08-11 01:20:41 +03:00
|
|
|
let text = {
|
2023-08-13 21:09:04 +03:00
|
|
|
let integrated_node = wallet.get_current_ext_conn_id().is_none();
|
|
|
|
let integrated_node_ready = Node::get_sync_status() == Some(SyncStatus::NoSync);
|
|
|
|
let info_progress = wallet.info_sync_progress();
|
2023-08-11 01:20:41 +03:00
|
|
|
if wallet.is_closing() {
|
|
|
|
t!("wallets.wallet_closing")
|
2023-08-13 21:09:04 +03:00
|
|
|
} else if integrated_node && !integrated_node_ready {
|
|
|
|
t!("wallets.node_loading", "settings" => GEAR_FINE)
|
|
|
|
} else if wallet.is_repairing() {
|
|
|
|
let repair_progress = wallet.repairing_progress();
|
|
|
|
if repair_progress == 0 {
|
|
|
|
t!("wallets.wallet_checking")
|
|
|
|
} else {
|
|
|
|
format!("{}: {}%", t!("wallets.wallet_checking"), repair_progress)
|
|
|
|
}
|
2023-08-11 01:20:41 +03:00
|
|
|
} else if info_progress != 100 {
|
|
|
|
if info_progress == 0 {
|
|
|
|
t!("wallets.wallet_loading")
|
|
|
|
} else {
|
|
|
|
format!("{}: {}%", t!("wallets.wallet_loading"), info_progress)
|
|
|
|
}
|
|
|
|
} else {
|
2023-08-13 21:09:04 +03:00
|
|
|
let tx_progress = wallet.txs_sync_progress();
|
2023-08-11 01:20:41 +03:00
|
|
|
if tx_progress == 0 {
|
|
|
|
t!("wallets.tx_loading")
|
|
|
|
} else {
|
|
|
|
format!("{}: {}%", t!("wallets.tx_loading"), tx_progress)
|
|
|
|
}
|
|
|
|
}
|
2023-08-09 20:11:44 +03:00
|
|
|
};
|
|
|
|
ui.label(RichText::new(text).size(16.0).color(Colors::INACTIVE_TEXT));
|
|
|
|
});
|
|
|
|
}
|
2023-04-27 01:28:55 +03:00
|
|
|
}
|