Commit a6e5daa
authored
feat: unified facets and quick action menu (#10)
* feat: implement unified facets and quick action menu (Option 2 + 3)
Completes the comprehensive TUI UX overhaul with unified facets model
and context-aware quick action menu system.
## Unified Facets Model (Task #5)
Plugin List Facets:
- Filters: All | Discover | Ready | Installed
- Sorts: ↑Name | ↑Updated | ↑Stars
- Visual separator (║) between filters and sorts
- Tab cycles through all facets, can filter AND sort simultaneously
Marketplace List Facets:
- Sorts: ↑Plugins | ↑Stars | ↑Name | ↑Updated
- Consistent Tab behavior across all views
## Quick Action Menu (Tasks #6-9)
Press Space for context-aware quick actions overlay:
Plugin List Menu:
- [m] Browse Marketplaces
- [f] Filter by Marketplace (opens picker)
- [s] Sort by (cycles sort modes)
- [v] Toggle View (card/slim)
- [u] Refresh Cache
Plugin Detail Menu (Discoverable):
- [i] Copy 2-Step Install (marketplace + plugin commands)
- [m] Copy Marketplace Install
- [p] Copy Plugin Install
- [g] Open on GitHub
- [l] Copy GitHub Link
Plugin Detail Menu (Installed):
- [o] Open Local Directory
- [p] Copy Local Path
- [g] Open on GitHub
- [l] Copy GitHub Link
Marketplace List Menu:
- [Enter] View Details
- [f] Show Plugins from This
- [i] Copy Install Command
- [g] Open on GitHub
## Features
**2-Step Install Copy (Task #8)**
- Press 'i' on discoverable plugins
- Copies formatted commands with comments:
# Step 1: Install marketplace
/plugin marketplace add owner/repo
# Step 2: Install plugin
/plugin install plugin-name@marketplace
**Enhanced Marketplace Picker (Task #7)**
- Shift+F as alternative trigger (in addition to @ autocomplete)
- Pre-fills @ in search box and activates picker
- Accessible from quick menu [f] action
**Updated Documentation (Task #10)**
- Help view updated with Space, Shift+F, 'i' shortcuts
- Terminology changed to "facets" throughout
- Context notes for each action
## Implementation Details
New Components:
- internal/ui/quick_menu.go (281 lines) - Complete quick menu system
- ViewQuickMenu state for overlay management
- Context-aware action generation based on view and plugin state
Enhanced Models:
- Facet struct for unified filter/sort representation
- GetPluginFacets() and GetMarketplaceFacets() methods
- NextFacet/PrevFacet for unified Tab navigation
- Plugin sort modes with applyPluginSort() logic
Testing & Quality (Task #11):
- All tests pass (14 test cases)
- Build successful
- Linter clean (1 pre-existing complexity warning)
- Comprehensive implementation log: docs/buzzminson/2026-02-04-tui-ux-improvements-tasks-5-11.md
## Breaking Changes
None - all existing functionality preserved, new features are additive.
* refactor: maximus code review - fixes and simplification
Applied automated code review cycle with critical bug fixes and
comprehensive simplification.
Fixes:
- Added empty facets guards to prevent division by zero panics
- URL validation before exec.Command (validates http/https scheme)
- Guard clauses in all facet navigation methods
Simplification:
- Consolidated facet cycling logic with cycleFacet() helper
- Extracted marketplace filtering into focused functions
- Unified marketplace sorting with safe stat extraction helpers
- Simplified viewport initialization with clampHeight utility
- Removed duplicate utility functions across files
- Improved code organization and readability
Quality Assurance:
- All tests passing
- Build successful
- Linter clean (1 pre-existing complexity warning)
- Code reviewed by feature-dev:code-reviewer
- Code simplified by code-simplifier:code-simplifier
* fix: allow plugins with same name from different marketplaces to coexist
Previously, plugins were deduplicated by name only, causing plugins with
the same name from different marketplaces to be filtered out. Now uses
plugin@marketplace as the deduplication key, allowing different plugins
with the same name to appear when they're from different sources.
* Updated .gitignore
* chore: add .mcp.json to .gitignore and debug utility
- Add .mcp.json to .gitignore (local MCP server config may contain secrets)
- Add cmd/debug-plugins utility for debugging plugin dedup issues
* refactor: comprehensive code quality improvements via maximus review
Applied all fixes from maximus code review cycle to address quality,
security, and maintainability issues identified before merge.
## Major Fixes
**1. Implemented complete plugin sort modes (internal/ui/model.go)**
- Fixed stub implementation in applyPluginSort()
- PluginSortName: Alphabetical sorting by plugin name
- PluginSortUpdated: Sort by marketplace last pushed date (from stats cache)
- PluginSortStars: Sort by marketplace GitHub stars (from stats cache)
- Graceful fallback to name sorting when stats unavailable
- Resolves: Sort modes ↑Updated and ↑Stars now functional
**2. Reduced handleListKeys cyclomatic complexity (internal/ui/update.go)**
- Refactored monolithic function (complexity 35+) into focused helpers
- Extracted 15+ single-purpose functions:
- Navigation: handleUpNavigation, handleDownNavigation, handlePageUp, etc.
- Actions: handleEnterKey, handleHelpKey, handleMarketplaceBrowser, etc.
- Setup: prepareDetailViewport, prepareHelpViewport
- Reduced main function complexity from 35+ to ~8
- Resolves: gocyclo linter warning eliminated
- Improved testability and maintainability
## Minor Fixes
**3. Enhanced KeyMsg synthesis reliability (internal/ui/quick_menu.go)**
- Improved ExecuteQuickMenuAction to handle multi-character keys
- Proper KeyMsg construction for both single and multi-char keys
- Ensures correct Type and Runes fields
**4. Added localhost URL validation (internal/ui/update.go)**
- Enhanced openURL() security with localhost rejection
- Blocks localhost, 127.0.0.1, and [::1] addresses
- Prevents potential local exploitation via malicious plugin URLs
**5. Documented TOCTOU race condition (internal/config/config.go)**
- Added clear documentation explaining negligible risk
- Read-only check in trusted local directory
- Current implementation acceptable for use case
## Quality Metrics
Pre-push checklist results:
- ✅ Linter: 0 issues (down from 1 complexity warning)
- ✅ Tests: All tests pass (8 packages)
- ✅ Build: Successful
Changes: +286 insertions, -180 deletions (net +106 lines)1 parent 3b2f546 commit a6e5daa
10 files changed
Lines changed: 1498 additions & 497 deletions
File tree
- cmd/debug-plugins
- docs/buzzminson
- internal
- config
- ui
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
Lines changed: 307 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
0 commit comments