Skip to content

Commit

Permalink
Support deleting/undoing deck from deck picker
Browse files Browse the repository at this point in the history
+ Delete the cards inside the default deck if user tries to delete it

Closes ankidroid#11703
  • Loading branch information
dae committed Jul 21, 2022
1 parent e432986 commit 18eb265
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 12 deletions.
32 changes: 24 additions & 8 deletions AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -2269,6 +2284,7 @@ open class DeckPicker :
res.getQuantityString(R.plurals.delete_deck_message, cnt, deckName, cnt)
}
showDialogFragment(DeckPickerConfirmDeleteDeckDialog.newInstance(msg, did))
return null
}

/**
Expand Down
7 changes: 6 additions & 1 deletion AnkiDroid/src/test/java/com/ichi2/anki/DeckPickerTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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.*
Expand Down Expand Up @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -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)
Expand All @@ -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)
Expand Down

0 comments on commit 18eb265

Please sign in to comment.