diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt b/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt index 6734df7ba184..441e563588fe 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt @@ -90,11 +90,8 @@ import com.ichi2.async.CollectionTask.* import com.ichi2.async.Connection.CancellableTaskListener import com.ichi2.async.Connection.ConflictResolution import com.ichi2.compat.CompatHelper.Companion.sdkVersion -import com.ichi2.libanki.ChangeManager +import com.ichi2.libanki.* import com.ichi2.libanki.Collection.CheckDatabaseResult -import com.ichi2.libanki.Consts -import com.ichi2.libanki.Decks -import com.ichi2.libanki.Utils import com.ichi2.libanki.importer.AnkiPackageImporter import com.ichi2.libanki.sched.AbstractDeckTreeNode import com.ichi2.libanki.sched.TreeNode @@ -106,6 +103,7 @@ import com.ichi2.ui.BadgeDrawableBuilder import com.ichi2.utils.* import com.ichi2.utils.Permissions.hasStorageAccessPermission import com.ichi2.widget.WidgetStatus +import kotlinx.coroutines.Job import net.ankiweb.rsdroid.BackendFactory import net.ankiweb.rsdroid.RustCleanup import timber.log.Timber @@ -2241,15 +2239,32 @@ open class DeckPicker : createDeckDialog.showDialog() } - fun confirmDeckDeletion(did: Long) { + fun confirmDeckDeletion(did: Long): Job? { + if (!BackendFactory.defaultLegacySchema) { + dismissAllDialogFragments() + // No confirmation required, as undoable + return launchCatchingCollectionTask { col -> + val changes = runInBackgroundWithProgress { + undoableOp { + col.newDecks.removeDecks(listOf(did)) + } + } + showSimpleSnackbar( + this@DeckPicker, + col.tr.browsingCardsDeleted(changes.count), + false + ) + } + } + val res = resources if (!colIsOpen()) { - return + return null } if (did == 1L) { showSimpleSnackbar(this, R.string.delete_deck_default_deck, true) dismissAllDialogFragments() - return + return null } // Get the number of cards contained in this deck and its subdecks val cnt = DeckService.countCardsInDeckTree(col, did) @@ -2258,7 +2273,7 @@ open class DeckPicker : if (cnt == 0 && !isDyn) { deleteDeck(did) dismissAllDialogFragments() - return + return null } // Otherwise we show a warning and require confirmation val msg: String @@ -2269,6 +2284,7 @@ open class DeckPicker : res.getQuantityString(R.plurals.delete_deck_message, cnt, deckName, cnt) } showDialogFragment(DeckPickerConfirmDeleteDeckDialog.newInstance(msg, did)) + return null } /** diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/DeckPickerTest.java b/AnkiDroid/src/test/java/com/ichi2/anki/DeckPickerTest.java index 6238620813a0..1859f85a418e 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/DeckPickerTest.java +++ b/AnkiDroid/src/test/java/com/ichi2/anki/DeckPickerTest.java @@ -24,6 +24,8 @@ import com.ichi2.testutils.DbUtils; import com.ichi2.utils.ResourceLoader; +import net.ankiweb.rsdroid.BackendFactory; + import org.apache.commons.exec.OS; import org.junit.Before; import org.junit.Test; @@ -237,7 +239,7 @@ public void confirmDeckDeletionDeletesEmptyDeck() { DeckPicker deckPicker = startActivityNormallyOpenCollectionWithIntent(DeckPicker.class, new Intent()); - deckPicker.confirmDeckDeletion(did); + awaitJob(deckPicker.confirmDeckDeletion(did)); advanceRobolectricLooperWithSleep(); @@ -246,6 +248,10 @@ public void confirmDeckDeletionDeletesEmptyDeck() { @Test public void deletion_of_filtered_deck_shows_warning_issue_10238() { + if (!BackendFactory.getDefaultLegacySchema()) { + // undoable + return; + } // Filtered decks contain their own options, deleting one can cause a significant loss of work. // And they are more likely to be empty temporarily long did = addDynamicDeck("filtered"); diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/CreateDeckDialogTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/CreateDeckDialogTest.kt index aa2c6993d3df..839f52da905c 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/CreateDeckDialogTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/dialogs/CreateDeckDialogTest.kt @@ -164,7 +164,7 @@ class CreateDeckDialogTest : RobolectricTest() { // After the last deck was created, delete a deck if (decks.count() >= 10) { - deckPicker.confirmDeckDeletion(did) + awaitJob(deckPicker.confirmDeckDeletion(did)) assertEquals(deckCounter.decrementAndGet(), decks.count()) assertEquals(deckCounter.get(), decks.count()) @@ -188,7 +188,8 @@ class CreateDeckDialogTest : RobolectricTest() { deckPicker.updateDeckList() assertTrue(deckPicker.searchDecksIcon!!.isVisible) - deckPicker.confirmDeckDeletion(decks.id("Deck0::Deck1")) + awaitJob(deckPicker.confirmDeckDeletion(decks.id("Deck0::Deck1"))) + assertEquals(2, decks.count()) deckPicker.updateDeckList() assertFalse(deckPicker.searchDecksIcon!!.isVisible) @@ -201,7 +202,8 @@ class CreateDeckDialogTest : RobolectricTest() { deckPicker.updateDeckList() assertTrue(deckPicker.searchDecksIcon!!.isVisible) - deckPicker.confirmDeckDeletion(decks.id("Deck0::Deck1")) + awaitJob(deckPicker.confirmDeckDeletion(decks.id("Deck0::Deck1"))) + assertEquals(2, decks.count()) deckPicker.updateDeckList() assertFalse(deckPicker.searchDecksIcon!!.isVisible)