feat(sleep): Bedtime tracking works without the quiet-hours schedule (#126) by foureight84 · Pull Request #128 · foureight84/PulseLoopAndroid · GitHub
Skip to content

feat(sleep): Bedtime tracking works without the quiet-hours schedule (#126) - #128

Merged
foureight84 merged 1 commit into
mainfrom
fix/126-bedtime-without-schedule
Oct 20, 2026
Merged

foureight84 merged 1 commit into
mainfrom
fix/126-bedtime-without-schedule

Conversation

@foureight84

Copy link
Copy Markdown
Owner

Fixes #126.

"Track Bedtime / DND mode" only worked as part of "Sleep quiet hours". A night without Bedtime fell back to the clock schedule and cut the night at its end, and trimmed minutes are never imported. The two are now independent.

Bedtime tracking Schedule Import Gap bridging (#105)
off off whole record none
off on clock window (unchanged) clock window (unchanged)
on off (new) trimmed to the Bedtime windows it overlaps; a record overlapping none is kept whole inside a Bedtime window; otherwise none
on on Bedtime windows, schedule as fallback (unchanged) unchanged

"Bedtime on" means the toggle is on and Notification access is granted, as before.

Overlap, not "the day has a window". The night-window lookup spans 48 h, so a DND meeting the next afternoon would count as the night having a Bedtime window and drop the whole night. A record is trimmed only by windows it actually overlaps.

Changes

  • QuietHoursPrefs.resolveKeptMinutes: pure resolution of the four cases. nightWindows/effectiveEnd moved here from SleepGapBridge so import and bridging share them.
  • SleepGapBridge: bridges when either source is on; uses the clock only when the schedule is on.
  • EventPersistenceSubscriber: always resolves through keptMinutesForRecord, which keeps the whole record when nothing is on.
  • Settings: the card is now "Sleep trimming" with two independent switches; the Notification-access flow works with the schedule off. Copy says trimmed minutes are never imported.

Migration

Bedtime on with the schedule off was reachable before (turn both on, then the schedule off) and meant no trimming. Under the new rules it would start trimming on the next sync, so a one-time migration (independentBedtime.v1) clears the Bedtime flag in that state. Every other state is unchanged.

Tests

./gradlew --no-daemon testDebugUnitTest: 1537 pass. New QuietHoursPrefsTest cases use the #126 night across all four combinations, the next-afternoon DND case, and the migration table; SleepGapsTest checks the bridge and the import pick the same source.

Not checked on a device; the settings layout is checked only by compilation.

🤖 Generated with Claude Code

…126)

"Track Bedtime / DND mode" was read only while "Sleep quiet hours" was on,
so a night without Bedtime fell back to the clock schedule and lost every
ring minute past its end, permanently (trimmed minutes are never imported).
The two are now independent switches:

- Bedtime only: trim to the Bedtime/DND windows a record overlaps; a record
  that overlaps none is kept whole.
- Schedule only, and both: unchanged.
- Neither: no trimming.

QuietHoursPrefs.resolveKeptMinutes is the pure resolution the import gate
calls; SleepGapBridge.forWindows follows the same source order, so Bedtime
alone also bridges gaps inside its window.

Upgrade: Bedtime=on with the schedule off was reachable (the row hid but kept
its value) and meant no trimming. A one-time migration clears it, so nobody
starts trimming on upgrade.
@foureight84
foureight84 merged commit b406b2f into main Oct 20, 2026
1 check passed
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.

Bedtime tracking without the fallback schedule

1 participant