diff --git a/ui/clock.go b/ui/clock.go index 2ff52d5..2ca4ab3 100644 --- a/ui/clock.go +++ b/ui/clock.go @@ -140,8 +140,8 @@ func RenderBigClock(t time.Time) string { timeStr := fmt.Sprintf("%02d:%02d:%02d", h, m, s) - // Colon visible for first 500ms of each second, hidden for last 500ms. - colonVisible := t.UnixMilli()%1000 < 500 + // 1500ms cycle: visible for 1000ms, hidden for 500ms. + colonVisible := t.UnixMilli() % 1500 < 1000 var lines [7]string for i := range lines { diff --git a/ui/model.go b/ui/model.go index 6779c98..02c34d1 100644 --- a/ui/model.go +++ b/ui/model.go @@ -47,6 +47,8 @@ type Model struct { firingBlink bool firingStart time.Time snoozeCount int + snoozeUntil time.Time + snoozeName string // Form state form *formModel @@ -66,14 +68,14 @@ func NewModel(store *db.Store, sched *scheduler.Scheduler, pl *player.Player) Mo func (m Model) Init() tea.Cmd { return tea.Batch( - tickEveryHalfSecond(), + tick(), listenForAlarms(m.scheduler), loadAlarmsCmd(m.store), ) } -func tickEveryHalfSecond() tea.Cmd { - return tea.Every(500*time.Millisecond, func(t time.Time) tea.Msg { +func tick() tea.Cmd { + return tea.Every(100*time.Millisecond, func(t time.Time) tea.Msg { return tickMsg(t) }) } @@ -113,7 +115,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if m.firingAlarm != nil { m.firingBlink = !m.firingBlink } - return m, tickEveryHalfSecond() + return m, tick() case alarmFiredMsg: alarm := msg.Alarm @@ -127,6 +129,8 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case snoozeFireMsg: alarm := db.Alarm(msg) m.snoozeCount++ + m.snoozeUntil = time.Time{} + m.snoozeName = "" m.startFiring(&alarm) return m, autoTimeoutCmd() @@ -172,6 +176,8 @@ func (m Model) handleKey(msg tea.KeyMsg) (tea.Model, tea.Cmd) { m.player.Stop() alarm := *m.firingAlarm m.firingAlarm = nil + m.snoozeUntil = time.Now().Add(snoozeDuration) + m.snoozeName = alarm.Name m.statusMsg = fmt.Sprintf("Snoozed '%s' for 5 minutes", alarm.Name) return m, snoozeCmd(alarm, snoozeDuration) } @@ -295,11 +301,22 @@ func (m Model) View() string { clockStr = lipgloss.PlaceHorizontal(m.width, lipgloss.Center, clockStr) sections = append(sections, clockStr) + // Spacer + sections = append(sections, "") + // Date line dateLine := StatusStyle.Render(m.now.Format("Monday, 02 January 2006")) dateLine = lipgloss.PlaceHorizontal(m.width, lipgloss.Center, dateLine) sections = append(sections, dateLine) + // Snooze indicator + if !m.snoozeUntil.IsZero() && m.now.Before(m.snoozeUntil) { + snoozeText := fmt.Sprintf("[Snoozing %s until %s]", m.snoozeName, m.snoozeUntil.Format("15:04:05")) + snoozeLine := AlarmFiringStyle.Render(snoozeText) + snoozeLine = lipgloss.PlaceHorizontal(m.width, lipgloss.Center, snoozeLine) + sections = append(sections, snoozeLine) + } + // Firing alarm overlay if m.firingAlarm != nil { firingText := fmt.Sprintf("ALARM: %s", m.firingAlarm.Name) diff --git a/woke b/woke index a58f85e..a096605 100755 Binary files a/woke and b/woke differ