wallet + ui: add account to config, show account info, amounts, optimize wallet content panels, update translations

This commit is contained in:
ardocrat 2023-08-16 04:42:05 +03:00
parent bc6f2623d9
commit 322adf66b4
8 changed files with 265 additions and 37 deletions

View file

@ -9,6 +9,10 @@ change: Change
show: Show
delete: Delete
wallets:
await_conf_amount: Awaiting confirmation
await_fin_amount: Awaiting finalization
locked_amount: Locked
txs_empty: 'To receive/send coins use %{receive}/%{send} buttons at the bottom of the screen, to change wallet settings press %{settings}.'
title: Wallets
create_desc: Create or import existing wallet from saved recovery phrase.
add: Add wallet
@ -47,6 +51,7 @@ wallets:
wallet_closing: Closing wallet
wallet_checking: Checking wallet
tx_loading: Loading transactions
default_account: Default account
recovery: Recovery
repair_wallet: Repair wallet
repair_desc: Check a wallet, repairing and restoring missing outputs if required. This operation will take time.
@ -132,7 +137,7 @@ network_mining:
disconnected: Disconnected
network_settings:
change_value: Change value
stratum_ip: 'Stratum IP Address:'
stratum_ip: 'Stratum IP address:'
stratum_port: 'Stratum port:'
port_unavailable: Specified port is unavailable
restart_node_required: Node restart is required to apply changes.
@ -140,8 +145,8 @@ network_settings:
disable: Disable
restart: Restart
server: Server
api_ip: 'API IP Address:'
api_port: 'API Port:'
api_ip: 'API IP address:'
api_port: 'API port:'
api_secret: 'Rest API and V2 Owner API token:'
foreign_api_secret: 'Foreign API token:'
disabled: Disabled

View file

@ -9,6 +9,10 @@ change: Изменить
show: Показать
delete: Удалить
wallets:
await_conf_amount: Ожидает подтверждения
await_fin_amount: Ожидает завершения
locked_amount: Заблокировано
txs_empty: 'Для получения/отправки монет используйте кнопки %{receive}/%{send} внизу экрана, для изменения настроек кошелька нажмите %{settings}.'
title: Кошельки
create_desc: Создайте или импортируйте существующий кошелёк из сохранённой фразы восстановления.
add: Добавить кошелёк
@ -47,6 +51,7 @@ wallets:
wallet_closing: Закрытие кошелька
wallet_checking: Проверка кошелька
tx_loading: Загрузка транзакций
default_account: Стандартный аккаунт
recovery: Восстановление
repair_wallet: Починить кошелёк
repair_desc: Проверить кошелёк, исправляя и восстанавливая недостающие выходы, если это необходимо. Эта операция займёт время.
@ -132,7 +137,7 @@ network_mining:
disconnected: Отключен
network_settings:
change_value: Изменить значение
stratum_ip: 'Stratum IP Адрес:'
stratum_ip: 'Stratum IP адрес:'
stratum_port: 'Порт Stratum:'
port_unavailable: Указанный порт недоступен
restart_node_required: Для применения изменений требуется перезапуск узла.
@ -140,8 +145,8 @@ network_settings:
disable: Выключить
restart: Перезапуск
server: Сервер
api_ip: 'API IP Адрес:'
api_port: 'API Порт:'
api_ip: 'API IP адрес:'
api_port: 'API порт:'
api_secret: 'Rest и V2 Owner API токен:'
foreign_api_secret: 'Foreign API токен:'
disabled: Отключен

View file

