Conversation
Add full GUI mode that launches when the exe is run without arguments. - Real-time memory dashboard with usage bars and history chart - One-click cleaning at all 4 levels (Gentle/Moderate/Aggressive/Nuclear) - Continuous monitoring with auto-clean at configurable thresholds - Process list sorted by memory usage via egui_extras TableBuilder - Settings panel (dark mode, tray icon placeholder, context menu toggle) - Background stats thread (1Hz snapshots) with Arc<Mutex<>> shared state - Console hidden on GUI launch via hide_and_free_console() Dependencies: eframe 0.33, egui_extras 0.33, egui_plot 0.34, tray-icon 0.21, image 0.25 Updated: deny.toml (new licenses + skip entries), cli.rs (help text), README.md, docs
- Anti-flash: start window hidden, reveal on first frame via ViewportCommand - Compact layout: 780x520 default, 620x400 min, tighter spacing - Text sharpness: explicit text styles (Heading 18, Body 13, Small 10) - Monitor toggle: custom animated iOS-style toggle switch widget - Icons fixed: removed U+FE0F variation selectors, safe Unicode only - Light theme: theme-aware colors in sidebar, nav, cards, and all panels - Split monitor.rs draw() into helpers to satisfy 100-line limit
…board, fix flash - Switch to SUBSYSTEM:WINDOWS to eliminate console window flash on GUI launch - Add setup_cli_console() with AttachConsole/AllocConsole + CONOUT$ redirect - Redesign color palette: GitHub-inspired dark/light themes with sky-blue accent - Merge cleaning panel into dashboard as 2x2 clickable level cards - Remove separate clean panel and reduce nav to 4 items - Move monitor defaults out of settings (already in monitor page) - Add display section to settings for top process count - Remove egui_plot dependency (chart removed from dashboard) - Update toggle switch and widget colors to match new palette
…d depth - Replace flat egui ProgressBar with custom-painted memory bar featuring 3-D top highlight, dark track background, and drop-shadow text overlay - Add soft shadow to all card containers for visual depth/elevation - Increase card padding (12->18), rounding (8->12), section spacing (10->16) - Enlarge page titles (18->22px) with subtle separator line underneath - Bolder section headers with wider accent bar (3->4px, height 16->20px) - Taller clean level cards (52->68px) with bigger text and wider accent bars - Accent bar corners now match card rounding for seamless left edge - Wrap System Info section in a card for visual consistency - Increase stat label values (13->15px) with 2px gap above for hierarchy - Widen sidebar (150->156px) and main panel margins (14->20px) for breathing room - Raise surface color contrast against background for better card definition
…n buttons - Merge Physical Memory and System Info into a single hero card with divider - Replace transparent info-card style clean buttons with colour-filled action buttons - Centre button text with hover glow, glass highlight, and bottom accent line - Move all informational data above all interactive controls (info-then-action) - Remove separate System Info section (draw_quick_info merged into info card)
- Replace 32px chunky bar with large percentage headline + slim 6px bar - Replace color-tinted buttons with uniform neutral cards + color dot indicator - Remove glass effects, fake 3D highlights, drop shadows, accent underlines - Clear typography hierarchy: 36px load%, 15px stat values, 11px labels - Hover: subtle colored border only, no background color tinting
… badge - Left coloured stripe (3px, brightens to 4px on hover) for instant level recognition - Background tints subtly toward level colour on hover (8%) and press (14%) - Right pill badge with filled-circle dots (1-4) showing relative intensity - Level name adopts level colour on hover for clear feedback - Extracted BtnCtx struct and three painter helpers to stay under lint limits
…e detail panel - Four equal-sized circles (88px) evenly spaced in a single row - Each circle has a coloured outer ring (dim at rest, full-brightness on hover) - Background tints toward level colour on hover (10%) and press (18%) - Level name turns level colour when hovered or pressed - Detail panel below updates live: name, subtitle, and full description - Neutral prompt shown when no circle is hovered
…le setting - Reserve 8px right margin on circle row to clear the scrollbar - Replace fixed detail panel with floating on_hover_ui tooltip - Tooltip shows level name (in level colour), subtitle, and full description - Add show_level_tooltips bool to GuiSettings (default: true) - Settings > Display: checkbox to enable/disable the hover tooltips
Gentle was running PurgeLowPriorityStandbyList (priority-0 only) which frees almost nothing on systems with few low-priority standby pages. Moderate was running EmptyWorkingSets (kernel-level) which is as aggressive as the Aggressive level, making it feel like a deep clean. New operation mapping: - Gentle: PurgeStandbyList (all standby, all priorities, zero process impact) - Moderate: FlushModifiedList + PurgeStandbyList (I/O flush then full standby purge, no working-set eviction) - Aggressive: unchanged - Nuclear: unchanged Also update dry_run_plan labels, CleanLevel doc comments, affected test, cli.rs help text, and dashboard tooltip descriptions.
All raw Unicode escape sequences used as icons in the GUI have been removed and replaced with named constants from egui_phosphor::regular (v0.11, egui 0.33 compatible). The Phosphor font is registered at startup in MagicXApp::new() so all glyphs render reliably across systems - the previous approach relied on egui's bundled NotoSans which lacks many of the glyphs (U+25C9 fisheye, U+2630 trigram, U+2699 gear). Icon mapping: GAUGE=Dashboard, ACTIVITY=Monitor, CPU=Processes, GEAR=Settings, CHECK/X=success/failure, ARROW_RIGHT=direction arrow, CARET_UP/CARET_DOWN=sort indicators.
The previous 156px sidebar wasted ~20% of the 780px window width. Replaced with a 56px icon-rail following the VS Code / Linear / Discord pattern: - Brand: 'MX' monogram badge (36x36, rounded, ACCENT tinted bg) instead of full wordmark - Nav: icon-only buttons (20px, centered) with tooltip on hover revealing label - Active state: accent-tinted pill background + ACCENT icon color - Hover state: faint pill background + primary text color - Version: bottom-pinned via bottom_up layout - Frame margin: 8px horizontal (was 12px) Content area gains 100px of horizontal space.
Four coordinated improvements: 1. Window: 780x520 -> 720x580 (taller, matches screenshot proportions) 2. Brand badge: 'MX' -> 'MGX' at 13px to fit 3 chars comfortably 3. Top Processes count slider moved from Settings to the Processes panel - settings draw_display renamed to draw_preferences, now only has tooltip toggle - processes panel owns draw_count_control() with 'Show top' slider 4. Processes table UX: - ROW_HEIGHT 20->26 for better vertical breathing room - HEADER_HEIGHT 26, right-aligned PID/WS/Peak columns to match numeric data convention - Wider Name column (140px min), 115px WS column for bar - Info row: '{N} processes / sorted by {col}' instead of plain count - Working Set cell: micro 2.5px usage bar (relative to top process) drawn below the value - draw() split into draw_table_card() + draw_ws_cell() to satisfy too_many_lines lint
Add src/gui/persistence.rs with load_settings() and save_settings() that read/write %APPDATA%\MagicX\RAM Cleaner\settings.json via serde_json (already a dependency). Settings load on startup so theme, process count, tooltips, monitor config, and all other GuiSettings fields survive restarts. Changes are written immediately when any setting is modified (shadow-copy comparison each frame) and again on window close via on_exit(). Uses existing serde + serde_json deps — no new dependencies added.
Replace loose load_settings/save_settings functions with a SettingsManager unit struct (src/gui/persistence.rs). All settings I/O — load, save, export, import — is centralised in one place, making it easy to add versioning or multi-profile logic later. Add Win32_UI_Controls_Dialogs feature to windows-sys (no new crate). Implement native file-picker dialogs via GetOpenFileNameW/GetSaveFileNameW so users can export settings to any JSON file and restore from it. Add a Backup & Restore card at the bottom of the Settings panel with Export/Import buttons and an 8-second auto-dismissed feedback banner. Add settings_status field to MagicXApp for cross-frame status messaging.
Change default settings path from %APPDATA%\MagicX\RAM Cleaner\settings.json to settings.json in the same directory as the running executable. Falls back to the current working directory if current_exe() fails. Update window inner size from 720x580 to 620x500 to match the screenshot dimensions.
Remove CentralPanel inner_margin and instead wrap scroll content in a Frame with the same 20px padding. The ScrollArea now spans the full CentralPanel width so the scrollbar sits flush at the right window edge with no wasted space beside it.
…ge scrollbar Disable max_scroll_height and vscroll on the TableBuilder so the process table expands to its full height. The outer ScrollArea (already pinned to the window edge) handles all vertical scrolling, eliminating the in-card scrollbar that overlapped Peak column content.
- Add TrayHandle in new gui/tray.rs: loads app.ico, builds context menu with Open/Quit items, polls events per frame via update()- Intercept close button when minimize_to_tray is enabled; CancelClose + hide window to notification area; TrayAction::Quit flag lets tray-initiated exit proceed normally- Add SettingsManager::set_autostart() in persistence.rs: writes/removes HKCU\Software\Microsoft\Windows\CurrentVersion\Run entry using RegOpenKeyExW / RegSetValueExW / RegDeleteValueW- Rename GuiSettings::tray_enabled -> minimize_to_tray (serde alias for back-compat) and replace context_menu_enabled with auto_start- Settings panel Integration card: real toggles with descriptive sub-labels and immediate feedback via settings_status on autostart errors- Cargo.toml: add ico feature to image dep for ICO decoding
- Cargo.toml FileDescription: 'The most powerful Windows RAM cleaner CLI' -> 'MagicX RAM Cleaner' (fixes the name shown in Windows Task Manager)- mod.rs: load assets/app.png via image crate and set it as the egui window icon using ViewportBuilder::with_icon() so the taskbar and alt-tab show the correct icon
…idden Root cause: eframe stops calling update() when the window is Visible(false), so poll_tray_events() never ran and tray menu clicks were silently ignored.Fix: TrayHandle now spawns a dedicated 'tray-watcher' thread that polls the global tray_icon event channels (sole consumer, avoiding concurrent Receiver access). When any tray or menu event arrives the thread sends TrayAction via an internal mpsc channel and calls ctx.request_repaint() to wake eframe's event loop regardless of window visibility. TrayHandle::poll() now reads from that internal channel only. The shutdown Arc<AtomicBool> lets the thread exit cleanly when the handle is dropped.
- Add context_menu_installed: bool to MagicXApp, initialised via context_menu::is_installed() at startup - New 'Desktop Context Menu' card in Settings panel showing: - Live status badge (Installed / Not installed) - Install button: calls context_menu::current_exe_path() + install() - Remove button: calls context_menu::uninstall() - Both buttons update context_menu_installed + settings_status feedback - Split draw_context_menu() into three focused helpers to satisfy the too_many_lines (100) clippy lint: draw_context_menu(), draw_context_menu_install_btn(), draw_context_menu_remove_btn() - Writes entries under HKCR\DesktopBackground\Shell and HKCR\Directory\Background\Shell via the existing context_menu module
…adata FileDescription was updated in Cargo.toml (commit c83b638) but build.rs had no cargo:rerun-if-changed=Cargo.toml trigger. The winresource step was therefore never re-run, so the old description string remained embedded in the PE version resources and Task Manager continued to show 'The most powerful Windows RAM cleaner CLI' instead of 'MagicX RAM Cleaner'.
…idden Root cause: ViewportCommand::Visible(false) clears WS_VISIBLE on the window. Windows then suppresses WM_PAINT delivery (confirmed in winit source: 'window technically has to be visible to receive WM_PAINT messages'). RedrawWindow(RDW_INTERNALPAINT) - which ctx.request_repaint() ultimately calls - is a no-op for hidden windows, so eframe never calls update() and tray click events pile up in the mpsc channel unprocessed. Fix: add post_synthetic_wm_paint(hwnd) to console.rs which calls PostMessageW(hwnd, WM_PAINT, 0, 0). Unlike RedrawWindow, PostMessageW bypasses the WS_VISIBLE guard and places WM_PAINT directly in the owning thread's message queue. Winit's WndProc dispatches it as WindowEvent::RedrawRequested, causing eframe to call update() and drain the tray action channel. Changes: - console.rs: add find_app_window(title) and post_synthetic_wm_paint(hwnd) - tray.rs: add wake_eframe() helper that calls both request_repaint() (visible windows) and post_synthetic_wm_paint() (hidden windows); TrayHandle::new() now accepts hwnd: isize and passes it to the watcher - app.rs: find HWND via console::find_app_window() at startup; pass it to TrayHandle::new() in both creation sites
winresource auto-maps CARGO_PKG_DESCRIPTION into the PE FileDescription field, overriding the [package.metadata.winresource] value. This caused Task Manager to show the long crate description instead of 'MagicX RAM Cleaner'. Adding an explicit .set("FileDescription", ...) call ensures the correct name appears.
When the window is hidden to the tray (WS_VISIBLE cleared), eframe cannot call update() because Windows suppresses RedrawWindow(RDW_INTERNALPAINT) for invisible windows. The previous workaround (PostMessageW WM_PAINT) was unreliable. Fix: the tray-watcher thread now calls ShowWindow directly via Win32 before requesting a repaint, ensuring the window is visible when eframe processes the event. For Show: SW_SHOW + SetForegroundWindow. For Quit: SW_SHOWNOACTIVATE (no focus steal). Additionally, poll_tray_events() now runs before the close intercept in update() so quit_requested is set before the intercept checks it.
winresource 0.1.30 defaults FileDescription to CARGO_PKG_NAME (not CARGO_PKG_DESCRIPTION as its docs claim). [package.metadata.winresource].FileDescription in Cargo.toml already provides the correct override to 'MagicX RAM Cleaner'. The explicit .set() call added in the previous commit was redundant - the real fix was triggering a rebuild that picked up the existing metadata section.
Adds a 'Clean RAM' submenu to the tray context menu with all four cleaning levels (Gentle, Moderate, Aggressive, Nuclear). Selecting a level restores the window, switches to the Dashboard panel, and starts the clean immediately. Introduces a MenuIds struct to track item IDs cleanly, and a TrayAction::Clean(CleanLevel) variant for dispatch.
The auto-clean result logging ran every frame while monitor_active was true, flooding the activity log with identical entries. Moved result logging into poll_clean_results() so each result is logged exactly once. Also added: - Start/stop transition messages when the toggle is flipped - Periodic heartbeat every 60s showing current load vs threshold - Two new fields: last_monitor_status_log, prev_monitor_active
Menu now includes Dashboard, Monitor, Processes, Settings items that navigate directly to the corresponding panel. Clean sub-items use IconMenuItem with the lite/aggressive ICO assets; Open shows app.ico. Navigation items use plain MenuItem (no distinct icons available). Added TrayAction::Navigate(Panel) variant handled in both the watcher thread and poll_tray_events().
The previous fix only idled when hidden-to-tray; a merely OS-minimized window still triggered full egui layout+tessellation every second. - Detect viewport().minimized and factor it into the needs_repaint flag so the app idles on both minimize-to-tray AND OS minimize. - Gate MemorySnapshot::capture() behind needs_repaint: when idle the stats thread does zero Win32 calls, zero mutex locks — just one atomic load + 1 s sleep. - Slow the tray-watcher polling from 50 ms (20 Hz) to 200 ms (5 Hz); menu interactions remain imperceptibly responsive.
Root cause: egui widgets like ui.spinner() and animate_bool() internally call ctx.request_repaint(), creating a perpetual layout-repaint loop even when the window is minimized or hidden to tray. Three changes: - Add is_window_minimized() using Win32 IsIconic API for reliable minimized detection (egui's ViewportInfo::minimized can return None on Windows) - Gate ALL rendering (layout, theme, process refresh) behind a window_visible check so no widget can trigger repaints while invisible - Extract update_visible_ui() helper to keep both update() and the new method under the too_many_lines lint threshold
…7776) eframe 0.33 has a confirmed bug (emilk/egui#7776, #5229) where the winit event loop spins with ControlFlow::Poll at full speed when a window is hidden via Visible(false). PR emilk/egui#7905 fixes this upstream but hasn't been merged yet. Add an application-level workaround: when hidden_to_tray is true, sleep 200ms and schedule the next repaint 1s out. This drops the event loop from thousands of calls/sec to ~5 Hz, bringing CPU to near-zero. The tray-watcher thread's request_repaint() overrides the delay on user interaction.
Add auto_clean_enabled field to GuiSettings with #[serde(default)] so existing settings.json files are deserialized without error. On startup, monitor_active is initialized from the saved setting. The monitor panel syncs the ephemeral toggle back to settings on every frame change, and the existing auto-save logic writes it to disk.
Use CreateMutexW with a session-local name to prevent multiple GUI instances. When a second launch detects the mutex already exists, it finds the existing window via FindWindowW, restores it with SW_RESTORE + SetForegroundWindow, then exits silently. The mutex handle is kept alive for the process lifetime via the _instance_guard binding in run_gui().
When the first instance is hidden to the system tray, the second instance calls ShowWindow(SW_RESTORE) which makes the window visible at the Win32 level, but the first instance's hidden_to_tray flag remained true. This caused: blank window (no UI rendered), close button intercepted and window re-hidden. Fix: detect external visibility changes via IsWindowVisible in update() and clear hidden_to_tray. Also post WM_PAINT from the second instance to wake the event loop immediately.
Two bugs fixed: 1. External restore detection (is_window_visible check) ran on the same frame as close-intercept. Because Visible(false) is an async viewport command, WS_VISIBLE was still set when checked, immediately undoing the hide and leaving the close button stuck. Fix: skip the is_window_visible check on frames where close was just requested. 2. The 200ms sleep in the hidden_to_tray branch blocked the UI thread during close transitions, adding noticeable lag. Fix: skip the sleep on close-request frames so eframe can process the Visible(false) command immediately.
Replace the single-frame close_requested guard with a 500 ms cooldown (hide_requested_at: Option<Instant>). After the close intercept sends Visible(false), suppress the is_window_visible check for 500 ms so the async viewport command has time to clear WS_VISIBLE. This prevents the external restore detection from immediately undoing the hide when the app is minimized and restored by a second instance.
Introduce hide_window(hwnd: isize) which calls ShowWindow(SW_HIDE) directly via windows_sys to immediately clear WS_VISIBLE and hide the main window on the current frame. This is used alongside egui::ViewportCommand::Visible(false) to avoid an async winit visibility race (e.g. after an external ShowWindow(SW_RESTORE)) that could leave the window visible and cause a blank-flash/no-close symptom. The function is a no-op for hwnd == 0 and wraps the FFI call in an unsafe block with a comment explaining the safety rationale.
Introduce a new About panel (src/gui/panels/about.rs) implementing a full-page About view with hero, developer profile, social links, project/license info and helper widgets. Move the About navigation out of the main NAV_ITEMS list (now 4 items) and render an About button pinned to the bottom of the sidebar that activates the About panel. Also harden tray-minimize behavior in src/gui/app.rs by calling crate::console::hide_window(self.hwnd) when minimizing to tray to ensure the window is hidden even if winit's visibility state is stale.
Replace manual actions/cache with Swatinem/rust-cache@v2 for intelligent caching of registry, git deps, and pruned target/ artifacts keyed on OS + toolchain + Cargo.toml + Cargo.lock hashes. Bump upload-artifact from v4 to v6 (Node.js 24 runtime). Fix artifact upload path: target/debug/ matches the debug build (was target/release/ from the old release build gate). Add registry-only rust-cache to the audit job alongside the existing cargo-deny binary cache.
… debug build commit-msg + commit-msg.bat: increase max description length from 72 to 200 characters to accommodate descriptive commit messages. pre-push + pre-push.bat: replace release build gate with debug build for faster local push checks.
copilot-instructions.md still documented the old 72-character limit. Updated to match the hooks (5-200 chars).
…reference egui is not in scope in console.rs so rustdoc::broken_intra_doc_links rejected the link, blocking cargo doc and the pre-push gate.
Use PROCESS_MEMORY_COUNTERS_EX2 to obtain PrivateWorkingSetSize — the exact metric Task Manager shows in its Memory column. Falls back to full WorkingSetSize on older Windows builds where the extended struct is not supported. The CLI --top display now shows Memory (private WS), Working Set (full), and Peak WS columns.
Replace sort+scan grouping with HashMap-based O(n) algorithm. Use private_working_set as the primary 'Memory' column to match Task Manager terminology. Rename column header from 'Working Set' to 'Memory'. Query all processes for complete grouping coverage.
Add real-time search bar to filter processes by name. Show instance
count consistently ('1' for single instances). Add hover tooltip
showing private vs full working set breakdown. Rename col_name
helper to reflect 'memory' terminology.
Code comments: - cli.rs: fix ContextMenuAction::Install doc (use actual menu entry names) - lib.rs: update architecture diagram to include GUI, Context Menu, Stats modules README.md: - fix architecture tree (add lib.rs, persistence.rs, tray.rs, about.rs; remove non-existent clean.rs) - fix FAQ context menu names to match actual entries - fix comparison table to reflect CLI + GUI support - replace outdated binary size claim with portable exe description copilot-instructions.md: - fix Project Identity to reflect CLI + GUI - fix architecture tree (same corrections as README) - update prohibition list to acknowledge existing egui GUI - fix CI pipeline gate descriptions RUST_IMPLEMENTATION_GUIDE.md: - update Section 3 Cargo.toml to match actual deps (add GUI, registry, file dialog, DWM features) - add 3 missing windows-sys feature entries to Feature Map table - fix Section 12 architecture tree and panel descriptions - fix MemoryListCommand module attribution (cleaner -> ntapi) WINDOWS_MEMORY_INTERNALS.md: - add SystemRegistryReconciliationInformation (0x9B) to info class table CONTRIBUTING.md: - fix Layer 1 reference from main.rs to lib.rs for crate-level enforcement
Source code doc comments: - lib.rs: update crate doc from 'CLI tool' to 'CLI + GUI tool', expand architecture diagram to show GUI subsystems, add missing comparison table entries (registry flush, GUI, context menu) - dashboard.rs: fix Aggressive and Nuclear level descriptions to match actual cleaning sequences (Aggressive was missing registry flush, working sets, standby; Nuclear was missing combining and second pass) Markdown documentation: - README.md: add missing --exclude flag to clean command options table with example; fix context menu icon column (Phosphor glyphs with resource IDs, not app.ico); fix Memory Status context menu description (uses --notify, not console) - Cargo.toml: update package description to mention GUI alongside CLI - RUST_IMPLEMENTATION_GUIDE.md: fix QuickMemoryReading field names (total_physical + available_physical, not available_bytes + load_percent); fix settle detection polling interval (100ms not 50ms); fix threshold description (0.01% with 4MB floor, same for both modes; modes differ in stable reads and max polls); fix SmartCleanResult description (no level field); add FileCacheSnapshot to key types; add build.rs/assets to architecture listing - CONTRIBUTING.md: fix CI pipeline description (7 gates not 6, debug build not release build, add bench compile gate) - copilot-instructions.md: fix pre-push hook description (debug build not release); fix CI gate count (7 not 6); add app.png to assets listing; update console.rs and gui/mod.rs descriptions - WINDOWS_MEMORY_INTERNALS.md: add registry cache flush operation to the Operations & Their APIs table
OpenProcess was called with PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, but K32GetProcessMemoryInfo only requires PROCESS_QUERY_INFORMATION (or PROCESS_QUERY_LIMITED_INFORMATION). The unnecessary PROCESS_VM_READ flag caused OpenProcess to fail for Chromium/Electron sandboxed child processes (VS Code, Chrome, Edge renderer/utility workers) whose DACLs explicitly deny VM read access — even for admin callers. Replace the single OpenProcess call with a two-tier strategy: 1. PROCESS_QUERY_INFORMATION (works for most processes, gives EX2 data) 2. PROCESS_QUERY_LIMITED_INFORMATION fallback (catches sandboxed and Protected Process Light processes) This fixes missing process entries (e.g. 13/18 VS Code processes) and the resulting inaccurate RAM usage totals in both the CLI and GUI.
sort_processes() used sort_unstable_by with no tiebreaker, so rows with identical primary values (e.g. same instance count) were reshuffled on every 5-second refresh, producing a visually glitchy flickering effect. Add a secondary sort key (case-insensitive name) via Ordering::then_with so equal-valued rows always appear in the same order.
The monogram badge was allocated at the top of the horizontal layout, sitting flush with the top edge while the right-side content (title, tagline, button row) was taller. Wrap the badge in a vertical container with calculated top padding (matching the developer avatar centering pattern) so it sits at the vertical midpoint of the hero content.
The heart icon in the contribution call-to-action banner was top-aligned within its horizontal row, while the adjacent text block (heading + body) was taller — making the icon visually off-centre. Switch from ui.horizontal() (inherits Align::Min from parent) to an explicit left_to_right layout with Align::Center so the icon and text block are both vertically centred within the row.
The previous Layout::left_to_right(Align::Center) approach did not work because egui places the icon label at the cursor position before the text block height is known, so it was never retroactively centered. Redesign: draw the text block first (offset right to leave room for the icon), then overlay the heart glyph via ui.painter().text() at the vertical center of the text block's measured rect. This matches the allocate_exact_size + painter pattern used for info_row icons and the developer avatar.
Replace the single name-based tiebreaker with meaningful per-column chains so rows with identical primary values are ordered by the most useful secondary metric: Memory → Peak → Count → Name Count → Memory → Peak → Name Peak → Memory → Count → Name Each then_with() closure is lazily evaluated — zero overhead when the primary key already differs. The final name tiebreaker uses exact-case cmp (not to_lowercase) since it only needs to be deterministic.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
added graphical user interface
Type of Change
Related Issues
Checklist
cargo fmt— code is formattedcargo clippy— no lint errors (deny level)cargo test— all tests passcargo build --release— release build succeedscargo doc— documentation builds without warningsTesting
Screenshots / Output