Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateEditor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import com.ichi2.anki.dialogs.DeckSelectionDialog
import com.ichi2.anki.dialogs.DeckSelectionDialog.DeckSelectionListener
import com.ichi2.anki.dialogs.DiscardChangesDialog
import com.ichi2.anki.dialogs.InsertFieldDialog
import com.ichi2.anki.libanki.CardOrdinal
import com.ichi2.anki.libanki.CardTemplates
import com.ichi2.anki.libanki.Collection
import com.ichi2.anki.libanki.Note
Expand Down Expand Up @@ -148,11 +149,11 @@ open class CardTemplateEditor :
* The inner HashMap's key is the editor window ID (e.g., R.id.front_edit).
* The value is the cursor position within that editor window.
*/
private var tabToCursorPositions: HashMap<Int, HashMap<Int, Int>> = HashMap()
private var tabToCursorPositions: HashMap<CardOrdinal, HashMap<Int, Int>> = HashMap()

// the current editor view among front/style/back
private var tabToViewId: HashMap<Int, Int?> = HashMap()
private var startingOrdId = 0
private var startingOrdId: CardOrdinal = 0

/**
* If true, the view is split in two. The template editor appears on the leading side and the previewer on the trailing side.
Expand Down Expand Up @@ -193,7 +194,7 @@ open class CardTemplateEditor :
// get id for currently edited note (optional)
noteId = intent.getLongExtra(EDITOR_NOTE_ID, -1L)
// get id for currently edited template (optional)
startingOrdId = intent.getIntExtra("ordId", -1)
startingOrdId = intent.getIntExtra(EDITOR_START_ORD_ID, -1)
tabToCursorPositions[0] = hashMapOf()
tabToViewId[0] = R.id.front_edit
} else {
Expand Down Expand Up @@ -1531,5 +1532,25 @@ open class CardTemplateEditor :

@Suppress("unused")
private const val REQUEST_CARD_BROWSER_APPEARANCE = 1

@CheckResult
fun getIntent(
context: Context,
noteTypeId: NoteTypeId,
noteId: NoteId? = null,
ord: CardOrdinal? = null,
) = Intent(context, CardTemplateEditor::class.java)
.apply {
putExtra(EDITOR_NOTE_TYPE_ID, noteTypeId)
noteId?.let { putExtra(EDITOR_NOTE_ID, it) }
ord?.let { putExtra(EDITOR_START_ORD_ID, it) }

Timber.d(
"Built intent for CardTemplateEditor; ntid: %s; nid: %s; ord: %s",
noteTypeId,
noteId,
ord,
)
}
}
}
3 changes: 2 additions & 1 deletion AnkiDroid/src/main/java/com/ichi2/anki/NoteEditorActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import com.ichi2.anki.NoteEditorActivity.Companion.FRAGMENT_NAME_EXTRA
import com.ichi2.anki.android.input.ShortcutGroup
import com.ichi2.anki.android.input.ShortcutGroupProvider
import com.ichi2.anki.databinding.ActivityNoteEditorBinding
import com.ichi2.anki.libanki.CardOrdinal
import com.ichi2.anki.libanki.Collection
import com.ichi2.anki.noteeditor.NoteEditorFragmentDelegate
import com.ichi2.anki.noteeditor.NoteEditorLauncher
Expand Down Expand Up @@ -245,7 +246,7 @@ class NoteEditorActivity :
private fun createPreviewerFragment(
fields: List<String>,
tags: List<String>,
ord: Int,
ord: CardOrdinal,
): TemplatePreviewerFragment {
val args =
TemplatePreviewerArguments(
Expand Down
26 changes: 10 additions & 16 deletions AnkiDroid/src/main/java/com/ichi2/anki/NoteEditorFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ import com.ichi2.anki.dialogs.tags.TagsDialog
import com.ichi2.anki.dialogs.tags.TagsDialogFactory
import com.ichi2.anki.dialogs.tags.TagsDialogListener
import com.ichi2.anki.libanki.Card
import com.ichi2.anki.libanki.CardOrdinal
import com.ichi2.anki.libanki.Collection
import com.ichi2.anki.libanki.Consts
import com.ichi2.anki.libanki.DeckId
Expand All @@ -111,7 +112,6 @@ import com.ichi2.anki.libanki.Note.ClozeUtils
import com.ichi2.anki.libanki.NoteTypeId
import com.ichi2.anki.libanki.NotetypeJson
import com.ichi2.anki.libanki.Notetypes
import com.ichi2.anki.libanki.Notetypes.Companion.NOT_FOUND_NOTE_TYPE
import com.ichi2.anki.libanki.Utils
import com.ichi2.anki.libanki.clozeNumbersInNote
import com.ichi2.anki.model.CardStateFilter
Expand Down Expand Up @@ -1682,7 +1682,7 @@ class NoteEditorFragment :
* @param fields The processed note fields
* @return The ordinal (position) of the card template to display
*/
suspend fun determineCardOrdinal(fields: MutableList<String>): Int {
suspend fun determineCardOrdinal(fields: MutableList<String>): CardOrdinal {
val ord =
if (editorNote!!.notetype.isCloze) {
val tempNote = withCol { Note.fromNotetypeId(this@withCol, editorNote!!.notetype.id) }
Expand Down Expand Up @@ -1800,20 +1800,14 @@ class NoteEditorFragment :
}

private fun showCardTemplateEditor() {
val intent = Intent(requireContext(), CardTemplateEditor::class.java)
// Pass the note type ID
intent.putExtra("noteTypeId", currentlySelectedNotetype!!.id)
Timber.d(
"showCardTemplateEditor() for model %s",
intent.getLongExtra("noteTypeId", NOT_FOUND_NOTE_TYPE),
)
// Also pass the note id and ord if not adding new note
if (!addNote && currentEditedCard != null) {
intent.putExtra("noteId", currentEditedCard!!.nid)
Timber.d("showCardTemplateEditor() with note %s", currentEditedCard!!.nid)
intent.putExtra("ordId", currentEditedCard!!.ord)
Timber.d("showCardTemplateEditor() with ord %s", currentEditedCard!!.ord)
}
val intent =
CardTemplateEditor.getIntent(
requireContext(),
noteTypeId = currentlySelectedNotetype!!.id,
// Also pass the note id and ord if not adding new note
noteId = if (addNote) null else currentEditedCard?.nid,
ord = if (addNote) null else currentEditedCard?.ord,
)
requestTemplateEditLauncher.launch(intent)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import android.content.Context
import androidx.annotation.CheckResult
import anki.config.ConfigKey
import com.ichi2.anki.libanki.Card
import com.ichi2.anki.libanki.CardOrdinal
import com.ichi2.anki.libanki.Collection
import com.ichi2.anki.libanki.TemplateManager.TemplateRenderContext.TemplateRenderOutput
import com.ichi2.anki.libanki.template.MathJax
Expand Down Expand Up @@ -67,7 +68,7 @@ class AndroidCardRenderContext(

private fun render(
content: String,
ord: Int,
ord: CardOrdinal,
): RenderedCard {
val requiresMathjax = MathJax.textContainsMathjax(content)

Expand Down
3 changes: 2 additions & 1 deletion AnkiDroid/src/main/java/com/ichi2/anki/cardviewer/TTS.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.ichi2.anki.R
import com.ichi2.anki.ReadText
import com.ichi2.anki.backend.stripHTML
import com.ichi2.anki.libanki.Card
import com.ichi2.anki.libanki.CardOrdinal
import com.ichi2.anki.libanki.Collection
import com.ichi2.anki.libanki.TTSTag
import com.ichi2.anki.libanki.template.TemplateFilters
Expand All @@ -47,7 +48,7 @@ class TTS {
private fun getOrdUsingCardType(
card: Card,
col: Collection,
): Int =
): CardOrdinal =
if (card.noteType(col).isCloze) {
0
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,7 @@ data class ManageNoteTypesState(
data class CardEditor(
val ntid: NoteTypeId,
) : Destination {
override fun toIntent(context: Context): Intent =
Intent(context, CardTemplateEditor::class.java).apply {
putExtra(CardTemplateEditor.EDITOR_NOTE_TYPE_ID, ntid)
}
override fun toIntent(context: Context) = CardTemplateEditor.getIntent(context, noteTypeId = ntid)
}

data class FieldsEditor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.google.android.material.card.MaterialCardView
import com.google.android.material.shape.ShapeAppearanceModel
import com.ichi2.anki.AnkiDroidApp
import com.ichi2.anki.LanguageUtils
import com.ichi2.anki.libanki.CardOrdinal
import com.ichi2.anki.settings.Prefs
import com.ichi2.anki.settings.enums.FrameStyle
import com.ichi2.themes.Themes
Expand Down Expand Up @@ -93,7 +94,7 @@ fun stdHtml(
* @return body classes used when showing a card
*/
fun bodyClassForCardOrd(
cardOrd: Int,
cardOrd: CardOrdinal,
nightMode: Boolean = Themes.isNightTheme,
): String = "card card${cardOrd + 1} ${bodyClass(nightMode)} mathjax-rendered"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.google.android.material.tabs.TabLayout
import com.ichi2.anki.R
import com.ichi2.anki.databinding.FragmentTemplatePreviewerBinding
import com.ichi2.anki.launchCatchingTask
import com.ichi2.anki.libanki.CardOrdinal
import com.ichi2.anki.snackbar.BaseSnackbarBuilderProvider
import com.ichi2.anki.snackbar.SnackbarBuilder
import com.ichi2.anki.utils.ext.doOnTabSelected
Expand Down Expand Up @@ -145,7 +146,7 @@ class TemplatePreviewerFragment :
*
* @return The safe cloze ordinal number
*/
suspend fun getSafeClozeOrd(): Int = viewModel.getSafeClozeOrd()
suspend fun getSafeClozeOrd(): CardOrdinal = viewModel.getSafeClozeOrd()

companion object {
const val ARGS_KEY = "templatePreviewerArgs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.ichi2.anki.NotetypeFile
import com.ichi2.anki.asyncIO
import com.ichi2.anki.launchCatchingIO
import com.ichi2.anki.libanki.Card
import com.ichi2.anki.libanki.CardOrdinal
import com.ichi2.anki.libanki.Consts.DEFAULT_DECK_ID
import com.ichi2.anki.libanki.DeckId
import com.ichi2.anki.libanki.Note
Expand All @@ -49,16 +50,16 @@ class TemplatePreviewerViewModel(
private val isCloze: Boolean

/**
* identifies which of the card templates or cloze deletions it corresponds to
* * for card templates, values are from 0 to the number of templates minus 1
* * for cloze deletions, values are from 0 to max cloze index minus 1
* Identifies which of the card templates or cloze deletions it corresponds to
*
* @see CardOrdinal
*/
@VisibleForTesting
val ordFlow: MutableStateFlow<Int>
val ordFlow: MutableStateFlow<CardOrdinal>

private val note: Deferred<Note>
private val templateNames: Deferred<List<String>>
private val clozeOrds: Deferred<List<Int>>?
private val clozeOrds: Deferred<List<CardOrdinal>>?
override var currentCard: Deferred<Card>
override val server = AnkiServer(this).also { it.start() }

Expand Down Expand Up @@ -207,7 +208,7 @@ class TemplatePreviewerViewModel(
ordFlow.value
}

suspend fun getSafeClozeOrd(): Int = ordFlow.value.coerceIn(0, clozeOrds!!.await().size - 1)
suspend fun getSafeClozeOrd(): CardOrdinal = ordFlow.value.coerceIn(0, clozeOrds!!.await().size - 1)

fun updateContent(
fields: List<String>,
Expand Down Expand Up @@ -271,11 +272,7 @@ class TemplatePreviewerViewModel(

/**
* @param id id of the note. Use 0 for non-created notes.
*
* @param ord identifies which of the card templates or cloze deletions it corresponds to
* * for card templates, values are from 0 to the number of templates minus 1
* * for cloze deletions, values are from 0 to max cloze index minus 1
*
* @param ord See [CardOrdinal]
* @param fillEmpty if blank fields should be replaced with placeholder content
*/
@Parcelize
Expand All @@ -284,7 +281,7 @@ data class TemplatePreviewerArguments(
val fields: List<String>,
val tags: List<String>,
val id: NoteId = 0,
val ord: Int = 0,
val ord: CardOrdinal = 0,
val fillEmpty: Boolean = false,
val deckId: DeckId = DEFAULT_DECK_ID,
) : Parcelable {
Expand Down
19 changes: 18 additions & 1 deletion libanki/src/main/java/com/ichi2/anki/libanki/Card.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ import net.ankiweb.rsdroid.RustCleanup
private typealias BackendCard = anki.cards.Card
private typealias FSRSMemoryState = anki.cards.FsrsMemoryState

/**
* Identifies the card template or cloze deletion which the card refers to.
*
* Values:
* - **card templates**: from 0 to [`templates.size - 1`][NotetypeJson.templates]
* - **cloze deletions**: `{{c1::}}` refers to ord 0. etc...
*
* Primarily used during rendering to determine the template to select, or cloze to hide.
*
* Defined as [Card.ord]
*/
typealias CardOrdinal = Int

/**
* A Card is the ultimate entity subject to review; it encapsulates the scheduling parameters (from which to derive
* the next interval), the note it is derived from (from which field data is retrieved), its own ownership (which deck it
Expand Down Expand Up @@ -68,7 +81,11 @@ open class Card : Cloneable {
var id: CardId = 0
var nid: NoteId = 0
var did: DeckId = 0
var ord = 0

/**
* @see CardOrdinal
*/
var ord: CardOrdinal = 0
var mod: Long = 0
private var usn = 0

Expand Down
10 changes: 7 additions & 3 deletions libanki/src/main/java/com/ichi2/anki/libanki/CardTemplate.kt
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,12 @@ data class CardTemplate(
*/
var name by jsonString("name")

/** The 0-based ordinal of the template */
val ord by jsonInt("ord")
/**
* The 0-based ordinal of the template
*
* @see CardOrdinal
*/
val ord: CardOrdinal by jsonInt("ord")

/**
* Format string for the question when reviewing
Expand Down Expand Up @@ -107,7 +111,7 @@ data class CardTemplate(

/** @see ord */
@RustCleanup("Check JSONObject.NULL")
fun setOrd(value: Int?) = jsonObject.put("ord", value ?: JSONObject.NULL)
fun setOrd(value: CardOrdinal?) = jsonObject.put("ord", value ?: JSONObject.NULL)

fun deepClone() = CardTemplate(jsonObject.deepClone())

Expand Down