@ -14,17 +14,19 @@
use std::time::Duration;
use egui::{Margin, RichText};
use egui::{Align, Layout, Margin, RichText, Rounding};
use grin_chain::SyncStatus;
use grin_core::core::amount_to_hr_string;
use crate::AppConfig;
use crate::gui::Colors;
use crate::gui::icons::{DOWNLOAD, GEAR_FINE, POWER, REPEAT, UPLOAD, WALLET};
use crate::gui::icons::{DOWNLOAD, FILE_ARCHIVE, GEAR_FINE, LIST, PACKAGE, PLUS, POWER, REPEAT, UPLOAD, WALLET};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Root, View};
use crate::gui::views::wallets::{WalletInfo, WalletReceive, WalletSend, WalletSettings};
use crate::gui::views::wallets::types::{WalletTab, WalletTabType};
use crate::node::Node;
use crate::wallet::types::WalletData;
use crate::wallet::Wallet;
/// Selected and opened wallet content.
@ -45,9 +47,36 @@ impl WalletContent {
frame: &mut eframe::Frame,
wallet: &mut Wallet,
cb: &dyn PlatformCallbacks) {
let data = wallet.get_data();
let data_empty = data.is_none();
// Show wallet balance panel when data is not empty and current tab is not Settings.
let show_balance = self.current_tab.get_type() != WalletTabType::Settings && !data_empty;
egui::TopBottomPanel::top("wallet_balance")
.frame(egui::Frame {
fill: Colors::FILL,
stroke: View::DEFAULT_STROKE,
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()
})
.show_animated_inside(ui, show_balance, |ui| {
ui.vertical_centered(|ui| {
// Draw wallet tabs.
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
Self::account_balance_ui(ui, data.as_ref().unwrap(), &wallet.config.account);
});
});
});
// Show wallet tabs panel.
egui::TopBottomPanel::bottom("wallet_tabs")
.frame(egui::Frame {
stroke: View::DEFAULT_STROKE,
fill: Colors::FILL,
inner_margin: Margin {
left: View::far_left_inset_margin(ui) + 4.0,
@ -69,14 +98,8 @@ impl WalletContent {
// Show tab content panel.
egui::CentralPanel::default()
.frame(egui::Frame {
stroke: View::DEFAULT_STROKE,
fill: Colors::WHITE,
inner_margin: Margin {
left: View::far_left_inset_margin(ui) + 4.0,
right: View::get_right_inset() + 4.0,
top: 3.0,
bottom: 4.0,
},
stroke: View::DEFAULT_STROKE,
..Default::default()
})
.show_inside(ui, |ui| {
@ -84,13 +107,67 @@ impl WalletContent {
});
// Refresh content after 1 second for synced wallet.
if wallet.get_data().is_some() {
if !data_empty {
ui.ctx().request_repaint_after(Duration::from_millis(1000));
} else {
ui.ctx().request_repaint();
}
}
/// Draw wallet account balance.
fn account_balance_ui(ui: &mut egui::Ui, data: &WalletData, account: &Option<String>) {
let mut rect = ui.available_rect_before_wrap();
rect.set_height(76.0);
// Draw round background.
let rounding = View::item_rounding(0, 1, false);
ui.painter().rect(rect, rounding, Colors::BUTTON, View::ITEM_STROKE);
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
// Setup padding for item buttons.
ui.style_mut().spacing.button_padding = egui::vec2(14.0, 0.0);
// Setup rounding for item buttons.
ui.style_mut().visuals.widgets.inactive.rounding = Rounding::same(8.0);
ui.style_mut().visuals.widgets.hovered.rounding = Rounding::same(8.0);
ui.style_mut().visuals.widgets.active.rounding = Rounding::same(8.0);
// Draw button to add new account.
View::item_button(ui, View::item_rounding(0, 1, true), PLUS, None, || {
//TODO add account modal.
});
// Draw button to show list of accounts.
View::item_button(ui, Rounding::none(), LIST, None, || {
//TODO: accounts list modal
});
let layout_size = ui.available_size();
ui.allocate_ui_with_layout(layout_size, Layout::left_to_right(Align::Center), |ui| {
ui.add_space(6.0);
ui.vertical(|ui| {
ui.add_space(3.0);
// Show spendable amount.
let amount = amount_to_hr_string(data.info.amount_currently_spendable, false);
let amount_text = format!("1234567{}", amount);
ui.label(RichText::new(amount_text).size(18.0).color(Colors::BLACK));
// Show account name.
let account_name = match account {
None => t!("wallets.default_account"),
Some(name) => name.to_owned()
};
let account_text = format!("{} {}", FILE_ARCHIVE, account_name);
ui.add_space(-1.0);
View::ellipsize_text(ui, account_text, 15.0, Colors::TEXT);
ui.add_space(1.0);
// Show confirmed height.
let height_text = format!("{} {}", PACKAGE, data.info.last_confirmed_height);
ui.label(RichText::new(height_text).size(15.0).color(Colors::GRAY));
})
});
});
}
/// Draw tab buttons in the bottom of the screen.
fn tabs_ui(&mut self, ui: &mut egui::Ui) {
ui.scope(|ui| {

View file

@ -12,10 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::{Margin, RichText};
use grin_core::core::amount_to_hr_string;
use crate::gui::Colors;
use crate::gui::icons::{DOWNLOAD, GEAR_FINE, UPLOAD};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Root, View};
use crate::gui::views::wallets::types::WalletTab;
use crate::gui::views::wallets::wallet::types::WalletTabType;
use crate::gui::views::wallets::wallet::WalletContent;
use crate::wallet::types::WalletData;
use crate::wallet::Wallet;
/// Wallet info tab content.
@ -35,5 +42,65 @@ impl WalletTab for WalletInfo {
if WalletContent::sync_ui(ui, frame, wallet) {
return;
}
let data = wallet.get_data().unwrap();
// Show wallet transactions panel.
egui::CentralPanel::default()
.frame(egui::Frame {
stroke: View::ITEM_STROKE,
fill: Colors::BUTTON,
inner_margin: Margin {
left: View::far_left_inset_margin(ui) + 4.0,
right: View::get_right_inset() + 4.0,
top: 0.0,
bottom: 4.0,
},
..Default::default()
})
.show_inside(ui, |ui| {
ui.vertical_centered(|ui| {
View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| {
self.txs_ui(ui, &data);
});
});
if data.txs.is_empty() {
View::center_content(ui, 96.0, |ui| {
let empty_text = t!(
"wallets.txs_empty",
"receive" => DOWNLOAD,
"send" => UPLOAD,
"settings" => GEAR_FINE
);
ui.label(RichText::new(empty_text).size(16.0).color(Colors::INACTIVE_TEXT));
});
} else {
}
});
}
}
impl WalletInfo {
/// Draw transactions content.
fn txs_ui(&self, ui: &mut egui::Ui, data: &WalletData) {
// Show awaiting confirmation amount.
let awaiting_conf = amount_to_hr_string(data.info.amount_awaiting_confirmation, false);
View::rounded_box(ui,
format!("{}", awaiting_conf),
t!("wallets.await_conf_amount"),
[false, false, false, false]);
// Show awaiting finalization amount.
let awaiting_conf = amount_to_hr_string(data.info.amount_awaiting_finalization, false);
View::rounded_box(ui,
format!("{}", awaiting_conf),
t!("wallets.await_fin_amount"),
[false, false, false, false]);
// Show locked amount.
let awaiting_conf = amount_to_hr_string(data.info.amount_locked, false);
View::rounded_box(ui,
format!("{}", awaiting_conf),
t!("wallets.locked_amount"),
[false, false, true, true]);
}
}

View file

@ -12,12 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::Margin;
use crate::gui::Colors;
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::View;
use crate::gui::views::wallets::wallet::types::{WalletTab, WalletTabType};
use crate::gui::views::wallets::wallet::WalletContent;
use crate::wallet::Wallet;
/// Receive funds tab content.
/// Receiving tab content.
#[derive(Default)]
pub struct WalletReceive;
@ -34,5 +38,29 @@ impl WalletTab for WalletReceive {
if WalletContent::sync_ui(ui, frame, wallet) {
return;
}
// Show receiving content panel.
egui::CentralPanel::default()
.frame(egui::Frame {
stroke: View::DEFAULT_STROKE,
fill: Colors::WHITE,
inner_margin: Margin {
left: View::far_left_inset_margin(ui) + 4.0,
right: View::get_right_inset() + 4.0,
top: 3.0,
bottom: 4.0,
},
..Default::default()
})
.show_inside(ui, |ui| {
self.receive_ui(ui, wallet);
});
}
}
impl WalletReceive {
/// Draw receiving content.
pub fn receive_ui(&self, ui: &mut egui::Ui, wallet: &mut Wallet) {
}
}

View file

@ -12,12 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::Margin;
use crate::gui::Colors;
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::View;
use crate::gui::views::wallets::wallet::types::{WalletTab, WalletTabType};
use crate::gui::views::wallets::wallet::WalletContent;
use crate::wallet::Wallet;
/// Send funds tab content.
/// Sending tab content.
#[derive(Default)]
pub struct WalletSend;
@ -30,9 +33,33 @@ impl WalletTab for WalletSend {
ui: &mut egui::Ui,
frame: &mut eframe::Frame,
wallet: &mut Wallet,
cb: &dyn PlatformCallbacks) {
_: &dyn PlatformCallbacks) {
if WalletContent::sync_ui(ui, frame, wallet) {
return;
}
// Show sending content panel.
egui::CentralPanel::default()
.frame(egui::Frame {
stroke: View::DEFAULT_STROKE,
fill: Colors::WHITE,
inner_margin: Margin {
left: View::far_left_inset_margin(ui) + 4.0,
right: View::get_right_inset() + 4.0,
top: 3.0,
bottom: 4.0,
},
..Default::default()
})
.show_inside(ui, |ui| {
self.send_ui(ui, wallet);
});
}
}
impl WalletSend {
/// Draw sending content.
pub fn send_ui(&self, ui: &mut egui::Ui, wallet: &mut Wallet) {
}
}

View file

@ -12,8 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::{Id, ScrollArea};
use egui::{Id, Margin, ScrollArea};
use crate::gui::Colors;
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Root, View};
use crate::gui::views::wallets::setup::{CommonSetup, ConnectionSetup, RecoverySetup};
@ -59,6 +60,20 @@ impl WalletTab for WalletSettings {
return;
}
// Show settings content panel.
egui::CentralPanel::default()
.frame(egui::Frame {
stroke: View::DEFAULT_STROKE,
fill: Colors::WHITE,
inner_margin: Margin {
left: View::far_left_inset_margin(ui) + 4.0,
right: View::get_right_inset() + 4.0,
top: 3.0,
bottom: 4.0,
},
..Default::default()
})
.show_inside(ui, |ui| {
ScrollArea::vertical()
.id_source(Id::from("wallet_settings_scroll").with(wallet.config.id))
.auto_shrink([false; 2])
@ -74,5 +89,6 @@ impl WalletTab for WalletSettings {
});
});
});
});
}
}

