Skip to content

Commit a1e88ee

Browse files
theMr17david-allison
authored andcommitted
feat(set-due-date): display interval
Only for review 'type' cards: other types don't have an interval Only when 1 card is selected Fixes 16406
1 parent 3a724fa commit a1e88ee

File tree

5 files changed

+75
-0
lines changed

5 files changed

+75
-0
lines changed

AnkiDroid/src/main/java/com/ichi2/anki/scheduling/SetDueDateDialog.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import com.google.android.material.snackbar.Snackbar
4141
import com.google.android.material.tabs.TabLayout
4242
import com.google.android.material.tabs.TabLayoutMediator
4343
import com.google.android.material.textfield.TextInputLayout
44+
import com.google.android.material.textview.MaterialTextView
4445
import com.ichi2.anki.AnkiActivity
4546
import com.ichi2.anki.CollectionManager
4647
import com.ichi2.anki.CollectionManager.TR
@@ -168,6 +169,25 @@ class SetDueDateDialog : DialogFragment() {
168169
viewModel.updateIntervalToMatchDueDate = isChecked
169170
}
170171
}
172+
173+
lifecycleScope.launch {
174+
viewModel.currentInterval.collect { currentInterval ->
175+
findViewById<MaterialTextView>(R.id.current_interval_text)!!.also { tv ->
176+
// Current interval is set to null when multiple cards are selected
177+
if (currentInterval != null) {
178+
tv.isVisible = true
179+
tv.text =
180+
resources.getQuantityString(
181+
R.plurals.set_due_date_current_interval,
182+
currentInterval,
183+
currentInterval,
184+
)
185+
} else {
186+
tv.isVisible = false
187+
}
188+
}
189+
}
190+
}
171191
}
172192

173193
override fun setupDialog(

AnkiDroid/src/main/java/com/ichi2/anki/scheduling/SetDueDateViewModel.kt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@ package com.ichi2.anki.scheduling
1919
import androidx.annotation.DrawableRes
2020
import androidx.lifecycle.ViewModel
2121
import androidx.lifecycle.viewModelScope
22+
import com.ichi2.anki.CollectionManager.withCol
2223
import com.ichi2.anki.R
2324
import com.ichi2.libanki.CardId
25+
import com.ichi2.libanki.CardType
2426
import com.ichi2.libanki.sched.SetDueDateDays
2527
import com.ichi2.libanki.undoableOp
2628
import kotlinx.coroutines.async
2729
import kotlinx.coroutines.flow.MutableStateFlow
2830
import kotlinx.coroutines.flow.update
31+
import kotlinx.coroutines.launch
2932
import timber.log.Timber
3033

3134
/**
@@ -34,6 +37,14 @@ import timber.log.Timber
3437
*/
3538
typealias NumberOfDaysInFuture = Int
3639

40+
/**
41+
* Represents the interval between reviews in days.
42+
*
43+
* - A value of `0` means the next review is due today.
44+
* - Indicates the number of days until a card's next review.
45+
*/
46+
typealias ReviewIntervalDays = Int
47+
3748
/**
3849
* [ViewModel] for [SetDueDateDialog]
3950
*/
@@ -112,12 +123,40 @@ class SetDueDateViewModel : ViewModel() {
112123
field = value
113124
}
114125

126+
/**
127+
* The current interval of the card.
128+
*
129+
* The value represents the number of days.
130+
* The value is not-null if exactly one card is selected, which is the only case
131+
* in which the view should display the interval.
132+
*/
133+
val currentInterval = MutableStateFlow<ReviewIntervalDays?>(null)
134+
115135
fun init(
116136
cardIds: LongArray,
117137
fsrsEnabled: Boolean,
118138
) {
119139
this.cardIds = cardIds.toList()
120140
this.fsrsEnabled = fsrsEnabled
141+
142+
initCurrentInterval(cardIds)
143+
}
144+
145+
private fun initCurrentInterval(cardIds: LongArray) {
146+
// Current interval cannot be shown if multiple cards are selected
147+
if (cardCount > 1) {
148+
return
149+
}
150+
151+
viewModelScope.launch {
152+
withCol {
153+
getCard(cardIds.first()).let {
154+
// Only show interval if card is in the review state
155+
// New, learning, or relearning cards have an interval of 0 and should not display it
156+
currentInterval.value = if (it.type == CardType.Rev) it.ivl else null
157+
}
158+
}
159+
}
121160
}
122161

123162
fun setNextDateRangeStart(value: Int?) {

AnkiDroid/src/main/res/layout/dialog_set_due_date.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@
5858
android:layout_height="wrap_content"
5959
/>
6060

61+
<com.google.android.material.textview.MaterialTextView
62+
android:id="@+id/current_interval_text"
63+
android:layout_width="wrap_content"
64+
android:layout_height="wrap_content"
65+
android:layout_marginStart="16dp" />
6166

6267
<com.google.android.material.checkbox.MaterialCheckBox
6368
android:id="@+id/change_interval"

AnkiDroid/src/main/res/values/03-dialogs.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,10 @@ also changes the interval of the card"
240240
<item quantity="one">day</item>
241241
<item quantity="other">days</item>
242242
</plurals>
243+
<plurals name="set_due_date_current_interval">
244+
<item quantity="one">Current interval: %d day</item>
245+
<item quantity="other">Current interval: %d days</item>
246+
</plurals>
243247
<string name="range_delimiter" comment="Placed between two input boxes to denote a range">–</string>
244248
<string name="set_due_date_range_start" comment="'Set Due Date' may change the due date of a card to a random number of days in the future. This labels the 'minimum' value of this range (inclusive)">From</string>
245249
<string name="set_due_date_range_end" comment="'Set Due Date' may change the due date of a card to a random number of days in the future. This labels the 'maximum' value of this range (inclusive)">To</string>

AnkiDroid/src/test/java/com/ichi2/anki/scheduling/SetDueDateViewModelTest.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,13 @@ class SetDueDateViewModelTest : JvmTest() {
159159
}
160160
}
161161

162+
@Test
163+
fun `currentInterval is null when multiple cards are selected`() {
164+
runViewModelTest(cardIds = listOf(1, 2)) {
165+
assertThat("currentInterval should be null", currentInterval.value, equalTo(null))
166+
}
167+
}
168+
162169
private fun runViewModelTest(
163170
cardIds: List<CardId> = listOf(1, 2, 3),
164171
fsrsEnabled: Boolean = false,

0 commit comments

Comments
 (0)