Skip to content

Add streak freeze and repair#19

Merged
bootuz merged 7 commits into
mainfrom
feature/streak-freeze-repair
Jun 5, 2026
Merged

Add streak freeze and repair#19
bootuz merged 7 commits into
mainfrom
feature/streak-freeze-repair

Conversation

@bootuz
Copy link
Copy Markdown
Owner

@bootuz bootuz commented Jun 5, 2026

Summary

  • Freeze: earn 1 streak freeze per 7 consecutive study days (cap 2); a missed day is auto-covered by a freeze so the streak survives. Free for everyone, no in-app currency.
  • Repair: if a streak breaks from a single recent missed day, a free one-tap "Repair" restores it — available after studying today, once per 30 days.
  • Synced via Firestore (last-write-wins), so the streak number stays consistent across devices.
  • The pure StreakCalculator is unchanged: a frozen day is fed to it as just another active day. All the new statefulness lives in one reconciler.

How it works

  • StreakReconciler (pure): decides which missed days become frozen, earns freezes (idempotent, capped), and computes repair eligibility.
  • StreakState persisted in Room (single-row table, migration v2→v3) and synced as a per-user Firestore doc via the existing SyncManager (LWW).
  • StreakStateManager ties the reconciler to the repos; reconcile runs on app foreground + session finish (never inside a Flow).
  • StreakProvider unions frozen days into the streak; the Today header shows a ❄️+count chip and a "Repair your N-day streak" banner; the session summary surfaces freeze count + repair.

Test Plan

  • ./gradlew :app:testDebugUnitTest — green (new: StreakReconcilerTest 9, StreakStateManagerTest, StreakStateRepositoryTest, SyncManagerTest streak LWW, StreakProviderTest union, StudyQueueViewModelTest freeze/repair exposure)
  • ./gradlew :app:assembleDebug — debug APK builds
  • ./gradlew :app:compileDebugAndroidTestKotlin — androidTest compiles
  • Migration MIGRATION_2_3 SQL verified character-for-character against Room's generated schema
  • Manual (emulator): build a streak, miss a day → a freeze is consumed and 🔥 survives with ❄️ shown; with no freeze, the streak breaks → after studying today a "Repair" banner appears → tap restores it

🤖 Generated with Claude Code

@bootuz bootuz merged commit 5db9b98 into main Jun 5, 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.

1 participant