Skip to content

feat: Multi-select with bulk install/uninstall#52

Open
hanthor wants to merge 2 commits intoValkyrie00:mainfrom
hanthor:feature/multi-select
Open

feat: Multi-select with bulk install/uninstall#52
hanthor wants to merge 2 commits intoValkyrie00:mainfrom
hanthor:feature/multi-select

Conversation

@hanthor
Copy link

@hanthor hanthor commented Jan 13, 2026

Implements multi-select functionality using Spacebar, allowing bulk install (I) and uninstall (U).

Copilot AI review requested due to automatic review settings January 13, 2026 15:50
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements multi-select functionality for the package table interface, allowing users to select multiple packages using the Spacebar key and perform bulk operations (install, remove, update) on the selected items.

Changes:

  • Added multi-select support to the Table component with visual highlighting
  • Integrated bulk operation support into install, remove, and update actions
  • Added Spacebar key binding for toggling row selection

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

File Description
internal/ui/components/table.go Adds selectedRows map to track multi-selected rows and methods for toggling, clearing, and retrieving selections with visual feedback
internal/services/input.go Implements spacebar key handler for selection toggling and modifies install/remove/update handlers to process multiple selected packages
Makefile Adds :Z SELinux label flag to podman volume mount for better compatibility
.env Changes build target platform from darwin/arm64 to linux/amd64

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

return nil
}

for _, input := range s.keyActions {
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spacebar key is handled explicitly before the general key action loop (lines 177-181), but it will also match in the loop (lines 183-195) if ActionToggleSelection is in keyActions. This creates redundant handling. Consider either removing the explicit handling at lines 177-181 or ensuring ActionToggleSelection is not added to keyActions (it's currently added at line 138 but marked with HideFromLegend=true).

Suggested change
for _, input := range s.keyActions {
for _, input := range s.keyActions {
// Skip ActionToggleSelection here because space is already handled explicitly above.
if input == s.ActionToggleSelection {
continue
}

Copilot uses AI. Check for mistakes.
t.selectedRows = make(map[int]bool)
}

func (t *Table) ClearSelection() {
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ClearSelection method only resets the selectedRows map but doesn't update the visual state of the table cells. This means previously selected rows will still appear highlighted until the table is redrawn. Consider iterating through the current selectedRows before clearing and resetting their background colors, or update the method to accept a theme parameter and properly reset cell backgrounds.

Suggested change
func (t *Table) ClearSelection() {
func (t *Table) ClearSelection() {
// Reset visual state for all currently selected rows
for row := range t.selectedRows {
colCount := t.view.GetColumnCount()
for col := 0; col < colCount; col++ {
cell := t.view.GetCell(row, col)
if cell != nil {
cell.SetBackgroundColor(t.theme.DefaultBgColor)
}
}
}
// Clear logical selection state

Copilot uses AI. Check for mistakes.
Comment on lines +76 to 82
func (t *Table) GetSelectedRows() []int {
rows := make([]int, 0, len(t.selectedRows))
for row := range t.selectedRows {
rows = append(rows, row)
}
return rows
}
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GetSelectedRows method returns rows in non-deterministic order since it iterates over a map. This could lead to unpredictable behavior when processing selected packages. Consider sorting the returned slice to ensure consistent ordering (e.g., ascending by row number).

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +6
BUILD_GOOS=linux
BUILD_GOARCH=amd64 No newline at end of file
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes to BUILD_GOOS and BUILD_GOARCH appear unrelated to the multi-select feature. These settings change the build target from macOS ARM64 (darwin/arm64) to Linux AMD64 (linux/amd64). If this change is intentional, it should be documented in the PR description or split into a separate commit. If unintentional, it should be reverted to the original values.

Suggested change
BUILD_GOOS=linux
BUILD_GOARCH=amd64
BUILD_GOOS=darwin
BUILD_GOARCH=arm64

Copilot uses AI. Check for mistakes.
theme *theme.Theme
view *tview.Table
theme *theme.Theme
selectedRows map[int]bool
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The selectedRows map is accessed without synchronization from both the UI thread (in ToggleSelection, GetSelectedRows) and from goroutines (ClearSelection is called from a goroutine at line 500). This creates a potential race condition. Consider using a sync.RWMutex to protect concurrent access to the selectedRows map, or ensure ClearSelection is called on the main thread using QueueUpdateDraw.

Copilot uses AI. Check for mistakes.
Comment on lines +205 to +210
// Force redraw of table to remove selection visuals
// s.appService.forceRefreshResults() // Might be too heavy?
// Actually Table.ToggleSelection updates visual.
// ClearSelection needs to update visual too.
// But Table.ClearSelection just clears the map. I need to implement visual clear in Table or just force refresh.
// For now, let's just assume we need to refresh.
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove commented code and TODO comments. This appears to be debugging/development notes that should be cleaned up before merging. The actual implementation at line 211 (s.appService.search(...)) addresses the visual refresh concern mentioned in the comments.

Suggested change
// Force redraw of table to remove selection visuals
// s.appService.forceRefreshResults() // Might be too heavy?
// Actually Table.ToggleSelection updates visual.
// ClearSelection needs to update visual too.
// But Table.ClearSelection just clears the map. I need to implement visual clear in Table or just force refresh.
// For now, let's just assume we need to refresh.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants