Skip to content

Commit 243fdec

Browse files
ericli3690david-allison
authored andcommitted
Adding Warning Badge for Cards with Empty Fronts in Previewer
Added code in TemplatePreviewerViewModel to compute whether cards have empty fronts, and added warning badges to previewer tabs in TemplatePreviewerPage accordingly
1 parent 1b73fe4 commit 243fdec

File tree

3 files changed

+68
-2
lines changed

3 files changed

+68
-2
lines changed

AnkiDroid/src/main/java/com/ichi2/anki/previewer/TemplatePreviewerPage.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,14 @@ class TemplatePreviewerPage : Fragment(R.layout.template_previewer_container) {
5555
val tabLayout = view.findViewById<TabLayout>(R.id.tab_layout)
5656

5757
lifecycleScope.launch {
58-
for (templateName in viewModel.getTemplateNames()) {
59-
tabLayout.addTab(tabLayout.newTab().setText(templateName))
58+
val cardsWithEmptyFronts = viewModel.cardsWithEmptyFronts?.await()
59+
for ((index, templateName) in viewModel.getTemplateNames().withIndex()) {
60+
val newTab = tabLayout.newTab().setText(templateName)
61+
if (cardsWithEmptyFronts?.get(index) == true) {
62+
val badge = newTab.getOrCreateBadge()
63+
badge.horizontalOffset = -4
64+
}
65+
tabLayout.addTab(newTab)
6066
}
6167
tabLayout.selectTab(tabLayout.getTabAt(viewModel.getCurrentTabIndex()))
6268
tabLayout.addOnTabSelectedListener(

AnkiDroid/src/main/java/com/ichi2/anki/previewer/TemplatePreviewerViewModel.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import kotlinx.coroutines.Deferred
3939
import kotlinx.coroutines.flow.MutableStateFlow
4040
import kotlinx.coroutines.flow.collectLatest
4141
import kotlinx.parcelize.Parcelize
42+
import org.intellij.lang.annotations.Language
4243
import org.jetbrains.annotations.VisibleForTesting
4344

4445
class TemplatePreviewerViewModel(
@@ -63,6 +64,11 @@ class TemplatePreviewerViewModel(
6364
override var currentCard: Deferred<Card>
6465
override val server = AnkiServer(this).also { it.start() }
6566

67+
/**
68+
* Ordered list of cards with empty fronts
69+
*/
70+
internal val cardsWithEmptyFronts: Deferred<List<Boolean>>?
71+
6672
init {
6773
note =
6874
asyncIO {
@@ -105,9 +111,28 @@ class TemplatePreviewerViewModel(
105111
val tr = CollectionManager.TR
106112
clozeNumbers.await().map { tr.cardTemplatesCard(it) }
107113
}
114+
cardsWithEmptyFronts = null
108115
} else {
109116
clozeOrds = null
110117
templateNames = CompletableDeferred(notetype.templatesNames)
118+
cardsWithEmptyFronts =
119+
asyncIO {
120+
val note = note.await()
121+
List(templateNames.await().size) { ord ->
122+
val questionText =
123+
withCol {
124+
note
125+
.ephemeralCard(
126+
col = this,
127+
ord = ord,
128+
customNoteType = notetype,
129+
fillEmpty = fillEmpty,
130+
deckId = arguments.deckId,
131+
).renderOutput(this)
132+
}.questionText
133+
EMPTY_FRONT_LINK in questionText
134+
}
135+
}
111136
}
112137
}
113138

@@ -205,6 +230,9 @@ class TemplatePreviewerViewModel(
205230
}
206231

207232
companion object {
233+
@Language("HTML")
234+
private const val EMPTY_FRONT_LINK = """<a href='https://docs.ankiweb.net/templates/errors.html#front-of-card-is-blank'>"""
235+
208236
fun factory(
209237
arguments: TemplatePreviewerArguments,
210238
cardMediaPlayer: CardMediaPlayer,

AnkiDroid/src/test/java/com/ichi2/anki/previewer/TemplatePreviewerViewModelTest.kt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,21 @@ class TemplatePreviewerViewModelTest : JvmTest() {
5757
}
5858
}
5959

60+
@Test
61+
fun `empty front field detected correctly for tab badge`() =
62+
runOptionalReversedTest(
63+
fields =
64+
mutableListOf(
65+
"we have two normal fields",
66+
"and purposefully leave the third blank",
67+
"",
68+
),
69+
) {
70+
onPageFinished(false)
71+
assertThat(this.cardsWithEmptyFronts!!.await()[0], equalTo(false))
72+
assertThat(this.cardsWithEmptyFronts!!.await()[1], equalTo(true))
73+
}
74+
6075
private fun runClozeTest(
6176
ord: Int = 0,
6277
fields: MutableList<String>? = null,
@@ -73,4 +88,21 @@ class TemplatePreviewerViewModelTest : JvmTest() {
7388
val viewModel = TemplatePreviewerViewModel(arguments, mock())
7489
block(viewModel)
7590
}
91+
92+
private fun runOptionalReversedTest(
93+
ord: Int = 0,
94+
fields: MutableList<String>? = null,
95+
block: suspend TemplatePreviewerViewModel.() -> Unit,
96+
) = runTest {
97+
val notetype = col.notetypes.byName("Basic (optional reversed card)")!!
98+
val arguments =
99+
TemplatePreviewerArguments(
100+
notetypeFile = NotetypeFile(tempDirectory.root, notetype),
101+
fields = fields ?: mutableListOf("question text", "answer text", "y"),
102+
tags = mutableListOf(),
103+
ord = ord,
104+
)
105+
val viewModel = TemplatePreviewerViewModel(arguments, mock())
106+
block(viewModel)
107+
}
76108
}

0 commit comments

Comments
 (0)