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) }