Skip to content

Commit 5bfc04c

Browse files
refactor(libanki): extract & document 'CardTemplate[s]'
similar to 095a492 A couple of 'optStr' calls remain using the underlying object did is not handled Co-authored-by: Arthur Milchior <arthur@milchior.fr>
1 parent b440d2a commit 5bfc04c

28 files changed

+550
-328
lines changed

.idea/dictionaries/anki.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
<w>apkg</w>
1111
<w>apkgaa</w>
1212
<w>bafmt</w>
13+
<w>bfont</w>
1314
<w>bqfmt</w>
15+
<w>bsize</w>
1416
<w>cid</w>
1517
<w>cids</w>
1618
<w>cloze</w>

AnkiDroid/src/androidTest/java/com/ichi2/anki/tests/ContentProviderTest.kt

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import com.ichi2.libanki.getStockNotetypeLegacy
4747
import com.ichi2.libanki.sched.Scheduler
4848
import com.ichi2.libanki.utils.set
4949
import com.ichi2.testutils.common.assertThrows
50+
import com.ichi2.utils.KotlinCleanup
5051
import com.ichi2.utils.emptyStringArray
5152
import net.ankiweb.rsdroid.exceptions.BackendNotFoundException
5253
import org.hamcrest.MatcherAssert.assertThat
@@ -242,9 +243,9 @@ class ContentProviderTest : InstrumentedTest() {
242243
TEST_NOTE_FIELDS.toMutableList(),
243244
)
244245
assertEquals("Check that tag was set correctly", TEST_TAG, addedNote.tags[0])
245-
val noteType: JSONObject? = col.notetypes.get(noteTypeId)
246+
val noteType: NotetypeJson? = col.notetypes.get(noteTypeId)
246247
assertNotNull("Check note type", noteType)
247-
val expectedNumCards = noteType!!.getJSONArray("tmpls").length()
248+
val expectedNumCards = noteType!!.tmpls.length()
248249
assertEquals("Check that correct number of cards generated", expectedNumCards, addedNote.numberOfCards(col))
249250
// Now delete the note
250251
cr.delete(newNoteUri, null, null)
@@ -287,7 +288,7 @@ class ContentProviderTest : InstrumentedTest() {
287288
val noteTypeUri = ContentUris.withAppendedId(FlashCardsContract.Model.CONTENT_URI, noteTypeId)
288289
val testIndex =
289290
TEST_NOTE_TYPE_CARDS.size - 1 // choose the last one because not the same as the basic note type template
290-
val expectedOrd = noteType.getJSONArray("tmpls").length()
291+
val expectedOrd = noteType.tmpls.length()
291292
val cv =
292293
ContentValues().apply {
293294
put(FlashCardsContract.CardTemplate.NAME, TEST_NOTE_TYPE_CARDS[testIndex])
@@ -309,21 +310,21 @@ class ContentProviderTest : InstrumentedTest() {
309310
)
310311
noteType = col.notetypes.get(noteTypeId)
311312
assertNotNull("Check note type", noteType)
312-
val template = noteType!!.getJSONArray("tmpls").getJSONObject(expectedOrd)
313+
val template = noteType!!.tmpls[expectedOrd]
313314
assertEquals(
314315
"Check template JSONObject ord",
315316
expectedOrd,
316-
template.getInt("ord"),
317+
template.ord,
317318
)
318319
assertEquals(
319320
"Check template name",
320321
TEST_NOTE_TYPE_CARDS[testIndex],
321-
template.getString("name"),
322+
template.name,
322323
)
323-
assertEquals("Check qfmt", TEST_NOTE_TYPE_QFMT[testIndex], template.getString("qfmt"))
324-
assertEquals("Check afmt", TEST_NOTE_TYPE_AFMT[testIndex], template.getString("afmt"))
325-
assertEquals("Check bqfmt", TEST_NOTE_TYPE_QFMT[testIndex], template.getString("bqfmt"))
326-
assertEquals("Check bafmt", TEST_NOTE_TYPE_AFMT[testIndex], template.getString("bafmt"))
324+
assertEquals("Check qfmt", TEST_NOTE_TYPE_QFMT[testIndex], template.qfmt)
325+
assertEquals("Check afmt", TEST_NOTE_TYPE_AFMT[testIndex], template.afmt)
326+
assertEquals("Check bqfmt", TEST_NOTE_TYPE_QFMT[testIndex], template.bqfmt)
327+
assertEquals("Check bafmt", TEST_NOTE_TYPE_AFMT[testIndex], template.bafmt)
327328
col.notetypes.rem(noteType)
328329
}
329330

@@ -577,7 +578,7 @@ class ContentProviderTest : InstrumentedTest() {
577578
assertEquals(
578579
"Check templates length",
579580
TEST_NOTE_TYPE_CARDS.size,
580-
noteType.getJSONArray("tmpls").length(),
581+
noteType.tmpls.length(),
581582
)
582583
assertEquals(
583584
"Check field length",
@@ -626,16 +627,16 @@ class ContentProviderTest : InstrumentedTest() {
626627
col = reopenCol()
627628
noteType = col.notetypes.get(mid)
628629
assertNotNull("Check note type", noteType)
629-
val template = noteType!!.getJSONArray("tmpls").getJSONObject(i)
630+
val template = noteType!!.tmpls[i]
630631
assertEquals(
631632
"Check template name",
632633
TEST_NOTE_TYPE_CARDS[i],
633-
template.getString("name"),
634+
template.name,
634635
)
635-
assertEquals("Check qfmt", TEST_NOTE_TYPE_QFMT[i], template.getString("qfmt"))
636-
assertEquals("Check afmt", TEST_NOTE_TYPE_AFMT[i], template.getString("afmt"))
637-
assertEquals("Check bqfmt", TEST_NOTE_TYPE_QFMT[i], template.getString("bqfmt"))
638-
assertEquals("Check bafmt", TEST_NOTE_TYPE_AFMT[i], template.getString("bafmt"))
636+
assertEquals("Check qfmt", TEST_NOTE_TYPE_QFMT[i], template.qfmt)
637+
assertEquals("Check afmt", TEST_NOTE_TYPE_AFMT[i], template.afmt)
638+
assertEquals("Check bqfmt", TEST_NOTE_TYPE_QFMT[i], template.bqfmt)
639+
assertEquals("Check bafmt", TEST_NOTE_TYPE_AFMT[i], template.bafmt)
639640
}
640641
} finally {
641642
// Delete the note type (this will force a full-sync)
@@ -1404,19 +1405,22 @@ class ContentProviderTest : InstrumentedTest() {
14041405
}
14051406
}
14061407

1408+
@KotlinCleanup("duplicate of TestClass method")
14071409
fun addNonClozeNoteType(
14081410
name: String,
14091411
fields: Array<String>,
1410-
qfmt: String?,
1411-
afmt: String?,
1412+
qfmt: String,
1413+
afmt: String,
14121414
): String {
14131415
val noteType = col.notetypes.new(name)
14141416
for (field in fields) {
14151417
col.notetypes.addFieldInNewModel(noteType, col.notetypes.newField(field))
14161418
}
1417-
val t = Notetypes.newTemplate("Card 1")
1418-
t.put("qfmt", qfmt)
1419-
t.put("afmt", afmt)
1419+
val t =
1420+
Notetypes.newTemplate("Card 1").also { t ->
1421+
t.qfmt = qfmt
1422+
t.afmt = afmt
1423+
}
14201424
col.notetypes.addTemplateInNewModel(noteType, t)
14211425
col.notetypes.add(noteType)
14221426
return name

AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2282,7 +2282,16 @@ open class CardBrowser :
22822282
CardBrowserColumn.SFLD -> card.note(col).sFld(col)
22832283
CardBrowserColumn.DECK -> col.decks.name(card.did)
22842284
CardBrowserColumn.TAGS -> card.note(col).stringTags(col)
2285-
CardBrowserColumn.CARD -> if (inCardMode) card.template(col).optString("name") else "${card.note(col).numberOfCards(col)}"
2285+
CardBrowserColumn.CARD ->
2286+
if (inCardMode) {
2287+
card
2288+
.template(
2289+
col,
2290+
).jsonObject
2291+
.optString("name")
2292+
} else {
2293+
"${card.note(col).numberOfCards(col)}"
2294+
}
22862295
CardBrowserColumn.DUE -> dueString(col, card)
22872296
CardBrowserColumn.EASE -> if (inCardMode) getEaseForCards() else getAvgEaseForNotes()
22882297
CardBrowserColumn.CHANGED -> LanguageUtil.getShortDateFormatFromS(if (inCardMode) card.mod else card.note(col).mod.toLong())

AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateBrowserAppearanceEditor.kt

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ import androidx.annotation.CheckResult
2626
import androidx.appcompat.app.AlertDialog
2727
import androidx.core.widget.doAfterTextChanged
2828
import com.ichi2.anki.dialogs.DiscardChangesDialog
29+
import com.ichi2.libanki.CardTemplate
2930
import com.ichi2.utils.message
3031
import com.ichi2.utils.negativeButton
3132
import com.ichi2.utils.positiveButton
3233
import com.ichi2.utils.show
3334
import org.jetbrains.annotations.Contract
34-
import org.json.JSONObject
3535
import timber.log.Timber
3636

3737
/** Allows specification of the Question and Answer format of a card template in the Card Browser
@@ -187,9 +187,9 @@ class CardTemplateBrowserAppearanceEditor : AnkiActivity() {
187187
val question: String = question ?: VALUE_USE_DEFAULT
188188
val answer: String = answer ?: VALUE_USE_DEFAULT
189189

190-
fun applyTo(template: JSONObject) {
191-
template.put("bqfmt", question)
192-
template.put("bafmt", answer)
190+
fun applyTo(template: CardTemplate) {
191+
template.bqfmt = question
192+
template.bafmt = answer
193193
}
194194

195195
companion object {
@@ -220,12 +220,8 @@ class CardTemplateBrowserAppearanceEditor : AnkiActivity() {
220220
@CheckResult
221221
fun getIntentFromTemplate(
222222
context: Context,
223-
template: JSONObject,
224-
): Intent {
225-
val browserQuestionTemplate = template.getString("bqfmt")
226-
val browserAnswerTemplate = template.getString("bafmt")
227-
return getIntent(context, browserQuestionTemplate, browserAnswerTemplate)
228-
}
223+
template: CardTemplate,
224+
): Intent = getIntent(context, template.bqfmt, template.bafmt)
229225

230226
@CheckResult
231227
fun getIntent(

0 commit comments

Comments
 (0)