Skip to content

Commit

Permalink
Add restore to default feature
Browse files Browse the repository at this point in the history
  • Loading branch information
RobozinhoD authored and david-allison committed Dec 17, 2024
1 parent 3751f14 commit fab4ed0
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 1 deletion.
66 changes: 66 additions & 0 deletions AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateEditor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package com.ichi2.anki

import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.os.Bundle
import android.os.Handler
Expand Down Expand Up @@ -50,10 +51,14 @@ import androidx.fragment.app.commitNow
import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import anki.notetypes.StockNotetype
import anki.notetypes.StockNotetype.OriginalStockKind.ORIGINAL_STOCK_KIND_UNKNOWN_VALUE
import anki.notetypes.notetypeId
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import com.ichi2.anki.CollectionManager.TR
import com.ichi2.anki.CollectionManager.withCol
import com.ichi2.anki.android.input.ShortcutGroup
import com.ichi2.anki.android.input.shortcut
Expand Down Expand Up @@ -84,12 +89,18 @@ import com.ichi2.libanki.NotetypeJson
import com.ichi2.libanki.Notetypes
import com.ichi2.libanki.Notetypes.Companion.NOT_FOUND_NOTE_TYPE
import com.ichi2.libanki.exception.ConfirmModSchemaException
import com.ichi2.libanki.getStockNotetype
import com.ichi2.libanki.getStockNotetypeKinds
import com.ichi2.libanki.restoreNotetypeToStock
import com.ichi2.libanki.undoableOp
import com.ichi2.themes.Themes
import com.ichi2.ui.FixedEditText
import com.ichi2.ui.FixedTextView
import com.ichi2.utils.KotlinCleanup
import com.ichi2.utils.copyToClipboard
import com.ichi2.utils.jsonObjectIterable
import com.ichi2.utils.listItems
import com.ichi2.utils.show
import net.ankiweb.rsdroid.Translations
import org.json.JSONArray
import org.json.JSONException
Expand Down Expand Up @@ -840,6 +851,7 @@ open class CardTemplateEditor :
* Setups the part of the menu that can be used either in template editor or in previewer fragment.
*/
fun setupCommonMenu(menu: Menu) {
menu.findItem(R.id.action_restore_to_default).title = CollectionManager.TR.cardTemplatesRestoreToDefault()
if (noteTypeCreatesDynamicNumberOfNotes()) {
Timber.d("Editing cloze/occlusion model, disabling add/delete card template and deck override functionality")
menu.findItem(R.id.action_add).isVisible = false
Expand Down Expand Up @@ -872,11 +884,24 @@ open class CardTemplateEditor :
menu.findItem(R.id.action_insert_field).isVisible = isInsertFieldItemVisible
}

@NeedsTest("Notetype is restored to stock kind")
private suspend fun restoreNotetypeToStock(kind: StockNotetype.Kind? = null) {
val nid = notetypeId { ntid = tempModel.modelId }
undoableOp { restoreNotetypeToStock(nid, kind) }
onModelSaved()
showThemedToast(
requireContext(),
TR.cardTemplatesRestoredToDefault(),
shortLength = false,
)
}

/**
* Handles the part of the menu set by [setupCommonMenu].
* @returns whether the given item was handled
* @see [onMenuItemSelected] and [onMenuItemClick]
*/
@NeedsTest("Restore to default option")
fun handleCommonMenuItemSelected(menuItem: MenuItem): Boolean {
return when (menuItem.itemId) {
R.id.action_add -> {
Expand Down Expand Up @@ -926,6 +951,47 @@ open class CardTemplateEditor :
Timber.i("CardTemplateEditor::Card Browser Template button pressed")
openBrowserAppearance()
}
R.id.action_restore_to_default -> {
Timber.i("CardTemplateEditor:: Restore to default button pressed")

fun askUser(kind: StockNotetype.Kind? = null) {
AlertDialog.Builder(requireContext()).show {
setTitle(TR.cardTemplatesRestoreToDefault())
setMessage(TR.cardTemplatesRestoreToDefaultConfirmation())
setPositiveButton(R.string.dialog_ok) { _, _ ->
launchCatchingTask {
restoreNotetypeToStock(kind)
}
}
setNegativeButton(R.string.dialog_cancel) { _, _ -> }
}
}

val originalStockKind = tempModel.notetype.optInt("originalStockKind", ORIGINAL_STOCK_KIND_UNKNOWN_VALUE)
if (originalStockKind != ORIGINAL_STOCK_KIND_UNKNOWN_VALUE) {
Timber.d("Asking to restore to original stock kind %s", originalStockKind)
askUser()
return true
}

launchCatchingTask {
Timber.d("Unknown stock kind: asking which kind to restore to")
val stockNotetypeKinds = getStockNotetypeKinds()
val stockNotetypesNames =
withCol {
stockNotetypeKinds.map { getStockNotetype(it).name }
}
AlertDialog.Builder(requireContext()).show {
setTitle(TR.cardTemplatesRestoreToDefault())
setNegativeButton(R.string.dialog_cancel) { _, _ -> }
listItems(stockNotetypesNames) { _: DialogInterface, index: Int ->
val kind = stockNotetypeKinds[index]
askUser(kind)
}
}
}
true
}
else -> {
return false
}
Expand Down
30 changes: 30 additions & 0 deletions AnkiDroid/src/main/java/com/ichi2/libanki/Notetypes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,22 @@

package com.ichi2.libanki

import androidx.annotation.CheckResult
import anki.collection.OpChanges
import anki.collection.OpChangesWithId
import anki.notetypes.Notetype
import anki.notetypes.NotetypeId
import anki.notetypes.NotetypeNameId
import anki.notetypes.NotetypeNameIdUseCount
import anki.notetypes.StockNotetype
import anki.notetypes.restoreNotetypeToStockRequest
import com.google.protobuf.ByteString
import com.ichi2.anki.CrashReportService
import com.ichi2.annotations.NeedsTest
import com.ichi2.libanki.Consts.MODEL_CLOZE
import com.ichi2.libanki.Utils.checksum
import com.ichi2.libanki.backend.BackendUtils
import com.ichi2.libanki.backend.BackendUtils.fromJsonBytes
import com.ichi2.libanki.backend.BackendUtils.toJsonBytes
import com.ichi2.libanki.exception.ConfirmModSchemaException
import com.ichi2.libanki.utils.LibAnkiAlias
Expand Down Expand Up @@ -774,3 +778,29 @@ fun Collection.getNotetypeNames(): List<NotetypeNameId> = backend.getNotetypeNam
fun Collection.addNotetypeLegacy(json: ByteString): OpChangesWithId = backend.addNotetypeLegacy(json = json)

fun Collection.getStockNotetypeLegacy(kind: StockNotetype.Kind): ByteString = backend.getStockNotetypeLegacy(kind = kind)

fun Collection.getStockNotetype(kind: StockNotetype.Kind): NotetypeJson = NotetypeJson(fromJsonBytes(getStockNotetypeLegacy(kind)))

/**
* Restores a notetype to its original stock kind.
*
* @param notetypeId id of the changed notetype
* @param forceKind optional stock kind to be forced instead of the original kind.
* Older notetypes did not store their original stock kind, so we allow the UI
* to pass in an override to use when missing, or for tests.
*/
@CheckResult
fun Collection.restoreNotetypeToStock(
notetypeId: NotetypeId,
forceKind: StockNotetype.Kind? = null,
): OpChanges {
val msg =
restoreNotetypeToStockRequest {
this.notetypeId = notetypeId
forceKind?.let { this.forceKind = forceKind }
}
return backend.restoreNotetypeToStock(msg)
}

@NotInLibAnki
fun getStockNotetypeKinds(): List<StockNotetype.Kind> = StockNotetype.Kind.entries.filter { it != StockNotetype.Kind.UNRECOGNIZED }
8 changes: 7 additions & 1 deletion AnkiDroid/src/main/res/menu/card_template_editor.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ankidroid="http://schemas.android.com/apk/res-auto" >
xmlns:ankidroid="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="@+id/action_confirm"
android:icon="@drawable/ic_done_white"
Expand Down Expand Up @@ -48,4 +49,9 @@
android:id="@+id/action_copy_as_markdown"
android:title="@string/copy_as_markdown"
ankidroid:showAsAction="never" />
<item
android:id="@+id/action_restore_to_default"
tools:title="Restore to default..."
ankidroid:showAsAction="never"
/>
</menu>

0 comments on commit fab4ed0

Please sign in to comment.