perf(learn): Delete now leaves Recently deleted at once
Deleting a studyset for good blanks and deletes every card, note, path and PDF of its subtree before the studyset's row goes, which took about 3 s while the studyset stayed in Recently deleted. Now the repository's Recently deleted leaves it out at once (StudysetRepository.leaving and stay, applied to the value last read without reading again), the deletion runs in the background, still one at a time in StudysetDeletions' queue, and where it fails the studyset shows there again, read anew with what is left of it, and a snack bar says so. Whats-New: Delete now in Recently deleted takes a studyset away at once. Whats-New-De: „Jetzt löschen“ unter „Zuletzt gelöscht“ entfernt ein Lernset sofort. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
c954e844f7
commit
920e1c6c13
2 changed files with 190 additions and 7 deletions
|
|
@ -159,6 +159,59 @@ void main() {
|
|||
expect([for (final s in await studysets.withDeleted()) s.id], [greek]);
|
||||
});
|
||||
|
||||
test('Delete now takes the studyset off Recently deleted at once, while '
|
||||
'it is deleted in the background', () async {
|
||||
open();
|
||||
final japanese = await studysets.create(StudysetContent.titled('Japanese'));
|
||||
await card(japanese);
|
||||
await deleteAt(japanese);
|
||||
final shown = <List<String>>[];
|
||||
final following = studysets.watchDeleted().listen(
|
||||
(deleted) => shown.add([for (final s in deleted) s.id]),
|
||||
);
|
||||
addTearDown(following.cancel);
|
||||
await eventually(() => shown.isNotEmpty && shown.last.contains(japanese));
|
||||
final hold = cardGateway.holdDeletes = Completer<void>();
|
||||
|
||||
final deleting = deletions.deleteForGood(japanese);
|
||||
await pumpEventQueue();
|
||||
expect(shown.last, isEmpty, reason: 'at once');
|
||||
expect(studysetGateway.deleted, isEmpty, reason: 'not done yet');
|
||||
|
||||
hold.complete();
|
||||
await deleting;
|
||||
await pumpEventQueue();
|
||||
expect(studysetGateway.deleted, [japanese]);
|
||||
expect(shown.last, isEmpty);
|
||||
});
|
||||
|
||||
test('a studyset Delete now fails on shows in Recently deleted again, and '
|
||||
'the failure reaches the caller', () async {
|
||||
open();
|
||||
final japanese = await studysets.create(StudysetContent.titled('Japanese'));
|
||||
await card(japanese);
|
||||
await deleteAt(japanese);
|
||||
final shown = <List<String>>[];
|
||||
final following = studysets.watchDeleted().listen(
|
||||
(deleted) => shown.add([for (final s in deleted) s.id]),
|
||||
);
|
||||
addTearDown(following.cancel);
|
||||
await eventually(() => shown.isNotEmpty && shown.last.contains(japanese));
|
||||
cardGateway.failDeletes = Exception('The disk is full');
|
||||
|
||||
await expectLater(deletions.deleteForGood(japanese), throwsException);
|
||||
await pumpEventQueue();
|
||||
|
||||
expect(
|
||||
shown,
|
||||
containsAllInOrder([
|
||||
<String>[],
|
||||
[japanese],
|
||||
]),
|
||||
);
|
||||
expect(shown.last, [japanese]);
|
||||
});
|
||||
|
||||
test('a studyset deleted inside one deleted later goes on its own '
|
||||
'clock, and with the other at the latest', () async {
|
||||
open();
|
||||
|
|
|
|||
|
|
@ -792,6 +792,45 @@ void main() {
|
|||
expect(find.text('No studysets yet'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('Delete now takes the studyset off Recently deleted at once; '
|
||||
'where deleting it fails, it comes back and a snack bar says so', (
|
||||
tester,
|
||||
) async {
|
||||
gateway.receiveRemoteChange(
|
||||
'japanese',
|
||||
encodeStudysetPayload(StudysetContent.titled('Japanese')),
|
||||
deletedAt: clock.now().toUtc(),
|
||||
);
|
||||
final cards = CardRepository(cardGateway);
|
||||
addTearDown(cards.dispose);
|
||||
await cards.create(
|
||||
'japanese',
|
||||
CardContent(front: RichContent.empty(), back: RichContent.empty()),
|
||||
);
|
||||
await showLibrary(tester);
|
||||
final hold = cardGateway.holdDeletes = Completer<void>();
|
||||
cardGateway.failDeletes = Exception('The disk is full');
|
||||
|
||||
await tester.tap(onDeletedCard('Japanese', find.byTooltip('Options')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Delete now'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Delete for good'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Recently deleted'), findsNothing, reason: 'at once');
|
||||
|
||||
hold.complete();
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Recently deleted'), findsOneWidget);
|
||||
expect(
|
||||
find.text(
|
||||
"“Japanese” couldn't be deleted. It's back in Recently deleted.",
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(gateway.deleted, isEmpty);
|
||||
});
|
||||
|
||||
testWidgets('a card invites studying its due cards, and counts anew after '
|
||||
'studying', (tester) async {
|
||||
stored('japanese', 'Japanese');
|
||||
|
|
|
|||
Loading…
Reference in a new issue