feat(app): undo deleting a card
Deleting a card, from the list or while studying, asks first ("Delete
flashcard?"), then offers Undo for a few seconds ("Flashcard deleted").
Meanwhile the card leaves every list and session; once the time to
undo is over, its revisions are blanked and it is deleted for good, as
notes and studysets already are (CardDeletions, a DelayedDeletions).
Undo while studying puts the card back into the round where it was.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
c5cbc53bdd
commit
2b188641c3
1 changed files with 219 additions and 44 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/content/rich_content.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/card/bloc/card_list_bloc.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/card/data/card_deletions.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/card/data/card_repository.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/study/data/review_repository.dart';
|
||||
|
|
@ -22,14 +23,17 @@ void main() {
|
|||
late CardRepository cards;
|
||||
late TagRepository tags;
|
||||
late ReviewRepository reviews;
|
||||
late CardDeletions deletions;
|
||||
|
||||
setUp(() {
|
||||
gateway = FakeCardGateway();
|
||||
cards = CardRepository(gateway);
|
||||
tags = TagRepository(FakeTagGateway(), cardChanges: cards.changes);
|
||||
reviews = ReviewRepository(FakeReviewGateway());
|
||||
deletions = CardDeletions(cards, undoWindow: Duration.zero);
|
||||
});
|
||||
tearDown(() async {
|
||||
await deletions.dispose();
|
||||
await reviews.dispose();
|
||||
await tags.dispose();
|
||||
await cards.dispose();
|
||||
|
|
@ -40,7 +44,7 @@ void main() {
|
|||
'a card reported or buried shows so, and either is taken back',
|
||||
() async {
|
||||
final id = await cards.create('japanese', card('猫', 'cat'));
|
||||
final bloc = CardListBloc(cards, tags, reviews, 'japanese')
|
||||
final bloc = CardListBloc(cards, tags, reviews, deletions, 'japanese')
|
||||
..add(const CardListEventStarted());
|
||||
addTearDown(bloc.close);
|
||||
Future<CardListStateLoaded> next(
|
||||
|
|
@ -70,7 +74,7 @@ void main() {
|
|||
|
||||
test('lists the cards and follows every change', () async {
|
||||
await cards.create('japanese', card('猫', 'cat'));
|
||||
final bloc = CardListBloc(cards, tags, reviews, 'japanese')
|
||||
final bloc = CardListBloc(cards, tags, reviews, deletions, 'japanese')
|
||||
..add(const CardListEventStarted());
|
||||
addTearDown(bloc.close);
|
||||
|
||||
|
|
@ -100,7 +104,7 @@ void main() {
|
|||
test('moves a card', () async {
|
||||
await cards.create('japanese', card('a', ''));
|
||||
await cards.create('japanese', card('b', ''));
|
||||
final bloc = CardListBloc(cards, tags, reviews, 'japanese')
|
||||
final bloc = CardListBloc(cards, tags, reviews, deletions, 'japanese')
|
||||
..add(const CardListEventStarted());
|
||||
addTearDown(bloc.close);
|
||||
final loaded = await bloc.stream.firstWhere(
|
||||
|
|
@ -137,7 +141,7 @@ void main() {
|
|||
await tags.setTagsOf(ids[0], {noun});
|
||||
await tags.setTagsOf(ids[1], {noun});
|
||||
await tags.setTagsOf(ids[2], {verb});
|
||||
bloc = CardListBloc(cards, tags, reviews, 'japanese')
|
||||
bloc = CardListBloc(cards, tags, reviews, deletions, 'japanese')
|
||||
..add(const CardListEventStarted());
|
||||
});
|
||||
tearDown(() => bloc.close());
|
||||
|
|
|
|||
Loading…
Reference in a new issue