diff --git a/src/gui/views/content.rs b/src/gui/views/content.rs index 624a038a..07a4b812 100644 --- a/src/gui/views/content.rs +++ b/src/gui/views/content.rs @@ -98,6 +98,16 @@ impl ContentContainer for Content { // its sidebar, so the network column stays hidden while it shows. // Same for first-run onboarding, which owns the whole window. let wallet_open = self.wallets.showing_wallet() || self.wallets.onboarding_active(); + // On the returning-user wallet list the node is demoted to a chip: + // the panel opens only when explicitly toggled, never forced open by + // dual-panel mode (otherwise GRIM's node column dominates the list). + let list_screen = self.wallets.wallet_list_screen(); + let show_network = !wallet_open + && if list_screen { + Self::is_network_panel_open() + } else { + is_panel_open + }; // Show network content. egui::SidePanel::left("network_panel") @@ -106,7 +116,7 @@ impl ContentContainer for Content { .frame(egui::Frame { ..Default::default() }) - .show_animated_inside(ui, is_panel_open && !wallet_open, |ui| { + .show_animated_inside(ui, show_network, |ui| { self.network.ui(ui, cb); }); diff --git a/src/gui/views/wallets/content.rs b/src/gui/views/wallets/content.rs index 54fe198b..02164cb0 100644 --- a/src/gui/views/wallets/content.rs +++ b/src/gui/views/wallets/content.rs @@ -210,9 +210,11 @@ impl ContentContainer for WalletsContent { || self.wallets.list().is_empty() || (showing_wallet && (!dual_panel || !AppConfig::show_wallets_at_dual_panel())); - // Show title panel, except over the full-bleed Goblin wallet surface - // and onboarding (they have their own header/navigation). - if !showing_wallet && !onboarding_active { + // Show title panel, except over the full-bleed Goblin wallet surface, + // onboarding, and the returning-user wallet list (all carry their own + // header; the yellow GRIM bar is off-brand on those surfaces). + let wallet_list_screen = self.wallet_list_screen(); + if !showing_wallet && !onboarding_active && !wallet_list_screen { self.title_ui(ui, dual_panel, cb); } @@ -423,6 +425,17 @@ impl WalletsContent { self.settings_content.is_some() } + /// Check if the returning-user wallet list owns the surface (wallets + /// exist, none open, not mid-onboarding/creation/settings). On this + /// screen the node panel is demoted to an opt-in chip, not a column. + pub fn wallet_list_screen(&self) -> bool { + !self.showing_wallet() + && !self.onboarding_active() + && !self.showing_settings() + && !self.creating_wallet() + && !self.wallets.list().is_empty() + } + /// Handle data from deeplink or opened file. fn on_data(&mut self, ui: &mut egui::Ui, data: Option, cb: &dyn PlatformCallbacks) { let wallets_size = self.wallets.list().len(); @@ -561,6 +574,72 @@ impl WalletsContent { } } + /// Slim header for the wallet-list surface: a tappable integrated-node + /// status chip (opens the full node panel — every feature intact, just + /// opt-in) on the left, and the app-settings gear on the right. + fn wallet_list_header_ui(&mut self, ui: &mut egui::Ui) { + use crate::node::Node; + ui.add_space(6.0); + ui.horizontal(|ui| { + // Node status chip. + let running = Node::is_running(); + let synced = running && Node::not_syncing(); + let (dot, label) = if !running { + (Colors::gray(), "Node") + } else if synced { + (Colors::pos(), "Node synced") + } else { + (Colors::gold(), "Syncing…") + }; + let galley = ui.painter().layout_no_wrap( + label.to_string(), + eframe::epaint::FontId::proportional(14.0), + Colors::text(false), + ); + let pad = egui::Vec2::new(12.0, 7.0); + let chip_w = 10.0 + 8.0 + galley.size().x + pad.x * 2.0; + let (rect, resp) = + ui.allocate_exact_size(egui::Vec2::new(chip_w, 34.0), Sense::click()); + ui.painter() + .rect_filled(rect, CornerRadius::same(17), Colors::fill_lite()); + let dot_c = egui::pos2(rect.min.x + pad.x + 5.0, rect.center().y); + ui.painter().circle_filled(dot_c, 4.0, dot); + ui.painter().galley( + egui::pos2(dot_c.x + 13.0, rect.center().y - galley.size().y / 2.0), + galley, + Colors::text(false), + ); + if resp + .on_hover_cursor(CursorIcon::PointingHand) + .on_hover_text("Node settings") + .clicked() + { + Content::toggle_network_panel(); + } + + // App-settings gear, right-aligned. Drawn manually (the title-bar + // button uses dark-on-yellow ink, invisible on this dark surface). + ui.with_layout(Layout::right_to_left(Align::Center), |ui| { + let (g_rect, g_resp) = + ui.allocate_exact_size(egui::Vec2::splat(34.0), Sense::click()); + ui.painter().text( + g_rect.center(), + egui::Align2::CENTER_CENTER, + GEAR, + eframe::epaint::FontId::proportional(20.0), + Colors::text(false), + ); + if g_resp + .on_hover_cursor(CursorIcon::PointingHand) + .on_hover_text("Settings") + .clicked() + { + self.settings_content = Some(SettingsContent::default()); + } + }); + }); + } + /// Draw list of wallets. fn wallet_list_ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) { ScrollArea::vertical() @@ -569,6 +648,13 @@ impl WalletsContent { .auto_shrink([false; 2]) .show(ui, |ui| { View::max_width_ui(ui, Content::SIDE_PANEL_WIDTH * 1.3, |ui| { + // Slim goblin header: node-status chip (opens the node + // panel) on the left, app-settings gear on the right — + // the controls the suppressed yellow title bar used to + // carry, restyled to match the open-wallet surface. + self.wallet_list_header_ui(ui); + ui.add_space(8.0); + // Show application logo and name. View::app_logo_name_version(ui); ui.add_space(15.0);