The course ending shows the longest streak and the Module Rewards - #557
Merged
Conversation
The completion moment's two flagged substitutions (#120's build notes) are replaced by the derivations #149 asks for, now that both inputs exist. The longest run is the streak fold read at its high-water mark rather than its end, so the two numbers cannot disagree about what a run is: a day a freeze covered joins the run either side of it for both. A Module Reward is a card the collectibles bank points at a module — the pointer only a module-awarded card carries — counted off the cards the learner owns. Nothing new is stored: both come off the day set and the owned-collectible set a reset already clears. Along the way: `collectedCardsProvider` was the completion screen's only reader, so it goes, and with it the two invalidations that were keeping a value nothing read. `getCardForModule` matched on a hazard that no longer exists — a lesson card carries no module pointer — so its condition and its note now say the same thing. Closes #149
`isModuleReward` becomes a getter on `CoffeeCardModel`, next to the field it reads — the shape `CollectibleUnlock.isValid` already uses. The trap it guards against (a lesson card's owning module lives in `moduleTag`) was written out twice; `getCardForModule` now points at the getter instead of restating it. The count loses its provider. It chained `cardsWithCollectionProvider.future`, which is the shape the comment directly above it warns about — a chained read hit a Riverpod pause-state assertion under the shell. The screen watches the grid's own provider and counts, so there is nothing new to invalidate. Restores the half of that comment still owed: a caller that collects a card invalidates `cardsWithCollectionProvider`, and everything showing a collection hangs off it.
This was referenced Sep 9, 2026
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.
Closes #149.
The completion moment's two flagged substitutions become the derivations the
spec asked for: the learner's longest streak, and the number of Module
Rewards they earned. Both come off state that already exists, so nothing new
is stored and a reset still leaves nothing behind.
The longest run is the streak fold read at its high-water mark rather than at
its end — one fold, so it and the current streak cannot disagree about what a
run is. A Module Reward is a card the collectibles bank points at a module;
that pointer is the only thing separating the five from the thirty-two lesson
cards.
Worth knowing:
collectedCardsProviderwas the completion screen's lastreader, so it goes, and the two invalidations that kept it warm go with it —
the cards grid and the new count both hang off
cardsWithCollectionProvider,which those callers already refresh.
getCardForModulematched on a hazardthat no longer exists (a lesson card carries no module pointer); its condition
and its note now say the same thing.
Checks:
flutter analyzeclean, full suite green, metrics clean, comment capclean on every file the branch touches.