timer/timer.go

116 lines
1.9 KiB
Go
Executable File

package main
import (
"fmt"
"time"
"github.com/everdev/mack"
)
type Typed func(*Timer) string
type Timer struct {
config Config
From time.Time
Typed Typed
paused bool
offset time.Duration
displayed bool
}
func NewTimer(config Config) (*Timer, error) {
t := &Timer{From: time.Now().Add(time.Duration(-1) * config.Offset), config: config}
return t, t.setTyped(config)
}
func (t *Timer) TogglePause() {
if t.paused {
t.Resume()
} else {
t.Pause()
}
}
func (t *Timer) Resume() {
t.paused = false
t.From = time.Now().Add(time.Duration(-1) * t.offset)
t.offset = 0
}
func (t *Timer) Pause() {
t.paused = true
t.offset = time.Since(t.From)
}
func (t *Timer) setTyped(config Config) error {
if config.Stopwatch {
t.Typed = NewBasicStopwatch
} else {
t.Typed = NewBasicTimer
}
if config.ETA {
t.Typed = WithETA(t.Typed)
}
if config.Done {
t.Typed = WithDone(t.Typed)
}
if config.TS {
t.Typed = WithTS(t.Typed)
}
return nil
}
func (t *Timer) Remaining() time.Duration {
remaining := time.Until(t.Deadline()) + time.Second
if remaining < 0 && !t.displayed {
t.displayed = true
go func() {
_, err := mack.Alert(fmt.Sprintf("Timer for %s done", t.config.Msg))
if err == nil {
t.Ack()
}
}()
}
return remaining
}
func (t *Timer) Deadline() time.Time {
from := t.From
if t.paused {
from = time.Now().Add(time.Duration(-1) * t.offset)
}
return from.Add(t.config.Duration)
}
func (t *Timer) Ack() {
for t.Done() {
t.From = t.From.Add(t.config.Duration)
}
t.displayed = false
}
func (t *Timer) Reset() {
t.Ack()
t.From = time.Now()
}
func (t *Timer) Done() bool {
return time.Now().After(t.From.Add(t.config.Duration))
}
func (t *Timer) String() string {
return t.Typed(t)
}
func (t *Timer) Add(d time.Duration) {
t.From = t.From.Add(d)
}
func (t *Timer) Sub(d time.Duration) {
t.Add(time.Duration(-1) * d)
}