mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-25 08:31:03 +00:00
Rework static notification handling
This commit is contained in:
parent
59f39d76cc
commit
70e96c6a49
15 changed files with 73 additions and 59 deletions
|
|
@ -16,7 +16,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
## Container
|
||||
|
||||
<pre>
|
||||
<kbd></kbd>: copy container id
|
||||
<kbd>y</kbd>: copy container ID
|
||||
<kbd>d</kbd>: entfernen
|
||||
<kbd>e</kbd>: hide/show stopped containers
|
||||
<kbd>p</kbd>: pause
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
## Containers
|
||||
|
||||
<pre>
|
||||
<kbd></kbd>: copy container id
|
||||
<kbd>y</kbd>: copy container ID
|
||||
<kbd>d</kbd>: remove
|
||||
<kbd>e</kbd>: hide/show stopped containers
|
||||
<kbd>p</kbd>: pause
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
## Contenedores
|
||||
|
||||
<pre>
|
||||
<kbd></kbd>: copy container id
|
||||
<kbd>y</kbd>: copy container ID
|
||||
<kbd>d</kbd>: borrar
|
||||
<kbd>e</kbd>: esconder/mostrar contenedores parados
|
||||
<kbd>p</kbd>: pausa
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
## Conteneurs
|
||||
|
||||
<pre>
|
||||
<kbd></kbd>: copy container id
|
||||
<kbd>y</kbd>: copy container ID
|
||||
<kbd>d</kbd>: supprimer
|
||||
<kbd>e</kbd>: cacher/montrer les conteneurs arrêtés
|
||||
<kbd>p</kbd>: pause
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
## Containers
|
||||
|
||||
<pre>
|
||||
<kbd></kbd>: copy container id
|
||||
<kbd>y</kbd>: copy container ID
|
||||
<kbd>d</kbd>: verwijder
|
||||
<kbd>e</kbd>: verberg gestopte containers
|
||||
<kbd>p</kbd>: pause
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
## Kontenery
|
||||
|
||||
<pre>
|
||||
<kbd></kbd>: copy container id
|
||||
<kbd>y</kbd>: copy container ID
|
||||
<kbd>d</kbd>: usuń
|
||||
<kbd>e</kbd>: hide/show stopped containers
|
||||
<kbd>p</kbd>: pause
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
## Contêineres
|
||||
|
||||
<pre>
|
||||
<kbd></kbd>: copy container id
|
||||
<kbd>y</kbd>: copy container ID
|
||||
<kbd>d</kbd>: remover
|
||||
<kbd>e</kbd>: ocultar/mostrar contêineres parados
|
||||
<kbd>p</kbd>: pausar
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
## Konteynerler
|
||||
|
||||
<pre>
|
||||
<kbd></kbd>: copy container id
|
||||
<kbd>y</kbd>: copy container ID
|
||||
<kbd>d</kbd>: kaldır
|
||||
<kbd>e</kbd>: hide/show stopped containers
|
||||
<kbd>p</kbd>: pause
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ _This file is auto-generated. To update, make the changes in the pkg/i18n direct
|
|||
## 容器
|
||||
|
||||
<pre>
|
||||
<kbd></kbd>: copy container id
|
||||
<kbd>y</kbd>: copy container ID
|
||||
<kbd>d</kbd>: 移除
|
||||
<kbd>e</kbd>: 隐藏/显示已停止的容器
|
||||
<kbd>p</kbd>: 暂停
|
||||
|
|
|
|||
|
|
@ -381,5 +381,13 @@ func (c *OSCommand) CopyToClipboard(str string) error {
|
|||
|
||||
c.Log.Debug(utils.ResolvePlaceholderString("Copying '{{str}}' to clipboard", map[string]string{"str": truncated}))
|
||||
|
||||
// Not needed yet
|
||||
//if c.UserConfig().OS.CopyToClipboardCmd != "" {
|
||||
// cmdStr := utils.ResolvePlaceholderString(c.UserConfig().OS.CopyToClipboardCmd, map[string]string{
|
||||
// "text": c.Cmd.Quote(str),
|
||||
// })
|
||||
// return c.Cmd.NewShell(cmdStr).Run()
|
||||
//}
|
||||
|
||||
return clipboard.WriteAll(str)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package gui
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
|
|
@ -16,15 +15,14 @@ type appStatus struct {
|
|||
|
||||
type statusManager struct {
|
||||
statuses []appStatus
|
||||
lock *sync.Mutex
|
||||
}
|
||||
|
||||
const (
|
||||
TickIntervalMs = 50
|
||||
)
|
||||
|
||||
func (m *statusManager) removeStatus(name string) {
|
||||
newStatuses := []appStatus{}
|
||||
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
for _, status := range m.statuses {
|
||||
if status.name != name {
|
||||
newStatuses = append(newStatuses, status)
|
||||
|
|
@ -33,61 +31,40 @@ func (m *statusManager) removeStatus(name string) {
|
|||
m.statuses = newStatuses
|
||||
}
|
||||
|
||||
func (m *statusManager) addWaitingStatus(name string) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
func (m *statusManager) addStatus(name string, statusType string, duration int) {
|
||||
m.removeStatus(name)
|
||||
newStatus := appStatus{
|
||||
name: name,
|
||||
statusType: "waiting",
|
||||
duration: 0,
|
||||
statusType: statusType,
|
||||
duration: duration,
|
||||
}
|
||||
m.statuses = append([]appStatus{newStatus}, m.statuses...)
|
||||
}
|
||||
|
||||
func (m *statusManager) getStatusString() string {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
if len(m.statuses) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
topStatus := m.statuses[0]
|
||||
if topStatus.statusType == "waiting" {
|
||||
return topStatus.name + " " + utils.Loader()
|
||||
} else if topStatus.statusType == "info" {
|
||||
return topStatus.name
|
||||
}
|
||||
return topStatus.name
|
||||
}
|
||||
|
||||
// WithStaticWaitingStatus shows a waiting status for a specific duration
|
||||
func (gui *Gui) WithStaticWaitingStatus(name string, duration time.Duration) error {
|
||||
return gui.WithWaitingStatus(name, func() error { time.Sleep(duration); return nil })
|
||||
return topStatus.name
|
||||
}
|
||||
|
||||
// WithWaitingStatus wraps a function and shows a waiting status while the function is still executing
|
||||
func (gui *Gui) WithWaitingStatus(name string, f func() error) error {
|
||||
go func() {
|
||||
gui.statusManager.addWaitingStatus(name)
|
||||
go gui.Notify(name, "waiting", 0)()
|
||||
|
||||
defer func() {
|
||||
gui.statusManager.removeStatus(name)
|
||||
}()
|
||||
|
||||
go func() {
|
||||
ticker := time.NewTicker(time.Millisecond * 50)
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
appStatus := gui.statusManager.getStatusString()
|
||||
if appStatus == "" {
|
||||
return
|
||||
}
|
||||
if err := gui.renderString(gui.g, "appStatus", appStatus); err != nil {
|
||||
gui.Log.Warn(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if err := f(); err != nil {
|
||||
gui.g.Update(func(g *gocui.Gui) error {
|
||||
return gui.createErrorPanel(err.Error())
|
||||
|
|
@ -97,3 +74,37 @@ func (gui *Gui) WithWaitingStatus(name string, f func() error) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Notify sends static notification to the user.
|
||||
// duration of 0 will disable the self-cleaning of the notification
|
||||
func (gui *Gui) Notify(name string, statusType string, duration int) func() {
|
||||
return func() {
|
||||
gui.statusManager.addStatus(name, statusType, duration)
|
||||
|
||||
defer func() {
|
||||
gui.statusManager.removeStatus(name)
|
||||
}()
|
||||
|
||||
ticker := time.NewTicker(time.Millisecond * TickIntervalMs)
|
||||
tickCount := 0
|
||||
endTick := duration * 1000 / TickIntervalMs
|
||||
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
tickCount++
|
||||
// If no duration, don't terminate early
|
||||
if duration > 0 && tickCount >= endTick {
|
||||
return
|
||||
}
|
||||
|
||||
appStatus := gui.statusManager.getStatusString()
|
||||
if appStatus == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if err := gui.renderString(gui.g, "appStatus", appStatus); err != nil {
|
||||
gui.Log.Warn(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -252,8 +252,10 @@ func (gui *Gui) refreshContainersAndServices() error {
|
|||
}
|
||||
|
||||
// keep track of current service selected so that we can reposition our cursor if it moves position in the list
|
||||
gui.DockerCommand.ServiceMutex.Lock()
|
||||
originalSelectedLineIdx := gui.Panels.Services.SelectedIdx
|
||||
selectedService, isServiceSelected := gui.Panels.Services.List.TryGet(originalSelectedLineIdx)
|
||||
gui.DockerCommand.ServiceMutex.Unlock()
|
||||
|
||||
containers, services, err := gui.DockerCommand.RefreshContainersAndServices(
|
||||
gui.Panels.Services.List.GetAllItems(),
|
||||
|
|
@ -364,10 +366,8 @@ func (gui *Gui) handleCopyContainerId(g *gocui.Gui, v *gocui.View) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
err = gui.WithStaticWaitingStatus(fmt.Sprintf(gui.Tr.CopyContainerIdStatus, utils.TruncateWithEllipsis(ctr.ID, 10)), time.Second*2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
formattedStatusText := fmt.Sprintf("Copied %s to clipboard", utils.TruncateWithEllipsis(ctr.ID, 10))
|
||||
go gui.Notify(formattedStatusText, "info", 3)()
|
||||
|
||||
return gui.OSCommand.CopyToClipboard(ctr.ID)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types/events"
|
||||
|
|
@ -147,11 +146,9 @@ func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand
|
|||
State: initialState,
|
||||
Config: config,
|
||||
Tr: tr,
|
||||
statusManager: &statusManager{
|
||||
lock: &sync.Mutex{},
|
||||
},
|
||||
taskManager: tasks.NewTaskManager(log, tr),
|
||||
ErrorChan: errorChan,
|
||||
statusManager: &statusManager{},
|
||||
taskManager: tasks.NewTaskManager(log, tr),
|
||||
ErrorChan: errorChan,
|
||||
}
|
||||
|
||||
deadlock.Opts.Disable = !gui.Config.Debug
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding {
|
|||
},
|
||||
{
|
||||
ViewName: "containers",
|
||||
Key: gocui.KeyCtrlO,
|
||||
Key: 'y',
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: gui.handleCopyContainerId,
|
||||
Description: gui.Tr.CopyContainerId,
|
||||
|
|
|
|||
|
|
@ -67,8 +67,6 @@ type TranslationSet struct {
|
|||
ViewLogs string
|
||||
UpProject string
|
||||
DownProject string
|
||||
CopyContainerId string
|
||||
CopyContainerIdStatus string
|
||||
ServicesTitle string
|
||||
ContainersTitle string
|
||||
StandaloneContainersTitle string
|
||||
|
|
@ -111,6 +109,7 @@ type TranslationSet struct {
|
|||
FilterList string
|
||||
OpenInBrowser string
|
||||
SortContainersByState string
|
||||
CopyContainerId string
|
||||
|
||||
LogsTitle string
|
||||
ConfigTitle string
|
||||
|
|
@ -199,8 +198,6 @@ func englishSet() TranslationSet {
|
|||
ViewLogs: "view logs",
|
||||
UpProject: "up project",
|
||||
DownProject: "down project",
|
||||
CopyContainerId: "copy container id",
|
||||
CopyContainerIdStatus: "Copied %s to clipboard",
|
||||
RemoveImage: "remove image",
|
||||
RemoveVolume: "remove volume",
|
||||
RemoveNetwork: "remove network",
|
||||
|
|
@ -220,6 +217,7 @@ func englishSet() TranslationSet {
|
|||
FilterList: "filter list",
|
||||
OpenInBrowser: "open in browser (first port is http)",
|
||||
SortContainersByState: "sort containers by state",
|
||||
CopyContainerId: "copy container ID",
|
||||
|
||||
GlobalTitle: "Global",
|
||||
MainTitle: "Main",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue