Enhance Category Manager UX and Implement Robust Settings Validation#421
Enhance Category Manager UX and Implement Robust Settings Validation#421SuperCoolPencil merged 15 commits intomainfrom
Conversation
…validation feedback
Binary Size Analysis
|
| // Categories tab → 'Manage Categories' selected → confirm full reset | ||
| if m.SettingsActiveTab < len(categories) && categories[m.SettingsActiveTab] == "Categories" && settingKey == "category_enabled" { | ||
| m.state = CategoryResetConfirmState | ||
| m.quitConfirmFocused = 0 | ||
| return m, nil | ||
| } |
There was a problem hiding this comment.
Reset intercept breaks
category_enabled and is semantically mismatched
The Reset key handler for category_enabled returns early in both branches of the modal, which means the CategoryEnabled boolean can never be reset to its default through this code path. If the user confirms, all custom categories are wiped but CategoryEnabled itself is left unchanged. If the user cancels, nothing at all happens — the expected reset of the boolean is silently skipped.
category_enabled is a simple boolean toggle (CategorySettings.CategoryEnabled), so wiring its "Reset to Default" action to a full-category-wipe confirmation is semantically wrong. Consider using a dedicated key (e.g., the Edit key on the "Manage Categories" row if one exists) to open the reset modal, and letting the existing resetSettingToDefault path handle category_enabled normally.
Prompt To Fix With AI
This is a comment left during a code review.
Path: internal/tui/update_settings.go
Line: 237-242
Comment:
**Reset intercept breaks `category_enabled` and is semantically mismatched**
The Reset key handler for `category_enabled` returns early in both branches of the modal, which means the `CategoryEnabled` boolean can **never** be reset to its default through this code path. If the user confirms, all custom categories are wiped but `CategoryEnabled` itself is left unchanged. If the user cancels, nothing at all happens — the expected reset of the boolean is silently skipped.
`category_enabled` is a simple boolean toggle (`CategorySettings.CategoryEnabled`), so wiring its "Reset to Default" action to a full-category-wipe confirmation is semantically wrong. Consider using a dedicated key (e.g., the `Edit` key on the "Manage Categories" row if one exists) to open the reset modal, and letting the existing `resetSettingToDefault` path handle `category_enabled` normally.
How can I resolve this? If you propose a fix, please make it concise.|
I have verified the implementation of all Greptile suggestions (Proxy URL validation, shared DNS helper, category fallback path, default reset values, and TUI error clearing). Additionally, I fixed the SA1019 lint error in internal/config/settings_test.go by migrating from reflect.PtrTo to reflect.PointerTo. All tests and linting are now passing. |
This PR improves the Category Manager UX and introduces a comprehensive validation system for all application settings.
Key Changes:
Category Manager
Settings & Validation
Documentation & Tests
Greptile Summary
This PR adds a hierarchical settings validation system with per-group
Validate()methods, partial rollback of invalid fields on startup, real-time TUI error feedback for settings and the category manager, Up/Down field navigation, and a reset confirmation modal for categories. The implementation is solid — the sharedValidateDNSListhelper eliminates the previously duplicated DNS parsing, proxy URL validation now correctly checks for emptyScheme/Host, and theupdateCategoryResetConfirmhandler correctly derives defaults fromconfig.DefaultSettings(). Only P2 findings remain: the newviewCategoryResetConfirmintroduces a third verbatim copy of the button-rendering boilerplate, and the new test suite is missing coverage for the category path-rollback branch.Confidence Score: 5/5
Safe to merge — no P0 or P1 findings; all remaining feedback is non-blocking style and test coverage.
Only P2 findings present: a style concern around duplicated button-rendering boilerplate and a missing test case for category path rollback. No runtime errors, data loss risk, or security issues were identified.
internal/tui/view.go (button rendering duplication) and internal/config/settings_test.go (missing category path rollback test).
Important Files Changed
Comments Outside Diff (4)
internal/config/settings.go, line 104-109 (link)url.Parsewon't catch invalid proxy URLsurl.Parsein Go is extremely permissive and almost never returns an error. Strings like"badproxy","://noscheme", or"ftp://missing-host"all parse without error, resulting in aurl.URLwith emptySchemeorHost. The self-healing behavior documented inSETTINGS.md— "Proxy URLs are validated for correct syntax" — will silently skip any invalid proxy URL read from disk, leaving the broken value in place.The TUI's
validateSetting(inupdate_settings.go) correctly guards against this by checkingu.Scheme == "" || u.Host == "". The same guard should be applied here:Prompt To Fix With AI
internal/tui/update_modals.go, line 621-630 (link)falseshould be derived from defaultsCategoryEnabledis reset to a hardcodedfalserather than the value returned byconfig.DefaultSettings(). This means if the default ever changes (e.g., totrue), this reset path diverges silently. Using the defaults struct is consistent with how every other field is rolled back inresetSettingToDefaultandValidate():This also avoids having to remember to update two places if a new
CategorySettingsfield is added.Prompt To Fix With AI
internal/tui/update_settings.go, line 692-695 (link)The error is cleared only when
m.SettingsInput.Value() != "". If a user types an invalid value (error appears), then deletes all characters, the error remains shown even though the input field is now empty. The condition should just check whetherm.settingsError != ""to clear it on any keystroke:Prompt To Fix With AI
internal/config/settings.go, line 112-136 (link)The DNS-parsing loop (split on
,,net.SplitHostPort,net.ParseIP) is essentially identical to the one invalidateSettinginupdate_settings.go. Per the project's no-duplicate-logic rule, consider extracting a shared helper (e.g.,config.ValidateDNSList(s string) error) that both call, so any future changes (hostname support, IPv6 tweaks) only need to be made in one place.Rule Used: What: Eliminate duplicate logic, functions, or cod... (source)
Prompt To Fix With AI
Prompt To Fix All With AI
Reviews (5): Last reviewed commit: "refactor: replace deprecated reflect.Ptr..." | Re-trigger Greptile
Context used: