mirror of
https://git.sr.ht/~phw/scotty
synced 2025-05-10 18:27:03 +02:00
Both export and import progress get updated over a unified channel. Most importantly this allows updating the import total from latest export results.
138 lines
3.4 KiB
Go
138 lines
3.4 KiB
Go
/*
|
|
Copyright © 2023-2025 Philipp Wolfer <phw@uploadedlobster.com>
|
|
|
|
This file is part of Scotty.
|
|
|
|
Scotty is free software: you can redistribute it and/or modify it under the
|
|
terms of the GNU General Public License as published by the Free Software
|
|
Foundation, either version 3 of the License, or (at your option) any later version.
|
|
|
|
Scotty is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
Scotty. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package cli
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/fatih/color"
|
|
"github.com/vbauerster/mpb/v8"
|
|
"github.com/vbauerster/mpb/v8/decor"
|
|
"go.uploadedlobster.com/scotty/internal/i18n"
|
|
"go.uploadedlobster.com/scotty/internal/models"
|
|
)
|
|
|
|
type progressBarUpdater struct {
|
|
wg *sync.WaitGroup
|
|
progress *mpb.Progress
|
|
exportBar *mpb.Bar
|
|
importBar *mpb.Bar
|
|
updateChan chan models.TransferProgress
|
|
lastExportUpdate time.Time
|
|
totalItems int
|
|
importedItems int
|
|
}
|
|
|
|
func setupProgressBars(updateChan chan models.TransferProgress) progressBarUpdater {
|
|
wg := &sync.WaitGroup{}
|
|
p := mpb.New(
|
|
mpb.WithWaitGroup(wg),
|
|
mpb.WithOutput(color.Output),
|
|
// mpb.WithWidth(64),
|
|
mpb.WithAutoRefresh(),
|
|
)
|
|
|
|
u := progressBarUpdater{
|
|
wg: wg,
|
|
progress: p,
|
|
exportBar: initProgressBar(p, i18n.Tr("exporting")),
|
|
importBar: initProgressBar(p, i18n.Tr("importing")),
|
|
updateChan: updateChan,
|
|
}
|
|
|
|
go u.update()
|
|
return u
|
|
}
|
|
|
|
func (u *progressBarUpdater) wait() {
|
|
// FIXME: This should probably be closed elsewhere
|
|
close(u.updateChan)
|
|
u.progress.Wait()
|
|
}
|
|
|
|
func (u *progressBarUpdater) update() {
|
|
u.wg.Add(1)
|
|
defer u.wg.Done()
|
|
u.lastExportUpdate = time.Now()
|
|
for progress := range u.updateChan {
|
|
if progress.Export != nil {
|
|
u.updateExportProgress(progress.Export)
|
|
}
|
|
|
|
if progress.Import != nil {
|
|
if int64(u.totalItems) > progress.Import.Total {
|
|
progress.Import.Total = int64(u.totalItems)
|
|
}
|
|
u.updateImportProgress(progress.Import)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (u *progressBarUpdater) updateExportProgress(progress *models.Progress) {
|
|
bar := u.exportBar
|
|
u.totalItems = progress.TotalItems
|
|
|
|
if progress.Aborted {
|
|
bar.Abort(false)
|
|
return
|
|
}
|
|
|
|
oldIterTime := u.lastExportUpdate
|
|
u.lastExportUpdate = time.Now()
|
|
elapsedTime := u.lastExportUpdate.Sub(oldIterTime)
|
|
bar.EwmaSetCurrent(progress.Elapsed, elapsedTime)
|
|
bar.SetTotal(progress.Total, progress.Completed)
|
|
}
|
|
|
|
func (u *progressBarUpdater) updateImportProgress(progress *models.Progress) {
|
|
bar := u.importBar
|
|
|
|
if progress.Aborted {
|
|
bar.Abort(false)
|
|
return
|
|
}
|
|
|
|
bar.SetCurrent(progress.Elapsed)
|
|
bar.SetTotal(progress.Total, progress.Completed)
|
|
}
|
|
|
|
func initProgressBar(p *mpb.Progress, name string) *mpb.Bar {
|
|
green := color.New(color.FgGreen).SprintFunc()
|
|
return p.New(0,
|
|
mpb.BarStyle(),
|
|
mpb.PrependDecorators(
|
|
decor.Name(" "),
|
|
decor.OnComplete(
|
|
decor.Spinner(nil, decor.WC{W: 2, C: decor.DindentRight}),
|
|
green("✓ "),
|
|
),
|
|
decor.Name(name, decor.WCSyncWidthR),
|
|
),
|
|
mpb.AppendDecorators(
|
|
decor.OnComplete(
|
|
decor.OnAbort(
|
|
decor.EwmaETA(decor.ET_STYLE_GO, 0, decor.WC{C: decor.DSyncWidth}),
|
|
i18n.Tr("aborted"),
|
|
),
|
|
i18n.Tr("done"),
|
|
),
|
|
decor.Name(" "),
|
|
),
|
|
)
|
|
}
|