diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt b/AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt index 5223ca3b0db5..9fe2a3ab77ef 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.kt b/AnkiDroid/src/test/java/com/ichi2/anki/DeckPickerTest.kt index 4c8de11c91c1..9e8af07fdf1b 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/DeckPickerTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/DeckPickerTest.kt @@ -17,6 +17,7 @@ import com.ichi2.testutils.BackupManagerTestUtilities import com.ichi2.testutils.DbUtils import com.ichi2.utils.KotlinCleanup import com.ichi2.utils.ResourceLoader +import net.ankiweb.rsdroid.BackendFactory import org.apache.commons.exec.OS import org.hamcrest.MatcherAssert.* import org.hamcrest.Matchers.* @@ -207,13 +208,17 @@ class DeckPickerTest : RobolectricTest() { val deckPicker = startActivityNormallyOpenCollectionWithIntent( DeckPicker::class.java, Intent() ) - deckPicker.confirmDeckDeletion(did) + awaitJob(deckPicker.confirmDeckDeletion(did)) advanceRobolectricLooperWithSleep() assertThat("deck was deleted", col.decks.count(), `is`(1)) } @Test fun deletion_of_filtered_deck_shows_warning_issue_10238() { + if (!BackendFactory.defaultLegacySchema) { + // 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 val 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)