feat: add column visibility selector popup#261
Conversation
Docker Image Built Successfully |
ReviewGood feature overall — well-structured code with solid test coverage. A few issues worth addressing: Bug: Help popup regressionAdding the - │ u/U Uptime n/N Name c/C CPU │The help popup appears to have a fixed height and doesn't scroll, so users can no longer see sort help. Either expand the popup height or consolidate the UX issue: Host column toggle is misleadingThe Host column can be toggled in the column selector, but visibility is also gated by Options: either disable the Host row in the selector when only one host is connected, or decouple the Non-atomic config write (
|
|
Review: Nice feature overall - modular design in columns.rs looks good. Issues: (1) save_column_config ignores config_path:None intent - silently creates ~/.config/dtop/config.yaml when CLI flags are used. (2) Silent disk write failures - spawn_blocking JoinHandle dropped, write errors not surfaced in UI. (3) YAML comments stripped on save via serde_yaml round-trip. (4) visible_columns() allocates fresh Vec on every 500ms render frame - should be cached. (5) Minor: hidden column order not preserved in config round-trip. |
Code Review - Overall this is a well-structured feature with good test coverage. Four issues worth addressing: 1) Help popup lost sorting shortcuts - the u/n/c/m key bindings row was silently dropped from the snapshot when the v line was added (the popup ran out of height). Either increase popup height or combine lines to fit. 2) Non-atomic config write - write_column_config writes directly to the file which can corrupt it if interrupted mid-write; prefer writing to a temp file then renaming over the destination. 3) Config comments silently erased on save - serde_yaml drops all YAML comments when round-tripping; consider warning the user in the save prompt. 4) visible_columns allocates every frame (noted in PR description as known) - since ColumnConfig only changes on user interaction, caching in AppState like sorted_container_keys would be cleaner. Minor: Column Status label shows Status Icon in the popup but the table header is empty; renaming to Status avoids confusion. |
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create column_selector.rs with render_column_selector() function that displays a popup overlay showing column visibility checkboxes, re-order instructions, and save prompt. Wire it up in render.rs for ViewState::ColumnSelector. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace stub handle_column_selector_key with full implementation supporting navigation (up/down/j/k), toggle (Enter/Space), reorder (PageUp/PageDown), close with unsaved-change prompt (Esc/F), and YAML config persistence (y/n). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Refactor container_list.rs to read visible columns from app_state.column_config.visible_columns() instead of hardcoding them. All three rendering functions (create_container_row, create_header_row, create_table) now dynamically build cells/headers/constraints from the column config. Also fix default column order to Id, Status, Name to match the original hardcoded layout. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace custom has_changed() method with PartialEq derive and != operator - Always pass config_path to AppState regardless of CLI host source Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Apply rustfmt formatting - Collapse nested if statements per clippy::collapsible_if Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use spawn_blocking for config file I/O to avoid blocking async event loop - Extract close logic into handle_close_column_selector, removing synthetic KeyEvent - Only pass config_path when config file is actually in use (prevents silent overwrites) - Remove planning/spec docs from the repo Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use &str instead of String::new() for empty cells - Return &str from get_status_icon instead of .to_string() - Use Cow<'static, str> for header row to avoid allocating static strings Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
aa6b654 to
64c3e7e
Compare
|
test |
ReviewThis is a well-structured feature with good test coverage. A few issues worth addressing: Bugs: Host column confusion with single-host setups (src/ui/container_list.rs, src/ui/render.rs): The Host column is included in visible_columns() but filtered out by show_host_column in rendering. If a user has one host and Host is toggled visible in the selector, the checkbox shows [X] but the column never appears in the table. Either hide the Host entry from the selector when there is only one host, or explain that it auto-hides. from_config_strings does not enforce Name visibility (src/core/types.rs:644): The toggle() method prevents hiding Name interactively, but from_config_strings does not enforce it. A user who edits their config file to omit name from the columns list will end up with Name hidden. Should add a guard after building result to ensure Name is always visible. Help popup regression (src/ui/snapshots/...help_popup_enabled.snap): The snapshot diff shows the sort keys row (u/U Uptime n/N Name c/C CPU) was dropped from the help popup. Looks like an unintentional removal. Performance: visible_columns() allocates a Vec on every render frame (src/ui/container_list.rs:40): visible_columns() is called three times per render (rows, header, constraints) and allocates a new Vec each time. Since column config changes rarely, this could be cached in AppState and invalidated only on config change - same pattern as sorted_container_keys. UX: Save prompt Esc is confusing (src/core/app_state/columns.rs:274): When the save prompt is shown, pressing Esc dismisses the prompt and returns to the column selector. But since the user already pressed Esc/v to close, they likely want to exit entirely. Consider making Esc in the save prompt discard changes and close (the n behavior) rather than returning to the selector. No user feedback on save (src/core/app_state/columns.rs:347): When columns are saved, there is no visible confirmation. The tracing::debug! is not visible to users. A brief status line (like how connection errors are shown) would help. Minor: config_path is None when CLI hosts are provided (src/main.rs:880): This silently disables saving when --host flags are used. Worth surfacing in the UI - either grey out the save option or show a message like Save unavailable (CLI hosts in use). spawn_blocking result is dropped (src/core/app_state/columns.rs:359): The JoinHandle from spawn_blocking is dropped silently. If the write task panics, it would be unobserved. At minimum use let _ = to make the intent explicit. Overall this is solid work - the Cow<'static, str> header optimization, avoiding .to_string() on icons, the modular split, and the snapshot test coverage are all well done. |
Summary
vkey) to show/hide and reorder table columns in the container list viewcolumnsconfig key supports setting default visible columns and their orderDetails
Popup controls:
↑/↓orj/k— navigate columnsEnter/Space— toggle column visibility (Name is always visible)PageUp/PageDown— reorder columnsEscorv— close (prompts to save if changed)Config example:
Test plan
🤖 Generated with Claude Code