diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..82cc20c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,22 @@ +# Changelog + +All notable changes to Pommedoro are documented here. + +## Unreleased + +### Added + +- **Work log** — Today's work log view (menu: View Work Log) with intervals, intent, reflection, and suggestion feedback. Permanent log file at `~/Documents/pommedoro/worklog.log`; in-app view shows today only. Copy and "Back to Work" from the log screen. +- **Intent pre-fill** — On the "Ready when you are" reflection/planning screen, the "What do you intend to work on next?" field is pre-filled with your current or last intent from today's log. + +### Changed + +- **Pause / Resume** — Menu bar item toggles to "Resume" when paused; state is visible at a glance. +- **Back to work** — "Pause" and "Continue" from the break/ready overlay no longer reset the countdown when you're mid-interval; remaining time is preserved. +- **Countdown flash schedule** — From 5 minutes: one flash per minute until 3 minutes, then every 30 seconds until 1 minute, then the existing last-minute pattern (every 10s → 5s → 2s, last 5s solid). See [README.md](README.md#phase-1-escalating-awareness). + +### Technical + +- Countdown pulse logic moved into `CountdownPulseSchedule`; shared by work and break. +- `KeyableWindow` for overlay text input (reflection/intent fields). +- Break flow: suggestion feedback, wellness reflection, then reflection + intent screen with Pause | Finish Day | Continue. diff --git a/README.md b/README.md index 615df57..f91f4e4 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,11 @@ The actionable suggestions matter too. "Take a break" is an instruction with no - **Launch at Login** via macOS LaunchAgent - **Native macOS app** — no Electron, no web views, just AppKit +## Changelog + +See [CHANGELOG.md](CHANGELOG.md) for release history and recent changes. + + ## Install Download the latest DMG directly: diff --git a/Sources/Pommedoro/CountdownPulseSchedule.swift b/Sources/Pommedoro/CountdownPulseSchedule.swift index 13cf3fc..91c988b 100644 --- a/Sources/Pommedoro/CountdownPulseSchedule.swift +++ b/Sources/Pommedoro/CountdownPulseSchedule.swift @@ -1,7 +1,7 @@ import Foundation /// Single source of truth for countdown pulse timing. Used by both default and debug modes -/// First 30s: blink every 10s; next 15s: every 5s; next 10s: every 2s; last 5s: solid. +/// 5 min→3 min: once per minute; 3 min→1 min: every 30s; last minute: every 10s→5s→2s; last 5s: solid. enum CountdownPulseSchedule { /// Whether we are in the "flashing" phase (remaining within countdown window). @@ -10,14 +10,16 @@ enum CountdownPulseSchedule { return remainingSeconds <= effective && remainingSeconds > 0 } - /// Whether to trigger a blink this second. Same logic for debug and default. - /// First 30s remaining: every 10s; next 15s: every 5s; next 10s: every 2s; last 5s: solid. + /// Whether to trigger a blink this second. + /// 5 min→3 min: once per minute; 3 min→1 min: every 30s; last minute: every 10s, then 5s, then 2s; last 5s: solid. static func shouldBlink(remainingSeconds: Int) -> Bool { let s = remainingSeconds if s <= 5 { return false } // last 5: solid - if s <= 15 { return s % 2 == 0 } // next 10: every 2s (14,12,10,8,6) - if s <= 30 { return s % 5 == 0 } // next 15: every 5s (30,25,20,15) - return s % 10 == 0 // first 30: every 10s (60,50,40,30,…) + if s <= 15 { return s % 2 == 0 } // 6–15: every 2s + if s <= 30 { return s % 5 == 0 } // 16–30: every 5s + if s <= 60 { return s % 10 == 0 } // 31–60: every 10s (last minute) + if s <= 180 { return s % 30 == 0 } // 61–180: every 30s (last 3 min) + return s % 60 == 0 // 181–300: once per minute (5 min → 3 min) } /// When remaining <= 5, show solid overlay instead of blinking.