gui: fixes

- Wgpu renderer by default for Windows
- Fix items borders sizes
- Start camera at  messages on scan press
- Do not show pull-to-refresh on empty tx list
- Do not close non-closeable modal on Back/Esc key press
- Cut long connection name at wallet list
- Fix setting of tx receiver address

Reviewed-on: https://code.gri.mw/GUI/grim/pulls/47
This commit is contained in:
ardocrat
2026-02-19 23:15:24 +00:00
parent a8df3a20ba
commit 7d75fc2ae0
21 changed files with 75 additions and 66 deletions
+2 -2
View File
@@ -171,7 +171,7 @@ impl<Platform: PlatformCallbacks> App<Platform> {
CornerRadius::ZERO,
Colors::fill_lite(),
View::default_stroke(),
StrokeKind::Middle);
StrokeKind::Outside);
// Draw content background.
ui.painter().add(content_bg);
@@ -250,7 +250,7 @@ impl<Platform: PlatformCallbacks> App<Platform> {
sw: 0.0 as u8,
se: 0.0 as u8,
}
}, Colors::yellow_dark(), Stroke::new(1.0, Colors::STROKE), StrokeKind::Middle);
}, Colors::yellow_dark(), Stroke::new(1.0, Colors::STROKE), StrokeKind::Outside);
// Draw title background.
ui.painter().add(window_title_bg);
+5 -3
View File
@@ -120,7 +120,9 @@ impl Modal {
/// Return `false` if modal existed in state before call.
pub fn on_back() -> bool {
if Self::opened().is_some() {
Self::close();
if Self::opened_closeable() {
Self::close();
}
return false;
}
true
@@ -310,7 +312,7 @@ impl Modal {
sw: 8.0 as u8,
se: 8.0 as u8,
}
}, Colors::fill(), Stroke::NONE, StrokeKind::Middle);
}, Colors::fill(), Stroke::NONE, StrokeKind::Outside);
let bg_idx = ui.painter().add(bg_shape.clone());
rect.min += egui::emath::vec2(6.0, 0.0);
@@ -341,7 +343,7 @@ fn title_ui(title: &String, ui: &mut egui::Ui) {
ne: 8.0 as u8,
sw: 0.0 as u8,
se: 0.0 as u8,
}, Colors::yellow(), Stroke::NONE, StrokeKind::Middle);
}, Colors::yellow(), Stroke::NONE, StrokeKind::Outside);
let bg_idx = ui.painter().add(bg_shape.clone());
// Draw title content.
+2 -2
View File
@@ -130,7 +130,7 @@ impl ConnectionsContent {
let mut rect = ui.available_rect_before_wrap();
rect.set_height(78.0);
let rounding = View::item_rounding(0, 1, false);
ui.painter().rect(rect, rounding, Colors::fill(), View::item_stroke(), StrokeKind::Middle);
ui.painter().rect(rect, rounding, Colors::fill(), View::item_stroke(), StrokeKind::Outside);
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
// Draw custom button.
@@ -206,7 +206,7 @@ impl ConnectionsContent {
item_rounding,
Colors::fill(),
View::item_stroke(),
StrokeKind::Middle);
StrokeKind::Outside);
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
// Draw provided buttons.
+1 -1
View File
@@ -154,7 +154,7 @@ fn block_item_ui(ui: &mut egui::Ui, db: &DiffBlock, rounding: CornerRadius) {
rounding,
Colors::white_or_black(false),
View::item_stroke(),
StrokeKind::Middle);
StrokeKind::Outside);
// Draw block hash.
ui.horizontal(|ui| {
+1 -1
View File
@@ -201,7 +201,7 @@ fn worker_item_ui(ui: &mut egui::Ui, ws: &WorkerStats, rounding: CornerRadius) {
rounding,
Colors::white_or_black(false),
View::item_stroke(),
StrokeKind::Middle);
StrokeKind::Outside);
ui.add_space(2.0);
ui.horizontal(|ui| {
+1 -1
View File
@@ -184,7 +184,7 @@ fn peer_item_ui(ui: &mut egui::Ui, peer: &PeerStats, rounding: CornerRadius) {
ui.add_space(4.0);
// Draw round background.
ui.painter().rect(rect, rounding, Colors::fill_lite(), View::item_stroke(), StrokeKind::Middle);
ui.painter().rect(rect, rounding, Colors::fill_lite(), View::item_stroke(), StrokeKind::Outside);
// Draw IP address.
ui.horizontal(|ui| {
+1 -1
View File
@@ -788,7 +788,7 @@ fn peer_item_ui(ui: &mut egui::Ui,
item_rounding,
Colors::white_or_black(false),
View::item_stroke(),
StrokeKind::Middle);
StrokeKind::Outside);
ui.vertical(|ui| {
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
+1 -1
View File
@@ -139,7 +139,7 @@ impl InterfaceSettingsContent {
item_rounding,
Colors::fill(),
View::item_stroke(),
StrokeKind::Middle);
StrokeKind::Outside);
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
if edit {
+1 -1
View File
@@ -213,7 +213,7 @@ impl NetworkSettingsContent {
item_rounding,
Colors::fill(),
View::item_stroke(),
StrokeKind::Middle);
StrokeKind::Outside);
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
View::item_button(ui, View::item_rounding(0, 1, true), PENCIL, None, || {
+3 -3
View File
@@ -333,7 +333,7 @@ impl TorSettingsContent {
item_rounding,
Colors::fill(),
View::item_stroke(),
StrokeKind::Middle);
StrokeKind::Outside);
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
View::item_button(ui, View::item_rounding(0, 1, true), PENCIL, None, || {
@@ -373,7 +373,7 @@ impl TorSettingsContent {
item_rounding,
Colors::fill(),
View::item_stroke(),
StrokeKind::Middle);
StrokeKind::Outside);
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
self.bridge_bin_pick_file.ui(ui, cb, |path| {
@@ -473,7 +473,7 @@ impl TorSettingsContent {
item_rounding,
Colors::fill(),
View::item_stroke(),
StrokeKind::Middle);
StrokeKind::Outside);
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
View::item_button(ui, View::item_rounding(0, 1, true), SCAN, None, || {
+1 -1
View File
@@ -410,7 +410,7 @@ impl View {
ne: if r[1] { 8.0 as u8 } else { 0.0 as u8 },
sw: if r[2] { 8.0 as u8 } else { 0.0 as u8 },
se: if r[3] { 8.0 as u8 } else { 0.0 as u8 },
}, Colors::fill_lite(), Self::item_stroke(), StrokeKind::Middle);
}, Colors::fill_lite(), Self::item_stroke(), StrokeKind::Outside);
let bg_idx = ui.painter().add(bg_shape.clone());
// Draw box content.
+3 -3
View File
@@ -539,7 +539,7 @@ impl WalletsContent {
} else {
Colors::fill()
};
ui.painter().rect(rect, rounding, bg, View::item_stroke(), StrokeKind::Middle);
ui.painter().rect(rect, rounding, bg, View::item_stroke(), StrokeKind::Outside);
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
if !wallet.is_open() {
@@ -547,7 +547,7 @@ impl WalletsContent {
View::item_button(ui, View::item_rounding(0, 1, true), FOLDER_OPEN, None, || {
self.show_opening_modal(wallet, None, cb);
});
if !wallet.syncing() {
if !wallet.is_repairing() {
View::item_button(ui, CornerRadius::default(), GLOBE, None, || {
self.select_wallet(wallet, None, cb);
self.conn_selection_content =
@@ -606,7 +606,7 @@ impl WalletsContent {
}
ConnectionMethod::External(_, url) => format!("{} {}", GLOBE_SIMPLE, url)
};
ui.label(RichText::new(conn_text).size(15.0).color(Colors::gray()));
View::ellipsize_text(ui, conn_text, 15.0, Colors::gray());
ui.add_space(3.0);
});
});
+1 -1
View File
@@ -96,7 +96,7 @@ impl WalletsModal {
rounding,
Colors::fill(),
View::hover_stroke(),
StrokeKind::Middle);
StrokeKind::Outside);
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
if self.can_open {
+1 -1
View File
@@ -78,7 +78,7 @@ impl WalletAccountsContent {
item_rounding,
Colors::fill(),
View::item_stroke(),
StrokeKind::Middle);
StrokeKind::Outside);
ui.vertical(|ui| {
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
+1
View File
@@ -151,6 +151,7 @@ impl MessageInputContent {
let scan_text = format!("{} {}", SCAN, t!("scan"));
View::button(ui, scan_text, Colors::white_or_black(false), || {
self.scan_qr_content = Some(CameraContent::default());
cb.start_camera();
});
}
});
@@ -160,7 +160,7 @@ impl ConnectionSettings {
item_rounding,
Colors::fill(),
View::item_stroke(),
StrokeKind::Middle);
StrokeKind::Outside);
ui.vertical(|ui| {
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
+5 -5
View File
@@ -21,7 +21,7 @@ use grin_wallet_libwallet::TxLogEntryType;
use std::ops::Range;
use std::time::{SystemTime, UNIX_EPOCH};
use crate::gui::icons::{ARCHIVE_BOX, ARROWS_CLOCKWISE, ARROW_CIRCLE_DOWN, ARROW_CIRCLE_UP, CALENDAR_CHECK, DOTS_THREE_CIRCLE, FILE_ARROW_DOWN, FILE_TEXT, GEAR_FINE, PROHIBIT, WARNING, X_CIRCLE};
use crate::gui::icons::{ARROWS_CLOCKWISE, ARROW_CIRCLE_DOWN, ARROW_CIRCLE_UP, CALENDAR_CHECK, DOTS_THREE_CIRCLE, FILE_ARROW_DOWN, FILE_TEXT, GEAR_FINE, PROHIBIT, WARNING, X_CIRCLE};
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::types::{LinePosition, ModalPosition};
use crate::gui::views::wallets::wallet::types::{WalletContentContainer, GRIN};
@@ -107,7 +107,7 @@ impl WalletTransactionsContent {
let empty_text = t!(
"wallets.txs_empty",
"message" => FILE_ARROW_DOWN,
"transport" => ARCHIVE_BOX,
"transport" => FILE_TEXT,
"settings" => GEAR_FINE
);
ui.label(RichText::new(empty_text)
@@ -126,7 +126,7 @@ impl WalletTransactionsContent {
let refresh = self.manual_sync.unwrap_or(0) + 1600 > now;
let refresh_resp = PullToRefresh::new(refresh)
.id(Id::from("refresh_tx_list").with(config.id))
.can_refresh(!refresh && !wallet.syncing())
.can_refresh(!refresh && !wallet.syncing() && !txs.is_empty())
.min_refresh_distance(70.0)
.scroll_area_ui(ui, |ui| {
ScrollArea::vertical()
@@ -166,7 +166,7 @@ impl WalletTransactionsContent {
// Draw tx item background.
let mut r = View::item_rounding(index, txs.len(), false);
let p = ui.painter();
p.rect(rect, r, Colors::fill(), View::item_stroke(), StrokeKind::Middle);
p.rect(rect, r, Colors::fill(), View::item_stroke(), StrokeKind::Outside);
let tx = txs.get(index).unwrap();
Self::tx_item_ui(ui, tx, rect, &data, |ui| {
@@ -220,7 +220,7 @@ impl WalletTransactionsContent {
ne: 0.0 as u8,
sw: 8.0 as u8,
se: 8.0 as u8,
}, Colors::fill(), View::item_stroke(), StrokeKind::Middle);
}, Colors::fill(), View::item_stroke(), StrokeKind::Outside);
let bg_idx = ui.painter().add(bg.clone());
let resp = ui.allocate_ui(rect.size(), |ui| {
ui.vertical_centered_justified(|ui| {
+2 -2
View File
@@ -228,7 +228,7 @@ impl WalletTransactionContent {
// Draw tx item background.
let p = ui.painter();
let r = View::item_rounding(0, 2, false);
p.rect(rect, r, Colors::TRANSPARENT, View::item_stroke(), StrokeKind::Middle);
p.rect(rect, r, Colors::TRANSPARENT, View::item_stroke(), StrokeKind::Outside);
// Show transaction amount status and time.
let data = wallet.get_data().unwrap();
@@ -304,7 +304,7 @@ fn info_item_ui(ui: &mut egui::Ui,
let bg_rect = rect.clone();
let mut rounding = View::item_rounding(1, 3, false);
ui.painter().rect(bg_rect, rounding, Colors::fill(), View::item_stroke(), StrokeKind::Middle);
ui.painter().rect(bg_rect, rounding, Colors::fill(), View::item_stroke(), StrokeKind::Outside);
ui.allocate_ui_with_layout(rect.size(), Layout::right_to_left(Align::Center), |ui| {
// Draw button to copy transaction info value.
+24 -26
View File
@@ -44,34 +44,32 @@ pub trait WalletContentContainer {
/// Get wallet status text.
pub fn wallet_status_text(wallet: &Wallet) -> String {
if wallet.is_open() {
if wallet.sync_error() {
format!("{} {}", WARNING_CIRCLE, t!("error"))
} else if wallet.is_closing() {
format!("{} {}", SPINNER, t!("wallets.closing"))
} else if wallet.is_repairing() {
let repair_progress = wallet.repairing_progress();
if repair_progress == 0 {
format!("{} {}", SPINNER, t!("wallets.checking"))
} else {
format!("{} {}: {}%",
SPINNER,
t!("wallets.checking"),
repair_progress)
}
} else if wallet.syncing() {
let info_progress = wallet.info_sync_progress();
if info_progress == 100 || info_progress == 0 {
format!("{} {}", SPINNER, t!("wallets.loading"))
} else {
format!("{} {}: {}%",
SPINNER,
t!("wallets.loading"),
info_progress)
}
if wallet.sync_error() {
format!("{} {}", WARNING_CIRCLE, t!("error"))
} else if wallet.is_closing() {
format!("{} {}", SPINNER, t!("wallets.closing"))
} else if wallet.is_repairing() {
let repair_progress = wallet.repairing_progress();
if repair_progress == 0 {
format!("{} {}", SPINNER, t!("wallets.checking"))
} else {
format!("{} {}", FOLDER_OPEN, t!("wallets.unlocked"))
format!("{} {}: {}%",
SPINNER,
t!("wallets.checking"),
repair_progress)
}
} else if wallet.syncing() {
let info_progress = wallet.info_sync_progress();
if info_progress == 100 || info_progress == 0 {
format!("{} {}", SPINNER, t!("wallets.loading"))
} else {
format!("{} {}: {}%",
SPINNER,
t!("wallets.loading"),
info_progress)
}
} else if wallet.is_open() {
format!("{} {}", FOLDER_OPEN, t!("wallets.unlocked"))
} else {
format!("{} {}", FOLDER_LOCK, t!("wallets.locked"))
}
+12 -2
View File
@@ -134,8 +134,14 @@ fn start_desktop_gui(platform: grim::gui::platform::Desktop) {
.with_transparent(true)
.with_decorations(is_mac || is_win);
let renderer = if is_win {
eframe::Renderer::Wgpu
} else {
eframe::Renderer::Glow
};
let mut options = eframe::NativeOptions {
renderer: eframe::Renderer::Glow,
renderer,
viewport,
..Default::default()
};
@@ -146,7 +152,11 @@ fn start_desktop_gui(platform: grim::gui::platform::Desktop) {
Ok(_) => {}
Err(_) => {
// Start with another renderer on error.
options.renderer = eframe::Renderer::Wgpu;
if is_win {
options.renderer = eframe::Renderer::Glow;
} else {
options.renderer = eframe::Renderer::Wgpu;
}
let app = grim::gui::App::new(platform);
match grim::start(options, grim::app_creator(app)) {
+6 -8
View File
@@ -242,15 +242,13 @@ impl WalletTransaction {
} else {
tx.amount_credited - tx.amount_debited
};
let receiver: Option<SlatepackAddress> = {
if let Some(proof) = &tx.payment_proof {
let onion_addr = OnionV3Address::from_bytes(proof.receiver_address.to_bytes());
if let Ok(addr) = SlatepackAddress::try_from(onion_addr) {
Some(addr);
}
let mut receiver: Option<SlatepackAddress> = None;
if let Some(proof) = &tx.payment_proof {
let onion_addr = OnionV3Address::from_bytes(proof.receiver_address.to_bytes());
if let Ok(addr) = SlatepackAddress::try_from(onion_addr) {
receiver = Some(addr);
}
None
};
}
let mut t = Self {
data: tx,
state: SlateState::Unknown,