refactor: perform clean up
This commit is contained in:
parent
c15cdea57d
commit
a7e427ca14
13 changed files with 133 additions and 85 deletions
10
cmd/main.go
10
cmd/main.go
|
|
@ -14,13 +14,11 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
// 1. App initialisieren und unser neues Theme setzen
|
||||
myApp := app.NewWithID("com.patani.kettlebell-tracker")
|
||||
myApp.Settings().SetTheme(&theme.KettlebellTheme{})
|
||||
myApp.Settings().SetTheme(&theme.KettlebellThemeOneDark{})
|
||||
|
||||
mainWindow := myApp.NewWindow("Kettlebell Tracker")
|
||||
|
||||
// 2. Services initialisieren
|
||||
dbDir := myApp.Storage().RootURI().Path()
|
||||
dbPath := filepath.Join(dbDir, "giant_training.db")
|
||||
dbService, err := data.NewDatabaseService(dbPath)
|
||||
|
|
@ -31,14 +29,11 @@ func main() {
|
|||
apiService := services.NewApiService(myApp.UniqueID())
|
||||
trainingService := services.NewTrainingService(dbService, settingsService, apiService)
|
||||
|
||||
// 3. UI-Bildschirme und Aktionen erstellen
|
||||
contentContainer := container.NewMax()
|
||||
var navigateTo func(string)
|
||||
|
||||
// Erstelle den Trainings-Screen und hole seine Start-Aktion
|
||||
trainingScreen, startTrainingAction := ui.MakeTrainingScreen(trainingService, settingsService, mainWindow)
|
||||
|
||||
// Erstelle den Home-Screen und übergebe ihm die Start-Aktion und die Navigationsfunktion
|
||||
homeScreen := ui.MakeHomeScreen(trainingService, dbService, func() {
|
||||
startTrainingAction()
|
||||
navigateTo("training")
|
||||
|
|
@ -58,14 +53,11 @@ func main() {
|
|||
contentContainer.Add(s)
|
||||
}
|
||||
|
||||
// 4. Benutzerdefinierte Navigationsleiste erstellen
|
||||
navBar, navigateFunc := ui.MakeNavBar(screens, contentContainer)
|
||||
navigateTo = navigateFunc
|
||||
|
||||
// Initial den Home-Bildschirm anzeigen
|
||||
navigateTo("home")
|
||||
|
||||
// 5. Hauptlayout mit Border-Layout erstellen
|
||||
mainLayout := container.NewBorder(nil, navBar, nil, nil, contentContainer)
|
||||
|
||||
mainWindow.SetContent(mainLayout)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
// ... (DatabaseService struct und NewDatabaseService bleiben gleich) ...
|
||||
type DatabaseService struct {
|
||||
DB *sql.DB
|
||||
}
|
||||
|
|
@ -42,7 +41,6 @@ func NewDatabaseService(dbPath string) (*DatabaseService, error) {
|
|||
return &DatabaseService{DB: db}, nil
|
||||
}
|
||||
|
||||
// ... (SaveTraining und GetHistory bleiben gleich) ...
|
||||
func (s *DatabaseService) SaveTraining(session *TrainingSession) error {
|
||||
dateStr := session.Date.Format(time.RFC3339)
|
||||
query := `
|
||||
|
|
@ -90,7 +88,6 @@ func (s *DatabaseService) GetHistory() ([]TrainingSession, error) {
|
|||
return sessions, nil
|
||||
}
|
||||
|
||||
// GetLastTraining ruft die letzte einzelne Trainingseinheit ab.
|
||||
func (s *DatabaseService) GetLastTraining() (*TrainingSession, error) {
|
||||
query := `SELECT id, date, sets, weightLeft, weightRight, repsPerSet, duration, program, blockDay FROM training ORDER BY date DESC LIMIT 1;`
|
||||
row := s.DB.QueryRow(query)
|
||||
|
|
@ -100,7 +97,7 @@ func (s *DatabaseService) GetLastTraining() (*TrainingSession, error) {
|
|||
err := row.Scan(&session.ID, &dateStr, &session.Sets, &session.WeightLeft, &session.WeightRight, &session.RepsPerSet, &session.Duration, &session.Program, &session.BlockDay)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil // Kein Fehler, nur keine Einträge
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -113,7 +110,6 @@ func (s *DatabaseService) GetLastTraining() (*TrainingSession, error) {
|
|||
return &session, nil
|
||||
}
|
||||
|
||||
// GetTrainingCount zählt alle Trainingseinheiten.
|
||||
func (s *DatabaseService) GetTrainingCount() (int, error) {
|
||||
var count int
|
||||
query := "SELECT COUNT(*) FROM training;"
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@ package data
|
|||
|
||||
import "time"
|
||||
|
||||
// TrainingSession repräsentiert eine einzelne Trainingseinheit.
|
||||
// Die `db`-Tags werden verwendet, um die Struct-Felder den Datenbankspalten zuzuordnen.
|
||||
type TrainingSession struct {
|
||||
ID int64 `db:"id"`
|
||||
Date time.Time `db:"date"`
|
||||
|
|
@ -11,7 +9,7 @@ type TrainingSession struct {
|
|||
WeightLeft float64 `db:"weightLeft"`
|
||||
WeightRight float64 `db:"weightRight"`
|
||||
RepsPerSet int64 `db:"repsPerSet"`
|
||||
Duration int64 `db:"duration"` // in Sekunden
|
||||
Duration int64 `db:"duration"`
|
||||
Program string `db:"program"`
|
||||
BlockDay int64 `db:"blockDay"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ import (
|
|||
"git.patanix.de/git/kettlebell-app/internal/data"
|
||||
)
|
||||
|
||||
// TrainingPayload ist die JSON-Struktur, die an das Backend gesendet wird.
|
||||
// Die `json:"..."`-Tags stellen sicher, dass die Feldnamen im JSON korrekt sind.
|
||||
type TrainingPayload struct {
|
||||
Reps int `json:"reps"`
|
||||
Rest float64 `json:"rest"`
|
||||
|
|
@ -19,17 +17,14 @@ type TrainingPayload struct {
|
|||
UUID string `json:"uuid"`
|
||||
}
|
||||
|
||||
// ApiService kümmert sich um die Kommunikation mit dem Backend.
|
||||
type ApiService struct {
|
||||
client *http.Client
|
||||
endpoint string
|
||||
uuid string
|
||||
}
|
||||
|
||||
// NewApiService erstellt einen neuen Service für die API-Kommunikation.
|
||||
func NewApiService(appUUID string) *ApiService {
|
||||
return &ApiService{
|
||||
// Erstellt einen HTTP-Client mit einem 5-Sekunden-Timeout, genau wie in deiner Flutter-App.
|
||||
client: &http.Client{
|
||||
Timeout: 5 * time.Second,
|
||||
},
|
||||
|
|
@ -38,15 +33,12 @@ func NewApiService(appUUID string) *ApiService {
|
|||
}
|
||||
}
|
||||
|
||||
// SendTrainingData sendet eine abgeschlossene Trainingseinheit an das Backend.
|
||||
func (s *ApiService) SendTrainingData(session *data.TrainingSession) {
|
||||
// Berechnung für 'rest' durchführen.
|
||||
var rest float64
|
||||
if session.Sets > 0 {
|
||||
rest = float64(session.Duration) / float64(session.Sets)
|
||||
}
|
||||
|
||||
// Die zu sendenden Daten vorbereiten.
|
||||
payload := TrainingPayload{
|
||||
Reps: int(session.RepsPerSet),
|
||||
Rest: rest,
|
||||
|
|
@ -54,14 +46,12 @@ func (s *ApiService) SendTrainingData(session *data.TrainingSession) {
|
|||
UUID: s.uuid,
|
||||
}
|
||||
|
||||
// Daten in JSON umwandeln.
|
||||
jsonData, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
log.Printf("API Fehler: Konnte Payload nicht in JSON umwandeln: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Den HTTP-Request erstellen.
|
||||
req, err := http.NewRequest("POST", s.endpoint, bytes.NewBuffer(jsonData))
|
||||
if err != nil {
|
||||
log.Printf("API Fehler: Konnte Request nicht erstellen: %v", err)
|
||||
|
|
@ -69,7 +59,6 @@ func (s *ApiService) SendTrainingData(session *data.TrainingSession) {
|
|||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
// Request senden.
|
||||
log.Printf("Sende Training an Backend: %s", string(jsonData))
|
||||
resp, err := s.client.Do(req)
|
||||
if err != nil {
|
||||
|
|
@ -78,7 +67,6 @@ func (s *ApiService) SendTrainingData(session *data.TrainingSession) {
|
|||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Antwort des Servers prüfen.
|
||||
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusCreated {
|
||||
log.Println("Training erfolgreich an Backend gesendet.")
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import (
|
|||
"fyne.io/fyne/v2/widget"
|
||||
)
|
||||
|
||||
// NavButton ist unser benutzerdefinierter Navigationsbutton
|
||||
type NavButton struct {
|
||||
widget.BaseWidget
|
||||
icon *canvas.Image
|
||||
|
|
@ -52,11 +51,9 @@ func (b *NavButton) Tapped(*fyne.PointEvent) {
|
|||
func (b *NavButton) SetActive(active bool) {
|
||||
b.isActive = active
|
||||
if b.isActive {
|
||||
// b.icon.Resource.Color = theme.ColorSky400
|
||||
b.label.Color = theme.ColorSky400
|
||||
b.label.Color = theme.OneDarkGreen
|
||||
} else {
|
||||
// b.icon.Resource.Color = theme.ColorSlate400
|
||||
b.label.Color = theme.ColorSlate400
|
||||
b.label.Color = theme.OneDarkText
|
||||
}
|
||||
b.Refresh()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ func MakeHistoryScreen(db *data.DatabaseService, parent fyne.Window) fyne.Canvas
|
|||
content := container.NewStack(list, container.NewCenter(placeholder))
|
||||
layout := container.NewBorder(toolbar, nil, nil, nil, content)
|
||||
|
||||
// Daten laden, wenn der Container sichtbar wird
|
||||
if layout.Visible() {
|
||||
refreshData()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"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"
|
||||
|
||||
|
|
@ -16,17 +17,14 @@ import (
|
|||
)
|
||||
|
||||
func MakeHomeScreen(ts *services.TrainingService, db *data.DatabaseService, onStart func()) fyne.CanvasObject {
|
||||
// Header
|
||||
headerTitle := canvas.NewText("Patanix", theme.ColorSlate200)
|
||||
headerTitle := canvas.NewText("Kettlebell Workout Tracker", theme.OneDarkText)
|
||||
headerTitle.TextSize = 28
|
||||
headerTitle.TextStyle.Bold = true
|
||||
|
||||
header := container.NewVBox(
|
||||
widget.NewLabel("Hallo,"),
|
||||
header := container.NewCenter(
|
||||
headerTitle,
|
||||
)
|
||||
|
||||
// Nächstes Training CTA
|
||||
state := ts.State
|
||||
nextTrainingCard := widget.NewCard(
|
||||
"Nächstes Training",
|
||||
|
|
@ -37,7 +35,6 @@ func MakeHomeScreen(ts *services.TrainingService, db *data.DatabaseService, onSt
|
|||
),
|
||||
)
|
||||
|
||||
// Letzte Leistung
|
||||
setsValue := widget.NewLabelWithStyle("–", fyne.TextAlignCenter, fyne.TextStyle{Bold: true})
|
||||
durationValue := widget.NewLabelWithStyle("–", fyne.TextAlignCenter, fyne.TextStyle{Bold: true})
|
||||
weightValue := widget.NewLabelWithStyle("–", fyne.TextAlignCenter, fyne.TextStyle{Bold: true})
|
||||
|
|
@ -48,7 +45,6 @@ func MakeHomeScreen(ts *services.TrainingService, db *data.DatabaseService, onSt
|
|||
container.NewVBox(widget.NewLabel("Gewicht"), weightValue),
|
||||
))
|
||||
|
||||
// Funktion zum Laden der letzten Leistung
|
||||
loadLastPerformance := func() {
|
||||
lastSession, err := db.GetLastTraining()
|
||||
if err != nil {
|
||||
|
|
@ -58,7 +54,7 @@ func MakeHomeScreen(ts *services.TrainingService, db *data.DatabaseService, onSt
|
|||
if lastSession != nil {
|
||||
setsValue.SetText(fmt.Sprintf("%d", lastSession.Sets))
|
||||
durationValue.SetText(utils.FormatDuration(lastSession.Duration))
|
||||
weightValue.SetText(fmt.Sprintf("%.1fkg", lastSession.WeightLeft)) // Annahme: linkes Gewicht ist repräsentativ
|
||||
weightValue.SetText(fmt.Sprintf("%.1fkg", lastSession.WeightLeft))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -70,11 +66,9 @@ func MakeHomeScreen(ts *services.TrainingService, db *data.DatabaseService, onSt
|
|||
)
|
||||
|
||||
paddedLayout := container.NewPadded(layout)
|
||||
// Daten laden, wenn der Bildschirm sichtbar wird
|
||||
if paddedLayout.Visible() {
|
||||
loadLastPerformance()
|
||||
}
|
||||
// paddedLayout.OnVisible = loadLastPerformance
|
||||
|
||||
return paddedLayout
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,9 @@ import (
|
|||
"fyne.io/fyne/v2/theme"
|
||||
)
|
||||
|
||||
// MakeNavBar erstellt die benutzerdefinierte Navigationsleiste und gibt die Navigationsfunktion zurück.
|
||||
func MakeNavBar(screens map[string]fyne.CanvasObject, content *fyne.Container) (fyne.CanvasObject, func(string)) {
|
||||
buttons := make(map[string]*components.NavButton)
|
||||
|
||||
// Funktion zum Umschalten der Ansichten
|
||||
navigateTo := func(name string) {
|
||||
for key, screen := range screens {
|
||||
screen.Hide()
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ func MakeSettingsScreen(settingsService *services.SettingsService, parent fyne.W
|
|||
paddedLayout := container.NewPadded(layout)
|
||||
if paddedLayout.Visible() {
|
||||
loadData()
|
||||
} // Daten laden, wenn sichtbar
|
||||
}
|
||||
|
||||
return paddedLayout
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,82 @@
|
|||
// package theme
|
||||
//
|
||||
// import (
|
||||
//
|
||||
// "image/color"
|
||||
//
|
||||
// "fyne.io/fyne/v2"
|
||||
// "fyne.io/fyne/v2/theme"
|
||||
//
|
||||
// )
|
||||
//
|
||||
// // Definiere unsere benutzerdefinierten Farben basierend auf dem Mock-up
|
||||
// var (
|
||||
//
|
||||
// ColorSlate900 = color.NRGBA{R: 0x0f, G: 0x17, B: 0x2a, A: 0xff} // bg-slate-900
|
||||
// ColorSlate800 = color.NRGBA{R: 0x1e, G: 0x29, B: 0x3b, A: 0xff} // bg-slate-800
|
||||
// ColorSlate700 = color.NRGBA{R: 0x33, G: 0x41, B: 0x55, A: 0xff} // bg-slate-700
|
||||
// ColorSlate400 = color.NRGBA{R: 0x94, G: 0xa3, B: 0xb8, A: 0xff} // text-slate-400
|
||||
// ColorSlate200 = color.NRGBA{R: 0xe2, G: 0xe8, B: 0xf0, A: 0xff} // text-slate-200
|
||||
// ColorSky500 = color.NRGBA{R: 0x0e, G: 0xa5, B: 0xe9, A: 0xff} // bg-sky-500
|
||||
// ColorSky400 = color.NRGBA{R: 0x38, G: 0xbd, B: 0xf8, A: 0xff} // text-sky-400
|
||||
// ColorRed500 = color.NRGBA{R: 0xef, G: 0x44, B: 0x44, A: 0xff} // red-500
|
||||
//
|
||||
// )
|
||||
//
|
||||
// // KettlebellTheme ist unsere benutzerdefinierte Theme-Implementierung
|
||||
// type KettlebellTheme struct{}
|
||||
//
|
||||
// func (t *KettlebellTheme) Color(name fyne.ThemeColorName, variant fyne.ThemeVariant) color.Color {
|
||||
// switch name {
|
||||
// case theme.ColorNameBackground:
|
||||
// return ColorSlate900
|
||||
// case theme.ColorNameButton:
|
||||
// return ColorSlate800
|
||||
// case theme.ColorNameDisabledButton:
|
||||
// return ColorSlate700
|
||||
// case theme.ColorNamePrimary:
|
||||
// return ColorSky500
|
||||
// case theme.ColorNamePlaceHolder:
|
||||
// return ColorSlate400
|
||||
// case theme.ColorNameHover:
|
||||
// return ColorSlate700
|
||||
// case theme.ColorNameForeground:
|
||||
// return ColorSlate200
|
||||
// case theme.ColorNameDisabled:
|
||||
// return ColorSlate400
|
||||
// case theme.ColorNameError:
|
||||
// return ColorRed500
|
||||
// case theme.ColorNameInputBackground:
|
||||
// return ColorSlate800
|
||||
// case theme.ColorNameSeparator:
|
||||
// return ColorSlate700
|
||||
// default:
|
||||
// return theme.DefaultTheme().Color(name, variant)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func (t *KettlebellTheme) Icon(name fyne.ThemeIconName) fyne.Resource {
|
||||
// return theme.DefaultTheme().Icon(name)
|
||||
// }
|
||||
//
|
||||
// func (t *KettlebellTheme) Font(style fyne.TextStyle) fyne.Resource {
|
||||
// return theme.DefaultTheme().Font(style)
|
||||
// }
|
||||
//
|
||||
// func (t *KettlebellTheme) Size(name fyne.ThemeSizeName) float32 {
|
||||
// switch name {
|
||||
// case theme.SizeNamePadding:
|
||||
// return 8
|
||||
// case theme.SizeNameText:
|
||||
// return 16
|
||||
// case theme.SizeNameHeadingText:
|
||||
// return 24
|
||||
// case theme.SizeNameSubHeadingText:
|
||||
// return 20
|
||||
// default:
|
||||
// return theme.DefaultTheme().Size(name)
|
||||
// }
|
||||
// }
|
||||
package theme
|
||||
|
||||
import (
|
||||
|
|
@ -7,59 +86,69 @@ import (
|
|||
"fyne.io/fyne/v2/theme"
|
||||
)
|
||||
|
||||
// Definiere unsere benutzerdefinierten Farben basierend auf dem Mock-up
|
||||
// One Dark Farben (angepasst für Fyne)
|
||||
var (
|
||||
ColorSlate900 = color.NRGBA{R: 0x0f, G: 0x17, B: 0x2a, A: 0xff} // bg-slate-900
|
||||
ColorSlate800 = color.NRGBA{R: 0x1e, G: 0x29, B: 0x3b, A: 0xff} // bg-slate-800
|
||||
ColorSlate700 = color.NRGBA{R: 0x33, G: 0x41, B: 0x55, A: 0xff} // bg-slate-700
|
||||
ColorSlate400 = color.NRGBA{R: 0x94, G: 0xa3, B: 0xb8, A: 0xff} // text-slate-400
|
||||
ColorSlate200 = color.NRGBA{R: 0xe2, G: 0xe8, B: 0xf0, A: 0xff} // text-slate-200
|
||||
ColorSky500 = color.NRGBA{R: 0x0e, G: 0xa5, B: 0xe9, A: 0xff} // bg-sky-500
|
||||
ColorSky400 = color.NRGBA{R: 0x38, G: 0xbd, B: 0xf8, A: 0xff} // text-sky-400
|
||||
ColorRed500 = color.NRGBA{R: 0xef, G: 0x44, B: 0x44, A: 0xff} // red-500
|
||||
// Basisfarben
|
||||
OneDarkBackground = color.NRGBA{R: 40, G: 44, B: 52, A: 0xff} // #282c34 (helleres Grau)
|
||||
OneDarkCardBackground = color.NRGBA{R: 30, G: 32, B: 40, A: 0xff} // #1e2028 (dunkler für Cards)
|
||||
OneDarkText = color.NRGBA{R: 171, G: 178, B: 191, A: 0xff} // #abb2bf (Standard-Text)
|
||||
OneDarkSubtleText = color.NRGBA{R: 110, G: 115, B: 141, A: 0xff} // #6e738d (deaktiviert, Placeholder)
|
||||
|
||||
// Akzentfarben (One Dark)
|
||||
OneDarkGreen = color.NRGBA{R: 152, G: 195, B: 121, A: 0xff} // #98c379
|
||||
OneDarkRed = color.NRGBA{R: 224, G: 108, B: 117, A: 0xff} // #e06c75
|
||||
OneDarkYellow = color.NRGBA{R: 229, G: 192, B: 123, A: 0xff} // #e5c07b
|
||||
)
|
||||
|
||||
// KettlebellTheme ist unsere benutzerdefinierte Theme-Implementierung
|
||||
type KettlebellTheme struct{}
|
||||
// KettlebellThemeOneDark ist das angepasste Theme
|
||||
type KettlebellThemeOneDark struct{}
|
||||
|
||||
func (t *KettlebellTheme) Color(name fyne.ThemeColorName, variant fyne.ThemeVariant) color.Color {
|
||||
func (t *KettlebellThemeOneDark) Color(name fyne.ThemeColorName, variant fyne.ThemeVariant) color.Color {
|
||||
switch name {
|
||||
case theme.ColorNameBackground:
|
||||
return ColorSlate900
|
||||
return OneDarkBackground
|
||||
case theme.ColorNameButton:
|
||||
return ColorSlate800
|
||||
return OneDarkGreen
|
||||
case theme.ColorNameDisabledButton:
|
||||
return ColorSlate700
|
||||
return OneDarkSubtleText
|
||||
case theme.ColorNamePrimary:
|
||||
return ColorSky500
|
||||
return OneDarkGreen
|
||||
case theme.ColorNamePlaceHolder:
|
||||
return ColorSlate400
|
||||
return OneDarkSubtleText
|
||||
case theme.ColorNameHover:
|
||||
return ColorSlate700
|
||||
return OneDarkYellow
|
||||
case theme.ColorNameForeground:
|
||||
return ColorSlate200
|
||||
return OneDarkText
|
||||
case theme.ColorNameDisabled:
|
||||
return ColorSlate400
|
||||
return OneDarkSubtleText
|
||||
case theme.ColorNameError:
|
||||
return ColorRed500
|
||||
return OneDarkRed
|
||||
case theme.ColorNameInputBackground:
|
||||
return ColorSlate800
|
||||
return OneDarkCardBackground
|
||||
case theme.ColorNameSeparator:
|
||||
return ColorSlate700
|
||||
return OneDarkSubtleText
|
||||
case theme.ColorNameSelection:
|
||||
return OneDarkYellow
|
||||
case theme.ColorNameShadow:
|
||||
return OneDarkCardBackground
|
||||
case theme.ColorNameFocus:
|
||||
return OneDarkYellow
|
||||
// case theme.ColorNameCardBackground:
|
||||
// return OneDarkCardBackground
|
||||
default:
|
||||
return theme.DefaultTheme().Color(name, variant)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *KettlebellTheme) Icon(name fyne.ThemeIconName) fyne.Resource {
|
||||
func (t *KettlebellThemeOneDark) Icon(name fyne.ThemeIconName) fyne.Resource {
|
||||
return theme.DefaultTheme().Icon(name)
|
||||
}
|
||||
|
||||
func (t *KettlebellTheme) Font(style fyne.TextStyle) fyne.Resource {
|
||||
func (t *KettlebellThemeOneDark) Font(style fyne.TextStyle) fyne.Resource {
|
||||
return theme.DefaultTheme().Font(style)
|
||||
}
|
||||
|
||||
func (t *KettlebellTheme) Size(name fyne.ThemeSizeName) float32 {
|
||||
func (t *KettlebellThemeOneDark) Size(name fyne.ThemeSizeName) float32 {
|
||||
switch name {
|
||||
case theme.SizeNamePadding:
|
||||
return 8
|
||||
|
|
|
|||
|
|
@ -15,19 +15,18 @@ import (
|
|||
"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 := canvas.NewText("00:00", theme.OneDarkText)
|
||||
timerLabel.TextSize = 60
|
||||
timerLabel.TextStyle.Bold = true
|
||||
timerLabel.Alignment = fyne.TextAlignCenter
|
||||
|
||||
setsLabel := canvas.NewText("0 / 0", theme.ColorSky400)
|
||||
setsLabel := canvas.NewText("0 / 0", theme.OneDarkGreen)
|
||||
setsLabel.TextSize = 48
|
||||
setsLabel.TextStyle.Bold = true
|
||||
setsLabel.Alignment = fyne.TextAlignCenter
|
||||
|
||||
repsLabel := canvas.NewText("0 Wiederholungen", theme.ColorSlate200)
|
||||
repsLabel := canvas.NewText("0 Wiederholungen", theme.OneDarkSubtleText)
|
||||
repsLabel.TextSize = 20
|
||||
repsLabel.Alignment = fyne.TextAlignCenter
|
||||
|
||||
|
|
@ -91,7 +90,7 @@ func MakeTrainingScreen(ts *services.TrainingService, ss *services.SettingsServi
|
|||
|
||||
setAction := func() {
|
||||
if !ts.State.IsTrainingRunning {
|
||||
return // Kein Satz ohne laufendes Training
|
||||
return
|
||||
}
|
||||
ts.CompleteSet()
|
||||
updateUI()
|
||||
|
|
@ -100,19 +99,19 @@ func MakeTrainingScreen(ts *services.TrainingService, ss *services.SettingsServi
|
|||
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
|
||||
setButton := widget.NewButton("Satz abschließen", setAction)
|
||||
setButton.Importance = widget.HighImportance
|
||||
setButton.Resize(fyne.NewSize(120, 60))
|
||||
|
||||
bottomPart := container.NewVBox(
|
||||
widget.NewButton("Satz abschließen", setAction),
|
||||
setButton,
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package utils
|
|||
|
||||
import "fmt"
|
||||
|
||||
// FormatDuration wandelt Sekunden in einen MM:SS String um.
|
||||
func FormatDuration(totalSeconds int64) string {
|
||||
if totalSeconds < 0 {
|
||||
totalSeconds = 0
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package utils
|
|||
|
||||
import "fmt"
|
||||
|
||||
// Hilfsfunktion (kann in einer utils.go Datei platziert werden)
|
||||
func formatDuration(totalSeconds int64) string {
|
||||
mins := totalSeconds / 60
|
||||
secs := totalSeconds % 60
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue