perf(learn): flashcards moved in the card browser go at once, in one write

Moving the chosen cards to another studyset wrote them one at a time,
each looking up its privacy keys and writing its row, while the
browser still showed them. CardBrowserBloc now shows the move at once
(gone from here, or after the cards of the studyset they go into where
the browser shows it, _withMoves) and puts them back where the move
fails, counting the failure for the screen's snack bar
(moveFailures, cardBrowserMoveFailed).

CardRepository.moveTo hands the gateway every card's new position at
once (CardGateway.updateStudysets): SyncCardGateway reads them in one
query, checks every card's key before changing any (one private card
among them refuses the whole move, as before for each), rekeys those
that need it, and updates every row in one write and one sync request.
updateStudyset delegates to it.

Whats-New: Flashcards moved to another studyset in the card browser move at once.
Whats-New-De: Im Karteikarten-Browser in ein anderes Lernset verschobene Karteikarten sind sofort dort.
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:19:20 +01:00
commit d6b2bec113
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
5 changed files with 481 additions and 194 deletions

View file

@ -1482,6 +1482,7 @@
"cardBrowserDeleted": "{count, plural, =1{1 Karteikarte gelöscht} other{{count} Karteikarten gelöscht}}",
"cardBrowserMoveTitle": "{count, plural, =1{1 Karteikarte verschieben nach} other{{count} Karteikarten verschieben nach}}",
"cardBrowserMoved": "{count, plural, =1{1 Karteikarte nach „{title}“ verschoben} other{{count} Karteikarten nach „{title}“ verschoben}}",
"cardBrowserMoveFailed": "Die Karteikarten ließen sich nicht verschieben und sind wieder, wo sie waren.",
"cardBrowserAddTagsTitle": "{count, plural, =1{Tags zu 1 Karteikarte hinzufügen} other{Tags zu {count} Karteikarten hinzufügen}}",
"cardBrowserAddTo": "{count, plural, =1{Zu 1 Karteikarte hinzufügen} other{Zu {count} Karteikarten hinzufügen}}",
"cardBrowserRemoveTagsTitle": "{count, plural, =1{Tags von 1 Karteikarte entfernen} other{Tags von {count} Karteikarten entfernen}}",

View file

@ -1759,6 +1759,8 @@
"@cardBrowserMoveTitle": {"placeholders": {"count": {"type": "int"}}},
"cardBrowserMoved": "{count, plural, =1{Moved 1 flashcard to “{title}”} other{Moved {count} flashcards to “{title}”}}",
"@cardBrowserMoved": {"placeholders": {"count": {"type": "int"}, "title": {"type": "String"}}},
"cardBrowserMoveFailed": "The flashcards couldn't be moved, so they are where they were.",
"@cardBrowserMoveFailed": {"description": "A snack bar when moving flashcards, shown moved at once, failed and they show where they were again."},
"cardBrowserAddTagsTitle": "{count, plural, =1{Add tags to 1 flashcard} other{Add tags to {count} flashcards}}",
"@cardBrowserAddTagsTitle": {"placeholders": {"count": {"type": "int"}}},
"cardBrowserAddTo": "{count, plural, =1{Add to 1 flashcard} other{Add to {count} flashcards}}",

View file

@ -8763,6 +8763,12 @@ abstract class AppLocalizations {
/// **'{count, plural, =1{Moved 1 flashcard to “{title}”} other{Moved {count} flashcards to “{title}”}}'**
String cardBrowserMoved(int count, String title);
/// A snack bar when moving flashcards, shown moved at once, failed and they show where they were again.
///
/// In en, this message translates to:
/// **'The flashcards couldn\'t be moved, so they are where they were.'**
String get cardBrowserMoveFailed;
/// No description provided for @cardBrowserAddTagsTitle.
///
/// In en, this message translates to:

View file

@ -5502,6 +5502,10 @@ class AppLocalizationsDe extends AppLocalizations {
return '$_temp0';
}
@override
String get cardBrowserMoveFailed =>
'Die Karteikarten ließen sich nicht verschieben und sind wieder, wo sie waren.';
@override
String cardBrowserAddTagsTitle(int count) {
String _temp0 = intl.Intl.pluralLogic(

View file

@ -5453,6 +5453,10 @@ class AppLocalizationsEn extends AppLocalizations {
return '$_temp0';
}
@override
String get cardBrowserMoveFailed =>
'The flashcards couldn\'t be moved, so they are where they were.';
@override
String cardBrowserAddTagsTitle(int count) {
String _temp0 = intl.Intl.pluralLogic(