Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 19 additions & 12 deletions pkg/gui/arrangement.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,23 +176,30 @@ func (gui *Gui) sidePanelChildren(width int, height int) []*boxlayout.Box {
}

// The project panel is compact (Size: 3) when not focused, but expands
// when focused to show the list of projects.
projectBox := &boxlayout.Box{
Window: sideWindowNames[0],
Size: 3,
}
if currentWindow == sideWindowNames[0] {
projectBox = &boxlayout.Box{
// when focused to show the list of projects. This only applies when the
// project panel is actually visible (i.e. we are inside a compose project).
if len(sideWindowNames) > 0 && sideWindowNames[0] == "project" {
projectBox := &boxlayout.Box{
Window: sideWindowNames[0],
Weight: 2,
Size: 3,
}
if currentWindow == sideWindowNames[0] {
projectBox = &boxlayout.Box{
Window: sideWindowNames[0],
Weight: 2,
}
}

return append([]*boxlayout.Box{
projectBox,
}, lo.Map(sideWindowNames[1:], func(window string, _ int) *boxlayout.Box {
return accordionBox(&boxlayout.Box{Window: window, Weight: 1})
})...)
}

return append([]*boxlayout.Box{
projectBox,
}, lo.Map(sideWindowNames[1:], func(window string, _ int) *boxlayout.Box {
return lo.Map(sideWindowNames, func(window string, _ int) *boxlayout.Box {
return accordionBox(&boxlayout.Box{Window: window, Weight: 1})
})...)
})
} else {
squashedHeight := 1
if height >= 21 {
Expand Down
41 changes: 26 additions & 15 deletions pkg/gui/containers_panel.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,25 +83,36 @@ func (gui *Gui) getContainersPanel() *panels.SideListPanel[*commands.Container]
return sortContainers(a, b, gui.Config.UserConfig.Gui.LegacySortContainers)
},
Filter: func(container *commands.Container) bool {
// Note that this is O(N*M) time complexity where N is the number of services
// and M is the number of containers. We expect N to be small but M may be large,
// so we will need to keep an eye on this.
if !gui.Config.UserConfig.Gui.ShowAllContainers && !isStandaloneContainer(container) {
return false
}

if !gui.State.ShowExitedContainers && container.Container.State == "exited" {
return false
}

// Filter by selected project. Containers with no project (truly
// standalone, not from any compose project) are always shown.
selectedProject := gui.getSelectedProjectName()
if selectedProject == "" {
selectedProject = gui.DockerCommand.LocalProjectName
}
if selectedProject != "" && container.ProjectName != "" && container.ProjectName != selectedProject {
return false
// Only apply project and standalone filtering when we are inside a
// docker-compose project. Outside of a compose project all
// containers are shown in a flat list regardless of which compose
// project they belong to.
if gui.DockerCommand.InDockerComposeProject {
// This check must be inside the InDockerComposeProject guard:
// outside a compose project, services are still derived from
// container labels, so compose-managed containers from other
// projects would be incorrectly hidden.
//
// Note that this is O(N*M) time complexity where N is the number of services
// and M is the number of containers. We expect N to be small but M may be large,
// so we will need to keep an eye on this.
if !gui.Config.UserConfig.Gui.ShowAllContainers && !isStandaloneContainer(container) {
return false
}

// Filter by selected project. Containers with no project (truly
// standalone, not from any compose project) are always shown.
selectedProject := gui.getSelectedProjectName()
if selectedProject == "" {
selectedProject = gui.DockerCommand.LocalProjectName
}
if selectedProject != "" && container.ProjectName != "" && container.ProjectName != selectedProject {
return false
}
}
Comment on lines +90 to 116

Copilot AI Apr 19, 2026

Copy link

Choose a reason for hiding this comment

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

The filtering behaviour here changed significantly (project filtering is now conditional on InDockerComposeProject). Since this impacts which containers are visible, it would be good to add unit tests covering the Filter logic for (a) InDockerComposeProject=false => compose-labelled containers are not hidden, and (b) InDockerComposeProject=true with ShowAllContainers toggled and selectedProject set/unset to ensure the expected inclusion/exclusion.

Copilot uses AI. Check for mistakes.

return true
Expand Down
8 changes: 8 additions & 0 deletions pkg/gui/project_panel.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ func (gui *Gui) getProjectPanel() *panels.SideListPanel[*commands.Project] {
// containers to show only those belonging to the selected project.
return gui.renderContainersAndServices()
},
Hide: func() bool {
// Only show the project panel when we are inside a docker-compose
// project directory. When launched outside of a compose project
// there is no meaningful local project to display, so we hide the
// panel and let the containers panel show all containers in a flat
// list (matching the behaviour from before v0.25).
return !gui.DockerCommand.InDockerComposeProject
},
}
}

Expand Down
8 changes: 6 additions & 2 deletions pkg/gui/services_panel.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,12 @@ func (gui *Gui) getServicesPanel() *panels.SideListPanel[*commands.Service] {
return presentation.GetServiceDisplayStrings(&gui.Config.UserConfig.Gui, service)
},
Hide: func() bool {
// Show services panel if there are any compose projects (local or discovered)
return !gui.DockerCommand.InDockerComposeProject && len(gui.Panels.Services.List.GetAllItems()) == 0
// Only show the services panel when we are inside a docker-compose
// project directory. When launched outside of a compose project
// there is no local project context, so the panel is hidden and
// all containers are shown in a flat list (matching pre-v0.25
// behaviour).
return !gui.DockerCommand.InDockerComposeProject
},
}
}
Expand Down
Loading