1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-06-04 23:37:41 +02:00

Replace loader panels with waiting status (pull/push/fetch) (#2973)

This commit is contained in:
Stefan Haller 2023-09-20 14:07:25 +02:00 committed by GitHub
commit 07cbb62510
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 48 additions and 155 deletions

View File

@ -537,14 +537,13 @@ func (self *BranchesController) fastForward(branch *models.Branch) error {
action := self.c.Tr.Actions.FastForwardBranch
message := utils.ResolvePlaceholderString(
self.c.Tr.Fetching,
self.c.Tr.FastForwarding,
map[string]string{
"from": fmt.Sprintf("%s/%s", branch.UpstreamRemote, branch.UpstreamBranch),
"to": branch.Name,
"branch": branch.Name,
},
)
return self.c.WithLoaderPanel(message, func(task gocui.Task) error {
return self.c.WithWaitingStatus(message, func(task gocui.Task) error {
worktree, ok := self.worktreeForBranch(branch)
if ok {
self.c.LogAction(action)

View File

@ -800,7 +800,7 @@ func (self *FilesController) onClickSecondary(opts gocui.ViewMouseBindingOpts) e
}
func (self *FilesController) fetch() error {
return self.c.WithLoaderPanel(self.c.Tr.FetchWait, func(task gocui.Task) error {
return self.c.WithWaitingStatus(self.c.Tr.FetchingStatus, func(task gocui.Task) error {
if err := self.fetchAux(task); err != nil {
_ = self.c.Error(err)
}

View File

@ -5,6 +5,7 @@ import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/status"
"github.com/jesseduffield/lazygit/pkg/utils"
)
type AppStatusHelper struct {
@ -77,7 +78,7 @@ func (self *AppStatusHelper) GetStatusString() string {
func (self *AppStatusHelper) renderAppStatus() {
self.c.OnWorker(func(_ gocui.Task) {
ticker := time.NewTicker(time.Millisecond * 50)
ticker := time.NewTicker(time.Millisecond * utils.LoaderAnimationInterval)
defer ticker.Stop()
for range ticker.C {
appStatus := self.statusMgr().GetStatusString()

View File

@ -141,13 +141,8 @@ func (self *ConfirmationHelper) getPopupPanelWidth() int {
}
func (self *ConfirmationHelper) prepareConfirmationPanel(
ctx goContext.Context,
opts types.ConfirmOpts,
) error {
self.c.Views().Confirmation.HasLoader = opts.HasLoader
if opts.HasLoader {
self.c.GocuiGui().StartTicking(ctx)
}
self.c.Views().Confirmation.Title = opts.Title
// for now we do not support wrapping in our editor
self.c.Views().Confirmation.Wrap = !opts.Editable
@ -181,7 +176,7 @@ func (self *ConfirmationHelper) CreatePopupPanel(ctx goContext.Context, opts typ
self.c.Mutexes().PopupMutex.Lock()
defer self.c.Mutexes().PopupMutex.Unlock()
ctx, cancel := goContext.WithCancel(ctx)
_, cancel := goContext.WithCancel(ctx)
// we don't allow interruptions of non-loader popups in case we get stuck somehow
// e.g. a credentials popup never gets its required user input so a process hangs
@ -198,11 +193,9 @@ func (self *ConfirmationHelper) CreatePopupPanel(ctx goContext.Context, opts typ
self.clearConfirmationViewKeyBindings()
err := self.prepareConfirmationPanel(
ctx,
types.ConfirmOpts{
Title: opts.Title,
Prompt: opts.Prompt,
HasLoader: opts.HasLoader,
FindSuggestionsFunc: opts.FindSuggestionsFunc,
Editable: opts.Editable,
Mask: opts.Mask,

View File

@ -140,7 +140,7 @@ type PullFilesOptions struct {
}
func (self *SyncController) PullAux(opts PullFilesOptions) error {
return self.c.WithLoaderPanel(self.c.Tr.PullWait, func(task gocui.Task) error {
return self.c.WithWaitingStatus(self.c.Tr.PullingStatus, func(task gocui.Task) error {
return self.pullWithLock(task, opts)
})
}
@ -168,7 +168,7 @@ type pushOpts struct {
}
func (self *SyncController) pushAux(opts pushOpts) error {
return self.c.WithLoaderPanel(self.c.Tr.PushWait, func(task gocui.Task) error {
return self.c.WithWaitingStatus(self.c.Tr.PushingStatus, func(task gocui.Task) error {
self.c.LogAction(self.c.Tr.Actions.Push)
err := self.c.Git().Sync.Push(
task,

View File

@ -487,7 +487,6 @@ func NewGui(
func(message string, f func(gocui.Task) error) { gui.helpers.AppStatus.WithWaitingStatus(message, f) },
func(message string) { gui.helpers.AppStatus.Toast(message) },
func() string { return gui.Views.Confirmation.TextArea.GetContent() },
func(f func(gocui.Task)) { gui.c.OnWorker(f) },
func() bool { return gui.c.InDemo() },
)

View File

@ -1,54 +0,0 @@
package popup
import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/types"
)
type FakePopupHandler struct {
OnErrorMsg func(message string) error
OnConfirm func(opts types.ConfirmOpts) error
OnPrompt func(opts types.PromptOpts) error
}
var _ types.IPopupHandler = &FakePopupHandler{}
func (self *FakePopupHandler) Error(err error) error {
return self.ErrorMsg(err.Error())
}
func (self *FakePopupHandler) ErrorMsg(message string) error {
return self.OnErrorMsg(message)
}
func (self *FakePopupHandler) Alert(title string, message string) error {
panic("not yet implemented")
}
func (self *FakePopupHandler) Confirm(opts types.ConfirmOpts) error {
return self.OnConfirm(opts)
}
func (self *FakePopupHandler) Prompt(opts types.PromptOpts) error {
return self.OnPrompt(opts)
}
func (self *FakePopupHandler) WithLoaderPanel(message string, f func(gocui.Task) error) error {
return f(gocui.NewFakeTask())
}
func (self *FakePopupHandler) WithWaitingStatus(message string, f func(gocui.Task) error) error {
return f(gocui.NewFakeTask())
}
func (self *FakePopupHandler) Menu(opts types.CreateMenuOptions) error {
panic("not yet implemented")
}
func (self *FakePopupHandler) Toast(message string) {
panic("not yet implemented")
}
func (self *FakePopupHandler) GetPromptInput() string {
panic("not yet implemented")
}

View File

@ -3,11 +3,9 @@ package popup
import (
"context"
"strings"
"time"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/common"
gctx "github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/sasha-s/go-deadlock"
@ -25,7 +23,6 @@ type PopupHandler struct {
withWaitingStatusFn func(message string, f func(gocui.Task) error)
toastFn func(message string)
getPromptInputFn func() string
onWorker func(func(gocui.Task))
inDemo func() bool
}
@ -41,7 +38,6 @@ func NewPopupHandler(
withWaitingStatusFn func(message string, f func(gocui.Task) error),
toastFn func(message string),
getPromptInputFn func() string,
onWorker func(func(gocui.Task)),
inDemo func() bool,
) *PopupHandler {
return &PopupHandler{
@ -55,7 +51,6 @@ func NewPopupHandler(
withWaitingStatusFn: withWaitingStatusFn,
toastFn: toastFn,
getPromptInputFn: getPromptInputFn,
onWorker: onWorker,
inDemo: inDemo,
}
}
@ -128,47 +123,6 @@ func (self *PopupHandler) Prompt(opts types.PromptOpts) error {
})
}
func (self *PopupHandler) WithLoaderPanel(message string, f func(gocui.Task) error) error {
index := 0
self.Lock()
self.index++
index = self.index
self.Unlock()
ctx, cancel := context.WithCancel(context.Background())
err := self.createPopupPanelFn(ctx, types.CreatePopupPanelOpts{
Prompt: message,
HasLoader: true,
})
if err != nil {
self.Log.Error(err)
cancel()
return nil
}
self.onWorker(func(task gocui.Task) {
// emulating a delay due to network latency
if self.inDemo() {
time.Sleep(500 * time.Millisecond)
}
if err := f(task); err != nil {
self.Log.Error(err)
}
cancel()
self.Lock()
if index == self.index && self.currentContextFn().GetKey() == gctx.CONFIRMATION_CONTEXT_KEY {
_ = self.popContextFn()
}
self.Unlock()
})
return nil
}
// returns the content that has currently been typed into the prompt. Useful for
// asynchronously updating the suggestions list under the prompt.
func (self *PopupHandler) GetPromptInput() string {

View File

@ -134,7 +134,6 @@ type IPopupHandler interface {
Confirm(opts ConfirmOpts) error
// Shows a popup prompting the user for input.
Prompt(opts PromptOpts) error
WithLoaderPanel(message string, f func(gocui.Task) error) error
WithWaitingStatus(message string, f func(gocui.Task) error) error
Menu(opts CreateMenuOptions) error
Toast(message string)
@ -166,7 +165,6 @@ type ConfirmOpts struct {
Prompt string
HandleConfirm func() error
HandleClose func() error
HasLoader bool
FindSuggestionsFunc func(string) []*Suggestion
Editable bool
Mask bool

View File

@ -72,9 +72,6 @@ func chineseTranslationSet() TranslationSet {
MergeConflictsTitle: "合并冲突",
Checkout: "检出",
NoChangedFiles: "没有更改过文件",
PullWait: "正在拉取…",
PushWait: "正在推送…",
FetchWait: "正在抓取…",
SoftReset: "软重置",
AlreadyCheckedOutBranch: "您已经检出至此分支",
SureForceCheckout: "您确定要强制检出吗?您将丢失所有本地更改",
@ -172,7 +169,7 @@ func chineseTranslationSet() TranslationSet {
ToggleStagingPanel: `切换到其他面板`,
ReturnToFilesPanel: `返回文件面板`,
FastForward: `从上游快进此分支`,
Fetching: "抓取并快进 {{.from}} -> {{.to}} ...",
FastForwarding: "抓取并快进 {{.branch}} ...",
FoundConflictsTitle: "自动合并失败",
ViewMergeRebaseOptions: "查看 合并/变基 选项",
NotMergingOrRebasing: "您目前既不进行变基也不进行合并",
@ -223,6 +220,9 @@ func chineseTranslationSet() TranslationSet {
AmendCommitPrompt: "您确定要使用暂存文件来修改此提交吗?",
DeleteCommitTitle: "删除提交",
DeleteCommitPrompt: "您确定要删除此提交吗?",
PullingStatus: "正在拉取",
PushingStatus: "正在推送",
FetchingStatus: "正在抓取",
SquashingStatus: "正在压缩",
FixingStatus: "正在修正",
DeletingStatus: "正在删除",

View File

@ -38,9 +38,6 @@ func dutchTranslationSet() TranslationSet {
ResetFilter: "Reset commit file state filter",
MergeConflictsTitle: "Merge conflicten",
Checkout: "Uitchecken",
PullWait: "Pullen...",
PushWait: "Pushen...",
FetchWait: "Fetchen...",
SoftReset: "Zacht reset",
AlreadyCheckedOutBranch: "Je hebt deze branch al uitgecheckt",
SureForceCheckout: "Weet je zeker dat je het uitchecken wil forceren? Al je lokale verandering zullen worden verwijdert",
@ -137,7 +134,7 @@ func dutchTranslationSet() TranslationSet {
ToggleStagingPanel: `Ga naar een ander paneel`,
ReturnToFilesPanel: `Ga terug naar het bestanden paneel`,
FastForward: `Fast-forward deze branch vanaf zijn upstream`,
Fetching: "Fetching en fast-forwarding {{.from}} -> {{.to}} ...",
FastForwarding: "Fast-forwarding {{.branch}} ...",
FoundConflictsTitle: "Conflicten!",
ViewMergeRebaseOptions: "Bekijk merge/rebase opties",
NotMergingOrRebasing: "Je bent momenteel niet aan het rebasen of mergen",
@ -187,6 +184,9 @@ func dutchTranslationSet() TranslationSet {
AmendCommitPrompt: "Weet je zeker dat je deze commit wil wijzigen met de vorige staged bestanden?",
DeleteCommitTitle: "Verwijder commit",
DeleteCommitPrompt: "Weet je zeker dat je deze commit wil verwijderen?",
PullingStatus: "Pullen",
PushingStatus: "Pushen",
FetchingStatus: "Fetchen",
SquashingStatus: "Squashen",
FixingStatus: "Fixing up",
DeletingStatus: "Verwijderen",

View File

@ -58,9 +58,6 @@ type TranslationSet struct {
MergeConflictsTitle string
Checkout string
NoChangedFiles string
PullWait string
PushWait string
FetchWait string
SoftReset string
AlreadyCheckedOutBranch string
SureForceCheckout string
@ -187,7 +184,7 @@ type TranslationSet struct {
ToggleStagingPanel string
ReturnToFilesPanel string
FastForward string
Fetching string
FastForwarding string
FoundConflictsTitle string
ViewConflictsMenuItem string
AbortMenuItem string
@ -253,6 +250,9 @@ type TranslationSet struct {
AmendCommitPrompt string
DeleteCommitTitle string
DeleteCommitPrompt string
PullingStatus string
PushingStatus string
FetchingStatus string
SquashingStatus string
FixingStatus string
DeletingStatus string
@ -848,9 +848,6 @@ func EnglishTranslationSet() TranslationSet {
FilterUnstagedFiles: "Show only unstaged files",
ResetFilter: "Reset filter",
NoChangedFiles: "No changed files",
PullWait: "Pulling...",
PushWait: "Pushing...",
FetchWait: "Fetching...",
SoftReset: "Soft reset",
AlreadyCheckedOutBranch: "You have already checked out this branch",
SureForceCheckout: "Are you sure you want force checkout? You will lose all local changes",
@ -980,7 +977,7 @@ func EnglishTranslationSet() TranslationSet {
ToggleStagingPanel: `Switch to other panel (staged/unstaged changes)`,
ReturnToFilesPanel: `Return to files panel`,
FastForward: `Fast-forward this branch from its upstream`,
Fetching: "Fetching and fast-forwarding {{.from}} -> {{.to}} ...",
FastForwarding: "Fast-forwarding {{.branch}}",
FoundConflictsTitle: "Conflicts!",
ViewConflictsMenuItem: "View conflicts",
AbortMenuItem: "Abort the %s",
@ -1049,6 +1046,9 @@ func EnglishTranslationSet() TranslationSet {
AmendCommitPrompt: "Are you sure you want to amend this commit with your staged files?",
DeleteCommitTitle: "Delete commit",
DeleteCommitPrompt: "Are you sure you want to delete this commit?",
PullingStatus: "Pulling",
PushingStatus: "Pushing",
FetchingStatus: "Fetching",
SquashingStatus: "Squashing",
FixingStatus: "Fixing up",
DeletingStatus: "Deleting",

View File

@ -63,9 +63,6 @@ func japaneseTranslationSet() TranslationSet {
FilterUnstagedFiles: "ステージされていないファイルのみを表示",
ResetFilter: "フィルタをリセット",
// NoChangedFiles: "No changed files",
PullWait: "Pull中...",
PushWait: "Push中...",
FetchWait: "Fetch中...",
SoftReset: "Softリセット",
AlreadyCheckedOutBranch: "ブランチはすでにチェックアウトされています。",
// SureForceCheckout: "Are you sure you want force checkout? You will lose all local changes",
@ -227,6 +224,9 @@ func japaneseTranslationSet() TranslationSet {
AmendCommitPrompt: "ステージされたファイルで現在のコミットをamendします。よろしいですか?",
DeleteCommitTitle: "コミットを削除",
DeleteCommitPrompt: "選択されたコミットを削除します。よろしいですか?",
PullingStatus: "Pull中",
PushingStatus: "Push中",
FetchingStatus: "Fetch中",
// SquashingStatus: "Squashing",
// FixingStatus: "Fixing up",
// DeletingStatus: "Deleting",

View File

@ -62,9 +62,6 @@ func koreanTranslationSet() TranslationSet {
FilterUnstagedFiles: "Stage되지 않은 파일만 표시",
ResetFilter: "필터 리셋",
NoChangedFiles: "변경된 파일이 없습니다.",
PullWait: "업데이트 중...",
PushWait: "푸시 중...",
FetchWait: "패치 중...",
SoftReset: "소프트 리셋",
AlreadyCheckedOutBranch: "브랜치가 이미 체크아웃 되었습니다",
SureForceCheckout: "강제로 체크아웃하시겠습니까? 모든 로컬 변경 사항을 잃게 됩니다.",
@ -173,7 +170,7 @@ func koreanTranslationSet() TranslationSet {
ToggleStagingPanel: `패널 전환`,
ReturnToFilesPanel: `파일 목록으로 돌아가기`,
FastForward: `Fast-forward this branch from its upstream`,
Fetching: "Fetching and fast-forwarding {{.from}} -> {{.to}} ...",
FastForwarding: "Fast-forwarding {{.branch}} ...",
FoundConflictsTitle: "Auto-merge failed",
ViewMergeRebaseOptions: "View merge/rebase options",
NotMergingOrRebasing: "You are currently neither rebasing nor merging",
@ -224,6 +221,9 @@ func koreanTranslationSet() TranslationSet {
AmendCommitPrompt: "Are you sure you want to amend this commit with your staged files?",
DeleteCommitTitle: "커밋 삭제",
DeleteCommitPrompt: "정말로 선택한 커밋을 삭제하시겠습니까?",
PullingStatus: "업데이트 중",
PushingStatus: "푸시 중",
FetchingStatus: "패치 중",
SquashingStatus: "Squashing",
FixingStatus: "Fixing up",
DeletingStatus: "Deleting",

View File

@ -34,9 +34,6 @@ func polishTranslationSet() TranslationSet {
ResetFilter: "Resetuj filtr commitów",
Checkout: "Przełącz",
NoChangedFiles: "Brak zmienionych plików",
PullWait: "Pobieranie zmian...",
PushWait: "Wysyłanie zmian...",
FetchWait: "Pobieram...",
AlreadyCheckedOutBranch: "Już przęłączono na tą gałąź",
SureForceCheckout: "Jesteś pewny, że chcesz wymusić przełączenie? Stracisz wszystkie lokalne zmiany",
ForceCheckoutBranch: "Wymuś przełączenie gałęzi",
@ -153,6 +150,9 @@ func polishTranslationSet() TranslationSet {
AmendCommitPrompt: "Czy na pewno chcesz poprawić ten commit plikami z poczekalni?",
DeleteCommitTitle: "Usuń commit",
DeleteCommitPrompt: "Czy na pewno usunąć ten commit?",
PullingStatus: "Pobieranie zmian",
PushingStatus: "Wysyłanie zmian",
FetchingStatus: "Pobieram",
SquashingStatus: "Spłaszczanie",
FixingStatus: "Naprawianie",
DeletingStatus: "Usuwanie",

View File

@ -81,9 +81,6 @@ func RussianTranslationSet() TranslationSet {
FilterUnstagedFiles: "Показывать только непроиндексированные файлы",
ResetFilter: "Сбросить фильтр",
NoChangedFiles: "Нет изменённых файлов",
PullWait: "Получение и слияние изменении...",
PushWait: "Отправка изменении...",
FetchWait: "Получение изменении...",
SoftReset: "Мягкий сброс",
AlreadyCheckedOutBranch: "Вы уже переключились в эту ветку",
SureForceCheckout: "Вы уверены, что хотите принудительная переключить? Вы потеряете все локальные изменения",
@ -204,7 +201,7 @@ func RussianTranslationSet() TranslationSet {
ToggleStagingPanel: `Переключиться на другую панель (проиндексированные/непроиндексированные изменения)`,
ReturnToFilesPanel: `Вернуться к панели файлов`,
FastForward: `Перемотать эту ветку вперёд из её upstream-ветки`,
Fetching: "Получить изменения и перемотать вперёд {{.from}} -> {{.to}} ...",
FastForwarding: "Получить изменения и перемотать вперёд {{.branch}} ...",
FoundConflictsTitle: "Конфликты!",
ViewConflictsMenuItem: "Просмотр конфликтов",
AbortMenuItem: "Прервать %s",
@ -268,6 +265,9 @@ func RussianTranslationSet() TranslationSet {
AmendCommitPrompt: "Вы уверены, что хотите править этот коммит проиндексированными файлами?",
DeleteCommitTitle: "Удалить коммит",
DeleteCommitPrompt: "Вы уверены, что хотите удалить этот коммит?",
PullingStatus: "Получение и слияние изменении",
PushingStatus: "Отправка изменении",
FetchingStatus: "Получение изменении",
SquashingStatus: "Объединение коммитов",
FixingStatus: "Объединение коммитов, отбросив сообщение коммита",
DeletingStatus: "Удаление",

View File

@ -114,9 +114,6 @@ func traditionalChineseTranslationSet() TranslationSet {
FilterUnstagedFiles: "僅顯示未預存的檔案",
ResetFilter: "重設篩選",
NoChangedFiles: "沒有變更的檔案",
PullWait: "拉取...",
PushWait: "推送...",
FetchWait: "擷取...",
SoftReset: "軟重設",
AlreadyCheckedOutBranch: "你已經檢出這個分支了",
SureForceCheckout: "你確定要強制檢出嗎?這將會使你失去本地的所有更改",
@ -237,7 +234,7 @@ func traditionalChineseTranslationSet() TranslationSet {
ToggleStagingPanel: `切換至另一個面板 (已預存/未預存更改)`,
ReturnToFilesPanel: `返回檔案面板`,
FastForward: `從上游快進此分支`,
Fetching: "{{.from}} -> {{.to}} 的擷取和快進中...",
FastForwarding: "{{.branch}} 的擷取和快進中...",
FoundConflictsTitle: "自動合併失敗",
ViewMergeRebaseOptions: "查看合併/變基選項",
NotMergingOrRebasing: "你當前既不在變基也不在合併中",
@ -299,6 +296,9 @@ func traditionalChineseTranslationSet() TranslationSet {
AmendCommitPrompt: "你確定要使用預存的檔案修正此提交嗎?",
DeleteCommitTitle: "刪除提交",
DeleteCommitPrompt: "你確定要刪除此提交嗎?",
PullingStatus: "拉取",
PushingStatus: "推送",
FetchingStatus: "擷取",
SquashingStatus: "壓縮中",
FixingStatus: "修復中",
DeletingStatus: "刪除中",

View File

@ -24,12 +24,15 @@ func GetProjectRoot() string {
return strings.Split(dir, "lazygit")[0] + "lazygit"
}
// The duration between two frames of the loader animation in milliseconds
const LoaderAnimationInterval = 50
// Loader dumps a string to be displayed as a loader
func Loader() string {
characters := "|/-\\"
now := time.Now()
nanos := now.UnixNano()
index := nanos / 50000000 % int64(len(characters))
milliseconds := now.UnixMilli()
index := milliseconds / LoaderAnimationInterval % int64(len(characters))
return characters[index : index+1]
}