Skip to content

Commit 69391d2

Browse files
committed
allow skipping the asyncWork definition
1 parent a22a288 commit 69391d2

2 files changed

Lines changed: 33 additions & 20 deletions

File tree

internal/ui/dialog/file_history_overlay.go

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -804,29 +804,23 @@ func (o *FileHistoryOverlay) restoreSelectedVersion() {
804804
DiffState: entry.DiffState,
805805
}
806806

807-
// 1. Dummy handler to trigger the async sequence
808-
asyncWork := func(d *SelectionDialog, action DialogActionId) error {
809-
return nil
810-
}
811-
812807
onComplete := func(d *SelectionDialog, option *DialogOption, err error) {
813-
d.Close()
814-
808+
// Only trigger chain logic if we are doing a restore
815809
if option.Id == RestoreFileDialogRestoreFileActionId || option.Id == RestoreFileDialogRestoreRecursiveActionId {
816810

817-
// FIX: Forcefully drop the focus back to the persistent table layout *before* // mounting the next dialog. This guarantees the Progress Dialog will record
818-
// the table as its fallback focus instead of the dying Selection Dialog.
819-
o.application.SetFocus(o.tableContainer.GetLayout())
820-
821-
// Mount directly (We are already safely inside the main UI thread)
822-
progressDialog := NewRestoreFileProgressDialog(o.application, restoreEntry, false)
823-
ShowDialogOnPages(o.application, o.pages, progressDialog, func() {
824-
o.updateDiff()
811+
// Use Chain() instead of Close() + QueueUpdateDraw()
812+
d.Chain(func() {
813+
progressDialog := NewRestoreFileProgressDialog(o.application, restoreEntry, false)
814+
ShowDialogOnPages(o.application, o.pages, progressDialog, func() {
815+
o.updateDiff()
816+
})
825817
})
818+
} else {
819+
d.Close()
826820
}
827821
}
828822

829-
restoreDialog := NewRestoreFileDialog(o.application, restoreEntry, asyncWork, onComplete)
823+
restoreDialog := NewRestoreFileDialog(o.application, restoreEntry, nil, onComplete)
830824
ShowDialogOnPages(o.application, o.pages, restoreDialog, nil)
831825
}
832826

internal/ui/dialog/selection_dialog.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type SelectionDialog struct {
2525
onComplete func(d *SelectionDialog, option *DialogOption, err error)
2626
}
2727

28+
// NewSelectionDialog
2829
// handler - The background execution logic to be executed when the user selects an option.
2930
// onComplete - The callback to be executed on the UI thread after the background execution completes.
3031
func NewSelectionDialog(
@@ -120,7 +121,25 @@ func (d *SelectionDialog) GetActionChannel() <-chan DialogActionId {
120121
}
121122

122123
func (d *SelectionDialog) Close() {
123-
emitDialogActions(d.actionChannel, DialogCloseActionId)
124+
// Bypass emitDialogActions' goroutine to guarantee the close signal
125+
// is processed synchronously if the listener is ready.
126+
select {
127+
case d.actionChannel <- DialogCloseActionId:
128+
default:
129+
go func() { d.actionChannel <- DialogCloseActionId }()
130+
}
131+
}
132+
133+
// Chain safely orchestrates closing the current dialog and opening a new one.
134+
// It prevents the "Dead Focus Pointer" bug by guaranteeing the current dialog
135+
// fully unmounts and restores its focus before the next dialog captures its fallback.
136+
func (d *SelectionDialog) Chain(mountNext func()) {
137+
d.Close()
138+
go func() {
139+
// A microscopic pause gives the background listener time to process the close event
140+
time.Sleep(10 * time.Millisecond)
141+
d.application.QueueUpdateDraw(mountNext)
142+
}()
124143
}
125144

126145
func (d *SelectionDialog) selectAction(option *DialogOption) {
@@ -129,18 +148,18 @@ func (d *SelectionDialog) selectAction(option *DialogOption) {
129148
return
130149
}
131150

132-
// 1. Always show loading, even if the work is instantaneous
151+
// 1. Always trigger the loading state and background routine
133152
d.ShowLoading(option)
134153

135154
go func() {
136155
var err error
137156

138-
// 2. Only execute the handler if one was actually provided
157+
// 2. Safely execute the handler only if it was provided
139158
if d.handler != nil {
140159
err = d.handler(d, option.Id)
141160
}
142161

143-
// 3. Always queue the completion logic back onto the main UI thread
162+
// 3. Queue the completion logic back to the main UI thread
144163
d.application.QueueUpdateDraw(func() {
145164
d.StopLoading()
146165
if d.onComplete != nil {

0 commit comments

Comments
 (0)