perf(learn): a rated card gives way to the next one at once

Rating a card while studying waited for its review to be written, then
for the card's schedule to be replayed, before the next card showed.
StudySessionBloc now starts keeping the review and shows what comes
next at once: the card's new place in the round is worked out from its
reviews with the new one counted as if kept already
(ReviewRepository.schedulesAsStudied's pending, each review counted
once should it be kept by then).

Should keeping it fail, the step leaves the session's Undo, the rating
leaves its accuracy, and the card comes back where it stood, saying so
(withRatingFailed), as a failed rating did before. An Undo of a rating
still being kept waits for it and takes it back once kept; one that
couldn't be kept has nothing to take back, and the Undo has brought
the card back already.

Whats-New: While studying, the next flashcard shows the moment you rate one.
Whats-New-De: Beim Lernen kommt die nächste Karteikarte, sobald du eine bewertet hast.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-07 23:26:25 +01:00
commit 4940230ef1
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:halkyon_learn_flutter/src/feature/study/data/review_gateway.dart';
/// A [ReviewGateway] in memory; ids sort by creation, as UUID v7 ids do.
@ -10,6 +12,9 @@ class FakeReviewGateway() implements ReviewGateway {
/// When set, storing a review fails with it.
Exception? failWrites;
/// When set, storing a review waits for it to complete.
Completer<void>? holdWrites;
@override
Future<List<ReviewRow>> reviewsOf(Set<String> cardIds) async => [
for (final row in rows)
@ -21,6 +26,9 @@ class FakeReviewGateway() implements ReviewGateway {
@override
Future<List<ReviewRow>> insert(Iterable<ReviewRow> reviews) async {
if (holdWrites case final hold?) {
await hold.future;
}
if (failWrites case final error?) {
throw error;
}