Skip to content

feat: visualize 30 s idle countdown during the reminding phase - #1

Open
mo2g wants to merge 1 commit into
tmpbin:mainfrom
mo2g:feature/reminding-countdown-visual
Open

feat: visualize 30 s idle countdown during the reminding phase#1
mo2g wants to merge 1 commit into
tmpbin:mainfrom
mo2g:feature/reminding-countdown-visual

Conversation

@mo2g

@mo2g mo2g commented Jul 30, 2026

Copy link
Copy Markdown

Summary

During the reminding phase, the system waits for 30 seconds of inactivity (ackIdleThreshold = 30) to implicitly acknowledge the break. This countdown was previously invisible to the user. This PR surfaces the countdown in the menu bar and the popover ring so users can see exactly how many seconds remain.

Motivation

Users had no way to know how long until their break would auto-acknowledge (or what the orange/red flashing icon meant in concrete terms). Showing a real-time 30→0 countdown closes that gap.

Changes

Core principle: zero modification to existing BreakTimer acknowledgment/rest logic. The countdown is purely read-only — derived from the idleSeconds value already passed into every tick.

BreakTimer.swift (3 additions, 0 modifications to existing logic)

  • Stores lastIdleSeconds from the existing idleSeconds parameter in tick()
  • Adds a stored remindingCountdown property computed inside tickReminding() before any acknowledge call — avoids the timing bug where completeAcknowledge() changes phase before the delegate can read the value
  • Resets to -1 when phase is no longer .reminding

AppController.swift

  • One line added in syncViewModel(): reads timer.remindingCountdown → syncs to viewModel.remindingCountdown

AppViewModel.swift

  • Adds @Published var remindingCountdown: Int = -1
  • timeString: shows bare "Ns" during reminding (ring center readout)
  • Adds menuBarTitle: shows "Break Ns" during reminding (menu bar text)

MenuBarController.swift

  • .iconCountdown style now uses viewModel.menuBarTitle
  • Orange/red flash logic fully preserved (unaffected by this change)

RingViews.swift

  • Adds CountdownArc subview: pure render layer, semi-transparent arc shrinking 30→0
  • CountdownRing gains a countdown: Int? parameter + spring-bounce animation on activity reset

PopoverView.swift

  • Passes the countdown parameter to CountdownRing

L10n.swift

  • Adds "status.countdown": "%ds" (consistent across en / zh-Hans / ja)

Not modified

  • BreakTimer acknowledgment logic, nudge scheduling, autoPostpone, phase transitions — untouched
  • ackIdleThreshold remains 30
  • All 98 existing tests pass

Verification

swift build && swift test
  • Build passes
  • All 98 tests pass
  • Manual: trigger reminding → menu bar shows "Break Ns" counting down, orange/red flash still works
  • Manual: popover ring countdown arc shrinks, center readout syncs
  • Manual: move mouse/press key → countdown spring-bounces back to 30
  • Manual: stay idle for 30 s → acknowledgment into resting works correctly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant