on main help sign in
fix(tui): further guard against type accessor and map panics (#783)
15b989cChristian Rocha
internal/tui/tui.go+65−17
@@ -76,8 +76,13 @@ type appModel struct {
76
76
77// Init initializes the application model and returns initial commands.
77// Init initializes the application model and returns initial commands.
78func (a appModel) Init() tea.Cmd {
78func (a appModel) Init() tea.Cmd {
79+ item, ok := a.pages[a.currentPage]
80+ if !ok {
81+ return nil
82+ }
83+
79 var cmds []tea.Cmd
84 var cmds []tea.Cmd
80− cmd := a.pages[a.currentPage].Init()
85+ cmd := item.Init()
81 cmds = append(cmds, cmd)
86 cmds = append(cmds, cmd)
82 a.loadedPages[a.currentPage] = true
87 a.loadedPages[a.currentPage] = true
83
88
@@ -99,7 +104,10 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
99 case tea.KeyboardEnhancementsMsg:
104 case tea.KeyboardEnhancementsMsg:
100 for id, page := range a.pages {
105 for id, page := range a.pages {
101 m, pageCmd := page.Update(msg)
106 m, pageCmd := page.Update(msg)
107+ if model, ok := m.(util.Model); ok {
102− a.pages[id] = m.(util.Model)
108+ a.pages[id] = model
109+ }
110+
103 if pageCmd != nil {
111 if pageCmd != nil {
104 cmds = append(cmds, pageCmd)
112 cmds = append(cmds, pageCmd)
105 }
113 }
@@ -114,7 +122,10 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
114 case completions.OpenCompletionsMsg, completions.FilterCompletionsMsg,
122 case completions.OpenCompletionsMsg, completions.FilterCompletionsMsg,
115 completions.CloseCompletionsMsg, completions.RepositionCompletionsMsg:
123 completions.CloseCompletionsMsg, completions.RepositionCompletionsMsg:
116 u, completionCmd := a.completions.Update(msg)
124 u, completionCmd := a.completions.Update(msg)
117− a.completions = u.(completions.Completions)
125+ if model, ok := u.(completions.Completions); ok {
126+ a.completions = model
127+ }
128+
118 return a, completionCmd
129 return a, completionCmd
119
130
120 // Dialog messages
131 // Dialog messages
@@ -214,9 +225,12 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
214 return a, nil
225 return a, nil
215 }
226 }
216
227
217− // forward to page
228+ // Forward to view.
218 updated, itemCmd := item.Update(msg)
229 updated, itemCmd := item.Update(msg)
230+ if model, ok := updated.(util.Model); ok {
219− a.pages[a.currentPage] = updated.(util.Model)
231+ a.pages[a.currentPage] = model
232+ }
233+
220 return a, itemCmd
234 return a, itemCmd
221 case pubsub.Event[permission.PermissionRequest]:
235 case pubsub.Event[permission.PermissionRequest]:
222 return a, util.CmdHandler(dialogs.OpenDialogMsg{
236 return a, util.CmdHandler(dialogs.OpenDialogMsg{
@@ -241,7 +255,10 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
241 // Forward agent events to dialogs
255 // Forward agent events to dialogs
242 if a.dialog.HasDialogs() && a.dialog.ActiveDialogID() == compact.CompactDialogID {
256 if a.dialog.HasDialogs() && a.dialog.ActiveDialogID() == compact.CompactDialogID {
243 u, dialogCmd := a.dialog.Update(payload)
257 u, dialogCmd := a.dialog.Update(payload)
244− a.dialog = u.(dialogs.DialogCmp)
258+ if model, ok := u.(dialogs.DialogCmp); ok {
259+ a.dialog = model
260+ }
261+
245 cmds = append(cmds, dialogCmd)
262 cmds = append(cmds, dialogCmd)
246 }
263 }
247
264
@@ -270,7 +287,10 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
270
287
271 a.isConfigured = config.HasInitialDataConfig()
288 a.isConfigured = config.HasInitialDataConfig()
272 updated, pageCmd := item.Update(msg)
289 updated, pageCmd := item.Update(msg)
290+ if model, ok := updated.(util.Model); ok {
273− a.pages[a.currentPage] = updated.(util.Model)
291+ a.pages[a.currentPage] = model
292+ }
293+
274 cmds = append(cmds, pageCmd)
294 cmds = append(cmds, pageCmd)
275 return a, tea.Batch(cmds...)
295 return a, tea.Batch(cmds...)
276
296
@@ -289,14 +309,20 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
289 }
309 }
290
310
291 updated, pageCmd := item.Update(msg)
311 updated, pageCmd := item.Update(msg)
312+ if model, ok := updated.(util.Model); ok {
292− a.pages[a.currentPage] = updated.(util.Model)
313+ a.pages[a.currentPage] = model
314+ }
315+
293 cmds = append(cmds, pageCmd)
316 cmds = append(cmds, pageCmd)
294 }
317 }
295 return a, tea.Batch(cmds...)
318 return a, tea.Batch(cmds...)
296 case tea.PasteMsg:
319 case tea.PasteMsg:
297 if a.dialog.HasDialogs() {
320 if a.dialog.HasDialogs() {
298 u, dialogCmd := a.dialog.Update(msg)
321 u, dialogCmd := a.dialog.Update(msg)
299− a.dialog = u.(dialogs.DialogCmp)
322+ if model, ok := u.(dialogs.DialogCmp); ok {
323+ a.dialog = model
324+ }
325+
300 cmds = append(cmds, dialogCmd)
326 cmds = append(cmds, dialogCmd)
301 } else {
327 } else {
302 item, ok := a.pages[a.currentPage]
328 item, ok := a.pages[a.currentPage]
@@ -305,7 +331,10 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
305 }
331 }
306
332
307 updated, pageCmd := item.Update(msg)
333 updated, pageCmd := item.Update(msg)
334+ if model, ok := updated.(util.Model); ok {
308− a.pages[a.currentPage] = updated.(util.Model)
335+ a.pages[a.currentPage] = model
336+ }
337+
309 cmds = append(cmds, pageCmd)
338 cmds = append(cmds, pageCmd)
310 }
339 }
311 return a, tea.Batch(cmds...)
340 return a, tea.Batch(cmds...)
@@ -317,12 +346,18 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
317 if !ok {
346 if !ok {
318 return a, nil
347 return a, nil
319 }
348 }
349+
320 updated, cmd := item.Update(msg)
350 updated, cmd := item.Update(msg)
351+ if model, ok := updated.(util.Model); ok {
321− a.pages[a.currentPage] = updated.(util.Model)
352+ a.pages[a.currentPage] = model
353+ }
322
354
323 if a.dialog.HasDialogs() {
355 if a.dialog.HasDialogs() {
324 u, dialogCmd := a.dialog.Update(msg)
356 u, dialogCmd := a.dialog.Update(msg)
325− a.dialog = u.(dialogs.DialogCmp)
357+ if model, ok := u.(dialogs.DialogCmp); ok {
358+ a.dialog = model
359+ }
360+
326 cmds = append(cmds, dialogCmd)
361 cmds = append(cmds, dialogCmd)
327 }
362 }
328 cmds = append(cmds, cmd)
363 cmds = append(cmds, cmd)
@@ -332,27 +367,38 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
332// handleWindowResize processes window resize events and updates all components.
367// handleWindowResize processes window resize events and updates all components.
333func (a *appModel) handleWindowResize(width, height int) tea.Cmd {
368func (a *appModel) handleWindowResize(width, height int) tea.Cmd {
334 var cmds []tea.Cmd
369 var cmds []tea.Cmd
370+
371+ // TODO: clean up these magic numbers.
335 if a.showingFullHelp {
372 if a.showingFullHelp {
336 height -= 5
373 height -= 5
337 } else {
374 } else {
338 height -= 2
375 height -= 2
339 }
376 }
377+
340 a.width, a.height = width, height
378 a.width, a.height = width, height
341 // Update status bar
379 // Update status bar
342 s, cmd := a.status.Update(tea.WindowSizeMsg{Width: width, Height: height})
380 s, cmd := a.status.Update(tea.WindowSizeMsg{Width: width, Height: height})
343− a.status = s.(status.StatusCmp)
381+ if model, ok := s.(status.StatusCmp); ok {
382+ a.status = model
383+ }
344 cmds = append(cmds, cmd)
384 cmds = append(cmds, cmd)
345
385
346− // Update the current page
386+ // Update the current view.
347 for p, page := range a.pages {
387 for p, page := range a.pages {
348 updated, pageCmd := page.Update(tea.WindowSizeMsg{Width: width, Height: height})
388 updated, pageCmd := page.Update(tea.WindowSizeMsg{Width: width, Height: height})
389+ if model, ok := updated.(util.Model); ok {
349− a.pages[p] = updated.(util.Model)
390+ a.pages[p] = model
391+ }
392+
350 cmds = append(cmds, pageCmd)
393 cmds = append(cmds, pageCmd)
351 }
394 }
352
395
353 // Update the dialogs
396 // Update the dialogs
354 dialog, cmd := a.dialog.Update(tea.WindowSizeMsg{Width: width, Height: height})
397 dialog, cmd := a.dialog.Update(tea.WindowSizeMsg{Width: width, Height: height})
355− a.dialog = dialog.(dialogs.DialogCmp)
398+ if model, ok := dialog.(dialogs.DialogCmp); ok {
399+ a.dialog = model
400+ }
401+
356 cmds = append(cmds, cmd)
402 cmds = append(cmds, cmd)
357
403
358 return tea.Batch(cmds...)
404 return tea.Batch(cmds...)
@@ -443,7 +489,9 @@ func (a *appModel) handleKeyPressMsg(msg tea.KeyPressMsg) tea.Cmd {
443 }
489 }
444
490
445 updated, cmd := item.Update(msg)
491 updated, cmd := item.Update(msg)
492+ if model, ok := updated.(util.Model); ok {
446− a.pages[a.currentPage] = updated.(util.Model)
493+ a.pages[a.currentPage] = model
494+ }
447 return cmd
495 return cmd
448 }
496 }
449}
497}