diff options
author | Robin Jarry <robin@jarry.cc> | 2023-09-05 21:55:11 +0200 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2023-09-19 16:49:59 +0200 |
commit | c2a4fc7fdfae6469e782c5daac6772e3ec4d52cb (patch) | |
tree | ae8220806157571c02bfda0bdb6dff9c1230b5bd /widgets/compose.go | |
parent | 43df87552c2c54a7cc346cb044d08dc8ee5b6925 (diff) | |
download | aerc-c2a4fc7fdfae6469e782c5daac6772e3ec4d52cb.tar.gz |
compose: avoid panic when deleting the last header
When removing the last header, the focusable list may be empty, and the
focused index becomes invalid. Avoid out of bounds access.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Inwit <inwit@sindominio.net>
Diffstat (limited to 'widgets/compose.go')
-rw-r--r-- | widgets/compose.go | 73 |
1 files changed, 49 insertions, 24 deletions
diff --git a/widgets/compose.go b/widgets/compose.go index 1c0aaab5..5db377be 100644 --- a/widgets/compose.go +++ b/widgets/compose.go @@ -743,9 +743,9 @@ func (c *Composer) focusTerminalPriv() *Composer { if c.editor == nil { return c } - c.focusable[c.focused].Focus(false) - c.focused = len(c.editors) - c.focusable[c.focused].Focus(true) + c.focusActiveWidget(false) + c.focused = len(c.focusable) - 1 + c.focusActiveWidget(true) return c } @@ -803,18 +803,31 @@ func (c *Composer) Bindings() string { switch c.editor { case nil: return "compose::review" - case c.focusable[c.focused]: + case c.focusedWidget(): return "compose::editor" default: return "compose" } } +func (c *Composer) focusedWidget() ui.MouseableDrawableInteractive { + if c.focused < 0 || c.focused >= len(c.focusable) { + return nil + } + return c.focusable[c.focused] +} + +func (c *Composer) focusActiveWidget(focus bool) { + if w := c.focusedWidget(); w != nil { + w.Focus(focus) + } +} + func (c *Composer) Event(event tcell.Event) bool { c.Lock() defer c.Unlock() - if c.editor != nil { - return c.focusable[c.focused].Event(event) + if w := c.focusedWidget(); c.editor != nil && w != nil { + return w.Event(event) } return false } @@ -834,9 +847,9 @@ func (c *Composer) MouseEvent(localX int, localY int, event tcell.Event) { for i, e := range c.focusable { he, ok := e.(*headerEditor) if ok && he.focused { - c.focusable[c.focused].Focus(false) + c.focusActiveWidget(false) c.focused = i - c.focusable[c.focused].Focus(true) + c.focusActiveWidget(true) return } } @@ -844,14 +857,16 @@ func (c *Composer) MouseEvent(localX int, localY int, event tcell.Event) { func (c *Composer) Focus(focus bool) { c.Lock() - c.focusable[c.focused].Focus(focus) + c.focusActiveWidget(focus) c.Unlock() } func (c *Composer) Show(visible bool) { c.Lock() - if vis, ok := c.focusable[c.focused].(ui.Visible); ok { - vis.Show(visible) + if w := c.focusedWidget(); w != nil { + if vis, ok := w.(ui.Visible); ok { + vis.Show(visible) + } } c.Unlock() } @@ -1323,12 +1338,12 @@ func (c *Composer) PrevField() { if c.editHeaders && c.editor != nil { return } - c.focusable[c.focused].Focus(false) + c.focusActiveWidget(false) c.focused-- if c.focused == -1 { c.focused = len(c.focusable) - 1 } - c.focusable[c.focused].Focus(true) + c.focusActiveWidget(true) } func (c *Composer) NextField() { @@ -1337,9 +1352,9 @@ func (c *Composer) NextField() { if c.editHeaders && c.editor != nil { return } - c.focusable[c.focused].Focus(false) + c.focusActiveWidget(false) c.focused = (c.focused + 1) % len(c.focusable) - c.focusable[c.focused].Focus(true) + c.focusActiveWidget(true) } func (c *Composer) FocusEditor(editor string) { @@ -1353,7 +1368,7 @@ func (c *Composer) FocusEditor(editor string) { func (c *Composer) focusEditor(editor string) { editor = strings.ToLower(editor) - c.focusable[c.focused].Focus(false) + c.focusActiveWidget(false) for i, f := range c.focusable { e := f.(*headerEditor) if strings.ToLower(e.name) == editor { @@ -1361,7 +1376,7 @@ func (c *Composer) focusEditor(editor string) { break } } - c.focusable[c.focused].Focus(true) + c.focusActiveWidget(true) } // AddEditor appends a new header editor to the compose window. @@ -1397,12 +1412,22 @@ func (c *Composer) addEditor(header string, value string, appendHeader bool) str } c.editors[header] = e c.layout = append(c.layout, []string{header}) - // Insert focus of new editor before terminal editor - c.focusable = append( - c.focusable[:len(c.focusable)-1], - e, - c.focusable[len(c.focusable)-1], - ) + switch { + case len(c.focusable) == 0: + c.focusable = []ui.MouseableDrawableInteractive{e} + case c.editor != nil: + // Insert focus of new editor before terminal editor + c.focusable = append( + c.focusable[:len(c.focusable)-1], + e, + c.focusable[len(c.focusable)-1], + ) + default: + c.focusable = append( + c.focusable[:len(c.focusable)-1], + e, + ) + } editor = e } @@ -1463,8 +1488,8 @@ func (c *Composer) delEditor(header string) { focusable = append(focusable, f) } } - focusable[c.focused].Focus(true) c.focusable = focusable + c.focusActiveWidget(true) delete(c.editors, header) } |