config + ui: fix wallets reload on change chain type, optimize wallet list item, add tab button effects, make dark color lighter, rename side panel constant

This commit is contained in:
ardocrat 2023-07-31 01:04:41 +03:00
parent 9d401d6bf8
commit 00767dd7e0
9 changed files with 78 additions and 70 deletions

View file

@ -26,8 +26,8 @@ impl Colors {
pub const GREEN: Color32 = Color32::from_rgb(0, 0x64, 0);
pub const RED: Color32 = Color32::from_rgb(0x8B, 0, 0);
pub const FILL: Color32 = Color32::from_gray(244);
pub const FILL_DARK: Color32 = Color32::from_gray(232);
pub const CHECKBOX: Color32 = Color32::from_gray(100);
pub const FILL_DARK: Color32 = Color32::from_gray(234);
pub const CHECKBOX: Color32 = Color32::from_gray(107);
pub const TEXT: Color32 = Color32::from_gray(80);
pub const TEXT_BUTTON: Color32 = Color32::from_gray(70);
pub const TITLE: Color32 = Color32::from_gray(60);
@ -35,6 +35,7 @@ impl Colors {
pub const GRAY: Color32 = Color32::from_gray(120);
pub const STROKE: Color32 = Color32::from_gray(190);
pub const INACTIVE_TEXT: Color32 = Color32::from_gray(150);
pub const ITEM_BUTTON: Color32 = Color32::from_gray(90);
pub const ITEM_STROKE: Color32 = Color32::from_gray(220);
pub const ITEM_HOVER: Color32 = Color32::from_gray(205);
pub const ITEM_CURRENT: Color32 = Color32::from_gray(227);

View file

@ -68,8 +68,8 @@ pub struct Modal {
impl Modal {
/// Margin from [`Modal`] window at top/left/right.
const DEFAULT_MARGIN: f32 = 10.0;
/// Default width of the content.
const DEFAULT_WIDTH: f32 = Root::SIDE_PANEL_MIN_WIDTH - (2.0 * Self::DEFAULT_MARGIN);
/// Maximum width of the content.
const DEFAULT_WIDTH: f32 = Root::SIDE_PANEL_WIDTH - (2.0 * Self::DEFAULT_MARGIN);
/// Create opened and closeable Modal with center position.
pub fn new(id: &'static str) -> Self {

View file

@ -20,7 +20,7 @@ use lazy_static::lazy_static;
use crate::gui::Colors;
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{WalletsContent, Modal, ModalContainer, Network, View};
use crate::gui::views::{Modal, ModalContainer, Network, View, WalletsContent};
use crate::node::Node;
lazy_static! {
@ -73,7 +73,7 @@ impl Root {
pub const EXIT_MODAL_ID: &'static str = "exit_confirmation";
/// Default width of side panel at application UI.
pub const SIDE_PANEL_MIN_WIDTH: f32 = 400.0;
pub const SIDE_PANEL_WIDTH: f32 = 400.0;
pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) {
// Show opened exit confirmation modal content.
@ -110,7 +110,7 @@ impl Root {
let dual_panel_mode = Self::is_dual_panel_mode(frame);
let is_panel_open = dual_panel_mode || Self::is_network_panel_open();
let panel_width = if dual_panel_mode {
Self::SIDE_PANEL_MIN_WIDTH + View::get_left_inset()
Self::SIDE_PANEL_WIDTH + View::get_left_inset()
} else {
frame.info().window_info.size.x
};
@ -126,7 +126,7 @@ impl Root {
// Dual panel mode is available when window is wide and its width is at least 2 times
// greater than minimal width of the side panel plus display insets from both sides.
let side_insets = View::get_left_inset() + View::get_right_inset();
is_wide_screen && w >= (Self::SIDE_PANEL_MIN_WIDTH * 2.0) + side_insets
is_wide_screen && w >= (Self::SIDE_PANEL_WIDTH * 2.0) + side_insets
}
/// Toggle [`Network`] panel state.

View file

@ -128,25 +128,35 @@ impl View {
/// Tab button with white background fill color, contains only icon.
pub fn tab_button(ui: &mut egui::Ui, icon: &str, active: bool, action: impl FnOnce()) {
ui.scope(|ui| {
let text_color = match active {
true => Colors::TITLE,
false => Colors::TEXT
};
let stroke = match active {
true => Stroke::NONE,
false => Self::DEFAULT_STROKE
};
let color = match active {
true => Colors::FILL,
false => Colors::WHITE
};
let br = Button::new(RichText::new(icon.to_string()).size(22.0).color(text_color))
.stroke(stroke)
.fill(color)
.ui(ui);
let mut button = Button::new(RichText::new(icon).size(22.0).color(text_color));
if !active {
// Disable expansion on click/hover.
ui.style_mut().visuals.widgets.hovered.expansion = 0.0;
ui.style_mut().visuals.widgets.active.expansion = 0.0;
// Setup fill colors.
ui.visuals_mut().widgets.inactive.weak_bg_fill = Colors::WHITE;
ui.visuals_mut().widgets.hovered.weak_bg_fill = Colors::BUTTON;
ui.visuals_mut().widgets.active.weak_bg_fill = Colors::FILL;
// Setup stroke colors.
ui.visuals_mut().widgets.inactive.bg_stroke = Self::DEFAULT_STROKE;
ui.visuals_mut().widgets.hovered.bg_stroke = Self::ITEM_HOVER_STROKE;
ui.visuals_mut().widgets.active.bg_stroke = Self::ITEM_STROKE;
} else {
button = button.fill(Colors::FILL).stroke(Stroke::NONE);
}
let br = button.ui(ui);
if Self::touched(ui, br) {
(action)();
}
});
}
/// Draw [`Button`] with specified background fill color.
@ -174,19 +184,17 @@ impl View {
// Disable expansion on click/hover.
ui.style_mut().visuals.widgets.hovered.expansion = 0.0;
ui.style_mut().visuals.widgets.active.expansion = 0.0;
// Setup fill colors.
ui.visuals_mut().widgets.inactive.weak_bg_fill = Colors::WHITE;
ui.visuals_mut().widgets.hovered.weak_bg_fill = Colors::BUTTON;
ui.visuals_mut().widgets.active.weak_bg_fill = Colors::FILL;
// Setup stroke colors.
ui.visuals_mut().widgets.inactive.bg_stroke = Self::DEFAULT_STROKE;
ui.visuals_mut().widgets.hovered.bg_stroke = Self::ITEM_HOVER_STROKE;
ui.visuals_mut().widgets.active.bg_stroke = Self::ITEM_STROKE;
// Show button.
let br = Button::new(RichText::new(icon).size(20.0).color(Colors::CHECKBOX))
let br = Button::new(RichText::new(icon).size(20.0).color(Colors::ITEM_BUTTON))
.rounding(rounding)
.min_size(button_size)
.ui(ui);

View file

@ -321,7 +321,7 @@ impl MnemonicSetup {
/// 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 min_panel_w = Root::SIDE_PANEL_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

View file

@ -18,7 +18,7 @@ use egui::{Align, Align2, Layout, Margin, RichText, Rounding, ScrollArea, TextSt
use egui_extras::{Size, StripBuilder};
use crate::gui::Colors;
use crate::gui::icons::{ARROW_LEFT, CARET_RIGHT, COMPUTER_TOWER, EYE, EYE_SLASH, FOLDER, FOLDER_LOCK, FOLDER_OPEN, GEAR, GLOBE, GLOBE_SIMPLE, PLUS};
use crate::gui::icons::{ARROW_LEFT, CARET_RIGHT, COMPUTER_TOWER, EYE, EYE_SLASH, FOLDER_LOCK, FOLDER_OPEN, GEAR, GLOBE, GLOBE_SIMPLE, PLUS};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{Modal, ModalContainer, ModalPosition, Root, TitlePanel, TitleType, View};
use crate::gui::views::wallets::creation::{MnemonicSetup, WalletCreation};
@ -229,14 +229,12 @@ impl WalletsContent {
.auto_shrink([false; 2])
.show(ui, |ui| {
ui.vertical_centered(|ui| {
// Calculate wallet list width.
let available_width = ui.available_width();
let width = if dual_panel {
available_width
} else {
min(available_width as i64, (Root::SIDE_PANEL_MIN_WIDTH * 1.3) as i64) as f32
};
// Setup wallet list width.
let mut rect = ui.available_rect_before_wrap();
let mut width = ui.available_width();
if !dual_panel {
width = min(width as i64, (Root::SIDE_PANEL_WIDTH * 1.3) as i64) as f32
}
rect.set_width(width);
ui.allocate_ui(rect.size(), |ui| {
@ -274,7 +272,7 @@ impl WalletsContent {
// Draw round background.
let mut rect = ui.available_rect_before_wrap();
rect.set_height(77.0);
rect.set_height(78.0);
let rounding = View::item_rounding(0, 1);
let bg_color = if is_current { Colors::ITEM_CURRENT } else { Colors::FILL };
let stroke = if is_current { View::ITEM_HOVER_STROKE } else { View::ITEM_HOVER_STROKE };
@ -310,21 +308,20 @@ impl WalletsContent {
ui.allocate_ui_with_layout(layout_size, Layout::left_to_right(Align::Center), |ui| {
ui.add_space(7.0);
ui.vertical(|ui| {
ui.add_space(3.0);
// Setup wallet name text.
let name_text = format!("{} {}", FOLDER, wallet.config.name);
let name_color = if is_selected { Colors::BLACK } else { Colors::TITLE };
ui.add_space(4.0);
View::ellipsize_text(ui, name_text, 18.0, name_color);
ui.add_space(-1.0);
View::ellipsize_text(ui, wallet.config.name.to_owned(), 18.0, name_color);
// Setup wallet connection text.
let external_url = wallet.config.get_external_node_url();
let external_url = &wallet.config.external_node_url;
let conn_text = if let Some(url) = external_url {
format!("{} {}", GLOBE_SIMPLE, url)
} else {
format!("{} {}", COMPUTER_TOWER, t!("network.node"))
};
View::ellipsize_text(ui, conn_text, 15.0, Colors::TEXT);
ui.add_space(1.0);
// Setup wallet status text.
let status_text = if Wallets::is_open(id) {
@ -491,10 +488,10 @@ impl WalletsContent {
let available_width = if is_list_empty || is_wallet_creation {
ui.available_width()
} else {
ui.available_width() - Root::SIDE_PANEL_MIN_WIDTH
ui.available_width() - Root::SIDE_PANEL_WIDTH
};
if dual_panel {
let min_width = (Root::SIDE_PANEL_MIN_WIDTH + View::get_right_inset()) as i64;
let min_width = (Root::SIDE_PANEL_WIDTH + View::get_right_inset()) as i64;
max(min_width, available_width as i64) as f32
} else {
if is_wallet_showing {
@ -509,7 +506,7 @@ impl WalletsContent {
fn is_dual_panel_mode(ui: &mut egui::Ui, frame: &mut eframe::Frame) -> bool {
let dual_panel_root = Root::is_dual_panel_mode(frame);
let max_width = ui.available_width();
dual_panel_root && max_width >= (Root::SIDE_PANEL_MIN_WIDTH * 2.0) + View::get_right_inset()
dual_panel_root && max_width >= (Root::SIDE_PANEL_WIDTH * 2.0) + View::get_right_inset()
}
/// Handle Back key event.

View file

@ -83,16 +83,19 @@ impl AppConfig {
pub fn change_chain_type(chain_type: &ChainTypes) {
let current_chain_type = Self::chain_type();
if current_chain_type != *chain_type {
// Save chain type at app config.
{
let mut w_app_config = Settings::app_config_to_update();
w_app_config.chain_type = *chain_type;
w_app_config.save();
}
// Load node config for selected chain type.
{
let mut w_node_config = Settings::node_config_to_update();
let node_config = NodeConfig::for_chain_type(chain_type);
w_node_config.node = node_config.node;
w_node_config.peers = node_config.peers;
}
// Reload wallets.
Wallets::reload(chain_type);
}

View file

@ -14,9 +14,10 @@
use std::fs;
use std::path::PathBuf;
use grin_core::global::ChainTypes;
use grin_core::global::ChainTypes;
use serde_derive::{Deserialize, Serialize};
use crate::{AppConfig, Settings};
use crate::wallet::Wallets;
@ -24,13 +25,13 @@ use crate::wallet::Wallets;
#[derive(Serialize, Deserialize, Clone)]
pub struct WalletConfig {
/// Chain type for current wallet.
chain_type: ChainTypes,
pub(crate) chain_type: ChainTypes,
/// Identifier for a wallet.
pub(crate) id: i64,
/// Human-readable wallet name for ui.
pub(crate) name: String,
/// External node connection URL.
external_node_url: Option<String>,
pub(crate) external_node_url: Option<String>,
}
/// Wallet configuration file name.
@ -84,13 +85,8 @@ impl WalletConfig {
Settings::write_to_file(self, config_path);
}
/// Get external node connection URL.
pub fn get_external_node_url(&self) -> &Option<String> {
&self.external_node_url
}
/// Set external node connection URL.
pub fn set_external_node_url(&mut self, url: Option<String>) {
pub fn save_external_node_url(&mut self, url: Option<String>) {
self.external_node_url = url;
self.save();
}

View file

@ -160,8 +160,11 @@ impl Wallets {
/// Reload list of wallets for provided [`ChainTypes`].
pub fn reload(chain_type: &ChainTypes) {
let wallets = Self::load_wallets(chain_type);
let mut w_state = WALLETS_STATE.write().unwrap();
w_state.list = Self::load_wallets(chain_type);
w_state.selected_id = None;
w_state.opened_ids = BTreeSet::default();
w_state.list = wallets;
}
}
@ -241,7 +244,7 @@ impl Wallet {
/// Create wallet instance from provided config.
fn create_wallet_instance(config: WalletConfig) -> Result<WalletInstance, Error> {
// Assume global chain type has already been initialized.
let chain_type = AppConfig::chain_type();
let chain_type = config.chain_type;
if !global::GLOBAL_CHAIN_TYPE.is_init() {
global::init_global_chain_type(chain_type);
} else {
@ -250,8 +253,8 @@ impl Wallet {
}
// Setup node client.
let (node_api_url, node_secret) = if let Some(url) = config.get_external_node_url() {
(url.to_string(), None)
let (node_api_url, node_secret) = if let Some(url) = &config.external_node_url {
(url.to_owned(), None)
} else {
(NodeConfig::get_api_address(), NodeConfig::get_api_secret())
};