Add menu bar timer showing how long Caffeine has been active - #15
Open
deathemperor wants to merge 3 commits into
Open
Add menu bar timer showing how long Caffeine has been active#15deathemperor wants to merge 3 commits into
deathemperor wants to merge 3 commits into
Conversation
The menu bar icon gave no indication of how long Caffeine had been running, and for indefinite activations nothing was tracking it at all — the display timer only ran when a timeout was set. Track the activation date and run the display timer whenever active, then render the duration next to the status item icon. Three preferences control it: show/hide, elapsed vs. remaining (remaining is undefined for indefinite activations, so those fall back to elapsed), and a compact (1:23:45) or verbose (1h 23m) format. The menu's status item honors the elapsed/remaining choice too. Durations are formatted with Duration.FormatStyle so they localize automatically; only the new preference labels needed new strings. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WxSse82nGGvb6CHbDatmfC
Remaining mode fell back to counting elapsed time when no timeout was set, which reads as a countdown that never ends. There is nothing to count down to, so show the infinity symbol instead. Elapsed mode is unchanged and still counts up. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WxSse82nGGvb6CHbDatmfC
The ♾️ emoji renders in color and reads as a dark blob in the menu bar. U+221E is drawn as regular text, so it picks up the menu bar tint in both light and dark appearance. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WxSse82nGGvb6CHbDatmfC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The menu bar icon shows that Caffeine is active, but not for how long. For indefinite activations nothing was tracking it at all —
displayTimeronly ran when a timeout was set, and the menu's status item just read "Caffeine is active".What
A live duration next to the status item icon, in monospaced digits so the item doesn't jitter as the time changes.
Three new preferences (Preferences window, below "Keep apps active"):
CAShowMenuBarTimerCATimerDisplayModeelapsedCATimerFormatcompactCompact renders
0:42/5:07/1:23:45; verbose renders42s/5m/1h 23m. Remaining mode has nothing to count down to for an indefinite activation, so it shows ∞ instead; elapsed mode still counts up.Implementation notes:
CaffeineViewModelgainsactivationDateand a publishedelapsedTime. The 1-second display timer now runs whenever Caffeine is active, not only when a timeout is set, and updates bothelapsedTimeandtimeRemaining.Duration.FormatStyle, so both styles localize automatically — only the seven new preference labels needed.stringsentries. They're added to all 13 localizations.fractionalPart: .hide(rounded: .towardZero); without it the default rounding renders 1:23:45 as "1h 24m" and 59:59 as "60m", so the verbose readout would run ahead of the compact one.Behavior change worth reviewing
formattedTimeRemaining()is renamedformattedStatusText()and now honors the display-mode preference. With the defaultelapsedmode, the menu's status item shows elapsed time for timed activations where it previously showed remaining. Happy to flip the default toremainingif you'd rather keep the existing behavior out of the box.Testing
xcodebuild -scheme Caffeine -destination "platform=macOS" build— succeeds.swiftformat .— no changes.Localizable.stringspassplutil -lint.The 12 non-English strings are my translations and would benefit from a native-speaker pass.