View file

@ -24,11 +24,13 @@ use crate::wallet::types::ConnectionMethod;
/// Wallet configuration.
#[derive(Serialize, Deserialize, Clone)]
pub struct WalletConfig {
/// Last chosen wallet account label.
pub account: Option<String>,
/// Chain type for current wallet.
pub chain_type: ChainTypes,
/// Identifier for a wallet.
pub id: i64,
/// Human-readable wallet name for ui.
/// Wallet name.
pub name: String,
/// External connection identifier.
pub ext_conn_id: Option<i64>,
@ -41,11 +43,11 @@ pub const BASE_DIR_NAME: &'static str = "wallets";
/// Wallet configuration file name.
const CONFIG_FILE_NAME: &'static str = "grim-wallet.toml";
/// Minimal amount of confirmations default value.
/// Default value of minimal amount of confirmations.
const MIN_CONFIRMATIONS_DEFAULT: u64 = 10;
impl WalletConfig {
/// Create wallet config.
/// Create new wallet config.
pub fn create(name: String, conn_method: &ConnectionMethod) -> WalletConfig {
// Setup configuration path.
let id = chrono::Utc::now().timestamp();
@ -53,6 +55,7 @@ impl WalletConfig {
let config_path = Self::get_config_file_path(chain_type, id);
// Write configuration to the file.
let config = WalletConfig {
account: None,
chain_type,
id,
name,
@ -60,7 +63,7 @@ impl WalletConfig {
ConnectionMethod::Integrated => None,
ConnectionMethod::External(id) => Some(*id)
},
min_confirmations: MIN_CONFIRMATIONS_DEFAULT,
min_confirmations: MIN_CONFIRMATIONS_DEFAULT
};
Settings::write_to_file(&config, config_path);
config