kettlebell-tracker/internal/ui/training.go

118 lines
3.3 KiB
Go

package ui
import (
"fmt"
"time"
"git.patanix.de/git/kettlebell-app/internal/data"
"git.patanix.de/git/kettlebell-app/internal/services"
"git.patanix.de/git/kettlebell-app/internal/ui/theme"
"git.patanix.de/git/kettlebell-app/internal/ui/utils"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
// MakeTrainingScreen gibt jetzt das CanvasObject und die Start-Funktion zurück
func MakeTrainingScreen(ts *services.TrainingService, ss *services.SettingsService, parent fyne.Window) (fyne.CanvasObject, func()) {
timerLabel := canvas.NewText("00:00", theme.ColorSlate200)
timerLabel.TextSize = 60
timerLabel.TextStyle.Bold = true
timerLabel.Alignment = fyne.TextAlignCenter
setsLabel := canvas.NewText("0 / 0", theme.ColorSky400)
setsLabel.TextSize = 48
setsLabel.TextStyle.Bold = true
setsLabel.Alignment = fyne.TextAlignCenter
repsLabel := canvas.NewText("0 Wiederholungen", theme.ColorSlate200)
repsLabel.TextSize = 20
repsLabel.Alignment = fyne.TextAlignCenter
var mainTimer *time.Ticker
updateUI := func() {
state := ts.State
timerLabel.Text = utils.FormatDuration(int64(state.RemainingSeconds))
setsLabel.Text = fmt.Sprintf("%d / %d", state.SetsDone, state.GoalSets)
repsLabel.Text = fmt.Sprintf("%d Wiederholungen", state.RepsPerSet)
timerLabel.Refresh()
setsLabel.Refresh()
repsLabel.Refresh()
}
finishAction := func() {
if mainTimer != nil {
mainTimer.Stop()
mainTimer = nil
}
if !ts.State.IsTrainingRunning {
return // Nichts tun, wenn kein Training läuft
}
session := &data.TrainingSession{
Date: time.Now(),
Sets: int64(ts.State.SetsDone),
WeightLeft: ss.LoadSettings().WeightLeft,
WeightRight: ss.LoadSettings().WeightRight,
RepsPerSet: int64(ts.State.RepsPerSet),
Duration: int64(ts.State.InitialDurationSeconds - ts.State.RemainingSeconds),
}
ts.FinishTraining(session)
fyne.CurrentApp().SendNotification(&fyne.Notification{Title: "Training gespeichert!", Content: "Gut gemacht!"})
updateUI()
}
startAction := func() {
if ts.State.IsTrainingRunning {
return // Verhindere Neustart
}
settings := ss.LoadSettings()
ts.StartTraining(settings.TrainingTimeMinutes, settings.GoalSets)
updateUI()
mainTimer = time.NewTicker(time.Second)
go func() {
for mainTimer != nil {
select {
case <-mainTimer.C:
if ts.State.RemainingSeconds <= 0 {
finishAction()
return
}
ts.Tick()
updateUI()
}
}
}()
}
setAction := func() {
if !ts.State.IsTrainingRunning {
return // Kein Satz ohne laufendes Training
}
ts.CompleteSet()
updateUI()
}
topPart := container.NewVBox(widget.NewLabelWithStyle("Verbleibende Zeit", fyne.TextAlignCenter, fyne.TextStyle{}), timerLabel)
middlePart := container.NewVBox(widget.NewLabelWithStyle("Sätze", fyne.TextAlignCenter, fyne.TextStyle{}), setsLabel, repsLabel)
finishButton := widget.NewButton("Training beenden", finishAction)
finishButton.Importance = widget.HighImportance
bottomPart := container.NewVBox(
widget.NewButton("Satz abschließen", setAction),
finishButton,
)
layout := container.NewBorder(topPart, bottomPart, nil, nil, container.NewCenter(middlePart))
// UI aktualisieren, wenn der Bildschirm sichtbar wird
if layout.Visible() {
updateUI()
}
// layout.OnVisible = updateUI
return layout, startAction
}