1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
package gui
import (
"sync"
"time"
"github.com/jesseduffield/lazygit/pkg/utils"
)
type appStatus struct {
message string
statusType string
id int
}
type statusManager struct {
statuses []appStatus
nextId int
mutex sync.Mutex
}
func (m *statusManager) removeStatus(id int) {
m.mutex.Lock()
defer m.mutex.Unlock()
newStatuses := []appStatus{}
for _, status := range m.statuses {
if status.id != id {
newStatuses = append(newStatuses, status)
}
}
m.statuses = newStatuses
}
func (m *statusManager) addWaitingStatus(message string) int {
m.mutex.Lock()
defer m.mutex.Unlock()
m.nextId += 1
id := m.nextId
newStatus := appStatus{
message: message,
statusType: "waiting",
id: id,
}
m.statuses = append([]appStatus{newStatus}, m.statuses...)
return id
}
func (m *statusManager) addToastStatus(message string) int {
m.mutex.Lock()
defer m.mutex.Unlock()
m.nextId++
id := m.nextId
newStatus := appStatus{
message: message,
statusType: "toast",
id: id,
}
m.statuses = append([]appStatus{newStatus}, m.statuses...)
go func() {
time.Sleep(time.Second * 2)
m.removeStatus(id)
}()
return id
}
func (m *statusManager) getStatusString() string {
if len(m.statuses) == 0 {
return ""
}
topStatus := m.statuses[0]
if topStatus.statusType == "waiting" {
return topStatus.message + " " + utils.Loader()
}
return topStatus.message
}
func (gui *Gui) raiseToast(message string) {
gui.statusManager.addToastStatus(message)
gui.renderAppStatus()
}
func (gui *Gui) renderAppStatus() {
go utils.Safe(func() {
ticker := time.NewTicker(time.Millisecond * 50)
defer ticker.Stop()
for range ticker.C {
appStatus := gui.statusManager.getStatusString()
gui.OnUIThread(func() error {
return gui.renderString(gui.Views.AppStatus, appStatus)
})
if appStatus == "" {
return
}
}
})
}
// WithWaitingStatus wraps a function and shows a waiting status while the function is still executing
func (gui *Gui) WithWaitingStatus(message string, f func() error) error {
go utils.Safe(func() {
id := gui.statusManager.addWaitingStatus(message)
defer func() {
gui.statusManager.removeStatus(id)
}()
gui.renderAppStatus()
if err := f(); err != nil {
gui.OnUIThread(func() error {
return gui.surfaceError(err)
})
}
})
return nil
}
|