diff --git a/pkg/gui/context/base_context.go b/pkg/gui/context/base_context.go index e4993828c..6c86f374e 100644 --- a/pkg/gui/context/base_context.go +++ b/pkg/gui/context/base_context.go @@ -21,6 +21,7 @@ type BaseContext struct { onRenderToMainFn func() onFocusFns []onFocusFn onFocusLostFns []onFocusLostFn + onQuitFns []func() focusable bool transient bool @@ -141,6 +142,7 @@ func (self *BaseContext) ClearAllAttachedControllerFunctions() { self.mouseKeybindingsFns = nil self.onFocusFns = nil self.onFocusLostFns = nil + self.onQuitFns = nil self.onDoubleClickFn = nil self.onClickFn = nil self.onClickFocusedMainViewFn = nil @@ -207,6 +209,12 @@ func (self *BaseContext) AddOnFocusLostFn(fn onFocusLostFn) { } } +func (self *BaseContext) AddOnQuitFn(fn func()) { + if fn != nil { + self.onQuitFns = append(self.onQuitFns, fn) + } +} + func (self *BaseContext) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding { bindings := []*gocui.ViewMouseBinding{} for i := range self.mouseKeybindingsFns { diff --git a/pkg/gui/context/simple_context.go b/pkg/gui/context/simple_context.go index f51d3dc5c..6405e91f5 100644 --- a/pkg/gui/context/simple_context.go +++ b/pkg/gui/context/simple_context.go @@ -54,6 +54,12 @@ func (self *SimpleContext) HandleFocusLost(opts types.OnFocusLostOpts) { } } +func (self *SimpleContext) HandleQuit() { + for _, fn := range self.onQuitFns { + fn() + } +} + func (self *SimpleContext) FocusLine(scrollIntoView bool) { } diff --git a/pkg/gui/controllers/attach.go b/pkg/gui/controllers/attach.go index c67c415a3..c9ef5d4b0 100644 --- a/pkg/gui/controllers/attach.go +++ b/pkg/gui/controllers/attach.go @@ -12,5 +12,6 @@ func AttachControllers(context types.Context, controllers ...types.IController) context.AddOnRenderToMainFn(controller.GetOnRenderToMain()) context.AddOnFocusFn(controller.GetOnFocus()) context.AddOnFocusLostFn(controller.GetOnFocusLost()) + context.AddOnQuitFn(controller.GetOnQuit()) } } diff --git a/pkg/gui/controllers/base_controller.go b/pkg/gui/controllers/base_controller.go index afd6cf210..4ea0b1fd3 100644 --- a/pkg/gui/controllers/base_controller.go +++ b/pkg/gui/controllers/base_controller.go @@ -38,3 +38,7 @@ func (self *baseController) GetOnFocus() func(types.OnFocusOpts) { func (self *baseController) GetOnFocusLost() func(types.OnFocusLostOpts) { return nil } + +func (self *baseController) GetOnQuit() func() { + return nil +} diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 3f62bfbc7..1da39ce05 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -935,7 +935,12 @@ func (gui *Gui) Run(startArgs appTypes.StartArgs) error { // setting here so we can use it in layout.go gui.integrationTest = startArgs.IntegrationTest - return gui.g.MainLoop() + err = gui.g.MainLoop() + if errors.Is(err, gocui.ErrQuit) { + // Give the focused context a chance to clean up before we tear down the app. + gui.c.Context().Current().HandleQuit() + } + return err } func (gui *Gui) RunAndHandleError(startArgs appTypes.StartArgs) error { diff --git a/pkg/gui/types/context.go b/pkg/gui/types/context.go index 09ed94e5a..5ef632196 100644 --- a/pkg/gui/types/context.go +++ b/pkg/gui/types/context.go @@ -105,6 +105,7 @@ type IBaseContext interface { AddOnRenderToMainFn(func()) AddOnFocusFn(func(OnFocusOpts)) AddOnFocusLostFn(func(OnFocusLostOpts)) + AddOnQuitFn(func()) } type Context interface { @@ -112,6 +113,7 @@ type Context interface { HandleFocus(opts OnFocusOpts) HandleFocusLost(opts OnFocusLostOpts) + HandleQuit() FocusLine(scrollIntoView bool) HandleRender() HandleRenderToMain() @@ -273,6 +275,10 @@ type IController interface { GetOnRenderToMain() func() GetOnFocus() func(OnFocusOpts) GetOnFocusLost() func(OnFocusLostOpts) + + // Implement this to get called when the app quits, and the controller's context has the focus. + // Useful for saving state on quit. + GetOnQuit() func() } type IList interface {