// See the LICENSE file to see your liberties and restrictions. package main import ( "time" "fyne.io/fyne/v2" "fyne.io/fyne/v2/app" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" ) func main() { var timer time.Duration var ticking bool = false var status string = "WORK TIME" // TODO: GET DEFAULT WORK AND BREAK TIMES FROM FILESYSTEM var defaultWorkTime string = "25m" var defaultBreakTime string = "5m" a := app.New() w := a.NewWindow(status) w.SetFixedSize(true) w.Resize(fyne.NewSize(400, 50)) workEntry := widget.NewEntry() workEntry.SetText(defaultWorkTime) workEntry.TextStyle.Monospace = true workEntry.Refresh() breakEntry := widget.NewEntry() breakEntry.SetText(defaultBreakTime) breakEntry.TextStyle.Monospace = true breakEntry.Refresh() var beginButton *widget.Button beginButton = widget.NewButtonWithIcon("Start", theme.Icon(theme.IconNameMediaPlay), func() { go func() { if !ticking { ticking = true var duration time.Duration var err error if status == "WORK TIME" { duration, err = time.ParseDuration(workEntry.Text) } else { duration, err = time.ParseDuration(breakEntry.Text) } if err != nil { neww := fyne.CurrentApp().NewWindow("Error") neww.Resize(fyne.NewSize(500, 500)) fyne.Do(func() { neww.Show() }) err_dialog := dialog.NewError(err, neww) err_dialog.SetOnClosed(func() { neww.Close() }) err_dialog.Show() ticking = false return } beginButton.Icon = theme.Icon(theme.IconNameMediaPause) fyne.Do(func() { beginButton.SetText("Stop") }) beginButton.Importance = widget.LowImportance fyne.Do(func() { beginButton.Refresh() }) timer = duration timeStarted := time.Now() for ticking { cur := time.Since(timeStarted) if status == "WORK TIME" { workEntry.Disable() workEntry.SetText((cur.Round(time.Second) - timer.Round(time.Second)).Abs().String()) } else { breakEntry.Disable() breakEntry.SetText((cur.Round(time.Second) - timer.Round(time.Second)).Abs().String()) } if cur >= timer { if status == "WORK TIME" { status = "BREAK TIME" workEntry.SetText(defaultWorkTime) workEntry.Enable() timer, err = time.ParseDuration(breakEntry.Text) if err != nil { panic(err) } timer = timer + cur w.SetTitle(status) } else { status = "WORK TIME" breakEntry.SetText(defaultBreakTime) breakEntry.Enable() timer, err = time.ParseDuration(workEntry.Text) if err != nil { panic(err) } timer = timer + cur w.SetTitle(status) } } else { time.Sleep(time.Second * 1) } } } else { ticking = false workEntry.Enable() breakEntry.Enable() beginButton.Icon = theme.Icon(theme.IconNameMediaPlay) fyne.Do(func() { beginButton.SetText("Start") }) beginButton.Importance = widget.HighImportance fyne.Do(func() { beginButton.Refresh() }) } }() }) beginButton.Importance = widget.HighImportance w.SetContent(container.NewGridWithColumns(3, workEntry, breakEntry, container.NewVBox(beginButton, widget.NewButtonWithIcon("Skip", theme.Icon(theme.IconNameMediaSkipNext), func() { if status == "WORK TIME" { status = "BREAK TIME" } else { status = "WORK TIME" } w.SetTitle(status) })))) menu := fyne.NewMainMenu(fyne.NewMenu("root"), fyne.NewMenu("help", fyne.NewMenuItem("valid time arguments", func() { neww := fyne.CurrentApp().NewWindow("Help") neww.Resize(fyne.NewSize(500, 500)) fyne.Do(func() { neww.Show() }) help_dialog := dialog.NewInformation("Help", "Here are some valid time arguments:\n3ns (3 nanoseconds)\n3s (3 seconds)\n2m (2 minutes)\n2m3s (2 minutes and 3 seconds)\n2h1m1s (2 hours 1 minute and 1 second)", neww) help_dialog.SetOnClosed(func() { neww.Close() }) help_dialog.Show() }))) w.SetMainMenu(menu) w.ShowAndRun() }