refactor(app): flashcards keep the order they came in, without Reorder

Studying breaks the order of due cards anyway; what follows the list
order is new cards and cramming, and that order comes from creating and
importing, with sub-studysets putting lessons in order. No one drags a
card among a thousand (decided 2026-10-08).

Gone: Reorder and the grip on flashcards, CardListEventMoved,
CardRepository.move and the gateway's updatePosition, with their tests.
Each card keeps its stored position, so the order stays the same on
every device. liftWhileDragged is Material's plain lift again, for the
lists that keep Reorder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMm7usAo6q9ZZRoPkWjoxi
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-08 18:42:15 +02:00
commit 6c9dfadf27
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
3 changed files with 97 additions and 410 deletions

View file

@ -95,30 +95,6 @@ void main() {
),
);
});
test('moves a card', () async {
await cards.create('japanese', card('a', ''));
await cards.create('japanese', card('b', ''));
final bloc = CardListBloc(cards, tags, deletions, 'japanese')
..add(const CardListEventStarted());
addTearDown(bloc.close);
final loaded = await bloc.stream.firstWhere(
(state) => state is CardListStateLoaded,
) as CardListStateLoaded;
bloc.add(CardListEventMoved(loaded.cards.last, toIndex: 0));
await expectLater(
bloc.stream,
emits(
isA<CardListStateLoaded>().having(
(s) => [for (final card in s.cards) card.content.front],
'fronts',
[text('b'), text('a')],
),
),
);
});
});
group('CardListBloc with tags', () {

View file

@ -195,25 +195,6 @@ void main() {
expect(await repository.headsOf('card-9999'), isEmpty);
});
test(
'moves a card between two others, to the start and to the end',
() async {
for (final front in ['a', 'b', 'c']) {
await repository.create('japanese', card(front, ''));
}
Future<List<Card>> cards() => repository.cardsOf('japanese');
await repository.move('japanese', (await cards())[2], toIndex: 1);
expect(fronts(await cards()), ['a', 'c', 'b']);
await repository.move('japanese', (await cards())[2], toIndex: 0);
expect(fronts(await cards()), ['b', 'a', 'c']);
await repository.move('japanese', (await cards())[0], toIndex: 2);
expect(fronts(await cards()), ['a', 'c', 'b']);
},
);
test('deleting blanks every revision before the card goes', () async {
final id = await repository.create('japanese', card('秘密', 'secret'));
await repository.save(

View file

@ -239,7 +239,7 @@ void main() {
testWidgets(
"on desktop, a card's whole … opens its options, with no handle to "
'drag it over it',
'drag it over it: cards keep the order they came in',
(tester) async {
await cards.create('japanese', card('猫', 'cat'));
await cards.create('japanese', card('犬', 'dog'));
@ -247,6 +247,7 @@ void main() {
expect(find.byIcon(Icons.drag_handle), findsNothing);
expect(find.byTooltip('Drag to reorder'), findsNothing);
expect(find.text('Reorder'), findsNothing);
await tester.tap(optionsOf('猫'));
await tester.pumpAndSettle();
expect(find.text('Edit'), findsOneWidget);
@ -254,54 +255,6 @@ void main() {
variant: TargetPlatformVariant.only(TargetPlatform.linux),
);
testWidgets('Reorder beside the tabs gives each card a handle to drag it '
'by instead of its options, until Done', (tester) async {
final first = await cards.create('japanese', card('猫', 'cat'));
final second = await cards.create('japanese', card('犬', 'dog'));
await showList(tester);
await tester.tap(find.text('Reorder'));
await tester.pumpAndSettle();
expect(find.byTooltip('Drag to reorder'), findsNWidgets(2));
expect(optionsOf('猫'), findsNothing);
// The first card, dragged below the second.
final rowHeight = tester.getSize(find.widgetWithText(CardTile, '猫')).height;
final drag = await tester.startGesture(
tester.getCenter(find.byTooltip('Drag to reorder').first),
);
for (var step = 0; step < 6; step++) {
await drag.moveBy(Offset(0, rowHeight * 1.5 / 6));
await tester.pump(const Duration(milliseconds: 50));
}
await drag.up();
await tester.pumpAndSettle();
expect(
[
for (final card in await cards.cardsOf('japanese')) card.id,
],
[second, first],
);
expect(
tester.getTopLeft(find.text('犬')).dy,
lessThan(tester.getTopLeft(find.text('猫')).dy),
);
await tester.tap(find.text('Done'));
await tester.pumpAndSettle();
expect(find.byTooltip('Drag to reorder'), findsNothing);
expect(optionsOf('猫'), findsOneWidget);
});
testWidgets('Reorder shows with two cards or more, all of them showing', (
tester,
) async {
await cards.create('japanese', card('猫', 'cat'));
await showList(tester);
expect(find.text('Reorder'), findsNothing);
});
testWidgets('builds only the cards in view, so a studyset of a thousand '
'opens as fast as one of ten', (tester) async {
await cards.createAll('japanese', [