fix(ui): completions: load files asynchronously

Ayman Bagabas created

Change summary

internal/ui/completions/completions.go | 15 +++++++++++----
internal/ui/model/ui.go                |  7 ++++++-
2 files changed, 17 insertions(+), 5 deletions(-)

Detailed changes

internal/ui/completions/completions.go 🔗

@@ -29,6 +29,11 @@ type SelectionMsg struct {
 // ClosedMsg is sent when the completions are closed.
 type ClosedMsg struct{}
 
+// FilesLoadedMsg is sent when files have been loaded for completions.
+type FilesLoadedMsg struct {
+	Files []string
+}
+
 // Completions represents the completions popup component.
 type Completions struct {
 	// Popup dimensions
@@ -88,10 +93,12 @@ func (c *Completions) KeyMap() KeyMap {
 }
 
 // OpenWithFiles opens the completions with file items from the filesystem.
-func (c *Completions) OpenWithFiles(depth, limit int) {
-	files, _, _ := fsext.ListDirectory(".", nil, depth, limit)
-	slices.Sort(files)
-	c.SetFiles(files)
+func (c *Completions) OpenWithFiles(depth, limit int) tea.Cmd {
+	return func() tea.Msg {
+		files, _, _ := fsext.ListDirectory(".", nil, depth, limit)
+		slices.Sort(files)
+		return FilesLoadedMsg{Files: files}
+	}
 }
 
 // SetFiles sets the file items on the completions popup.

internal/ui/model/ui.go 🔗

@@ -371,6 +371,11 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		cmds = append(cmds, clearInfoMsgCmd(ttl))
 	case uiutil.ClearStatusMsg:
 		m.status.ClearInfoMsg()
+	case completions.FilesLoadedMsg:
+		// Handle async file loading for completions.
+		if m.completionsOpen {
+			m.completions.SetFiles(msg.Files)
+		}
 	}
 
 	// This logic gets triggered on any message type, but should it?
@@ -878,7 +883,7 @@ func (m *UI) handleKeyPressMsg(msg tea.KeyPressMsg) tea.Cmd {
 						m.completionsStartIndex = curIdx
 						m.completionsPositionStart = m.completionsPosition()
 						depth, limit := m.com.Config().Options.TUI.Completions.Limits()
-						m.completions.OpenWithFiles(depth, limit)
+						cmds = append(cmds, m.completions.OpenWithFiles(depth, limit))
 					}
 				}