Skip to content

Commit bc66bf8

Browse files
committed
ReviewRemindersScope for ScheduleReminders entry
GSoC 2025: Review Reminders - Refactored ScheduleReminders to take a ReviewReminderScope as an argument in `getIntent` to better enforce that callers should either trigger ScheduleReminders in deck-specific or global mode rather than leaving open the possibility of passing an incorrect deckId, etc. This was recommended by David. - Made toolbar title use ReviewReminderScope to follow the above change - Modified review reminder entry points to pass a ReviewReminderScope rather than the old `getIntent` arguments
1 parent 2dce713 commit bc66bf8

File tree

6 files changed

+47
-49
lines changed

6 files changed

+47
-49
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import com.ichi2.anki.libanki.Collection
4646
import com.ichi2.anki.libanki.Decks
4747
import com.ichi2.anki.observability.ChangeManager
4848
import com.ichi2.anki.preferences.sharedPrefs
49+
import com.ichi2.anki.reviewreminders.ReviewReminderScope
4950
import com.ichi2.anki.reviewreminders.ScheduleReminders
5051
import com.ichi2.anki.snackbar.showSnackbar
5152
import com.ichi2.anki.ui.internationalization.toSentenceCase
@@ -286,8 +287,7 @@ class StudyOptionsFragment :
286287
val intent =
287288
ScheduleReminders.getIntent(
288289
requireContext(),
289-
false,
290-
col!!.decks.current().id,
290+
ReviewReminderScope.DeckSpecific(col!!.decks.current().id),
291291
)
292292
startActivity(intent)
293293
return true

AnkiDroid/src/main/java/com/ichi2/anki/deckpicker/DeckPickerViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ class DeckPickerViewModel :
181181

182182
fun scheduleReviewReminders(deckId: DeckId) =
183183
viewModelScope.launch {
184-
flowOfDestination.emit(ScheduleRemindersDestination(false, deckId))
184+
flowOfDestination.emit(ScheduleRemindersDestination(deckId))
185185
}
186186
}
187187

AnkiDroid/src/main/java/com/ichi2/anki/preferences/HeaderFragment.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import com.ichi2.anki.BuildConfig
2828
import com.ichi2.anki.CollectionManager.TR
2929
import com.ichi2.anki.R
3030
import com.ichi2.anki.preferences.reviewer.ReviewerMenuSettingsFragment
31+
import com.ichi2.anki.reviewreminders.ReviewReminderScope
3132
import com.ichi2.anki.reviewreminders.ScheduleReminders
3233
import com.ichi2.anki.settings.Prefs
3334
import com.ichi2.anki.ui.internationalization.toSentenceCase
@@ -64,7 +65,7 @@ class HeaderFragment : SettingsFragment() {
6465
requirePreference<HeaderPreference>(R.string.pref_review_reminders_screen_key)
6566
.setOnPreferenceClickListener {
6667
Timber.i("HeaderFragment:: edit review reminders button pressed")
67-
val intent = ScheduleReminders.getIntent(requireContext(), true)
68+
val intent = ScheduleReminders.getIntent(requireContext(), ReviewReminderScope.Global)
6869
startActivity(intent)
6970
true
7071
}

AnkiDroid/src/main/java/com/ichi2/anki/preferences/Preferences.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import com.google.android.material.appbar.MaterialToolbar
4343
import com.ichi2.anki.R
4444
import com.ichi2.anki.SingleFragmentActivity
4545
import com.ichi2.anki.preferences.HeaderFragment.Companion.getHeaderKeyForFragment
46+
import com.ichi2.anki.reviewreminders.ReviewReminderScope
4647
import com.ichi2.anki.reviewreminders.ScheduleReminders
4748
import com.ichi2.anki.utils.ext.sharedPrefs
4849
import com.ichi2.anki.utils.isWindowCompact
@@ -115,7 +116,7 @@ class PreferencesFragment :
115116
override fun onSearchResultClicked(result: SearchPreferenceResult) {
116117
if (result.key == getString(R.string.pref_review_reminders_screen_key)) {
117118
Timber.i("Preferences:: edit review reminders button pressed")
118-
val intent = ScheduleReminders.getIntent(requireContext(), true)
119+
val intent = ScheduleReminders.getIntent(requireContext(), ReviewReminderScope.Global)
119120
startActivity(intent)
120121
return
121122
}

AnkiDroid/src/main/java/com/ichi2/anki/reviewreminders/ScheduleReminders.kt

Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -20,89 +20,82 @@ import android.content.Context
2020
import android.content.Intent
2121
import android.os.Bundle
2222
import android.view.View
23+
import androidx.appcompat.app.AppCompatActivity
24+
import androidx.core.os.BundleCompat
2325
import androidx.fragment.app.Fragment
2426
import com.google.android.material.appbar.MaterialToolbar
25-
import com.ichi2.anki.CollectionManager.withCol
2627
import com.ichi2.anki.R
2728
import com.ichi2.anki.SingleFragmentActivity
2829
import com.ichi2.anki.launchCatchingTask
29-
import com.ichi2.anki.libanki.DeckId
3030
import timber.log.Timber
3131

3232
/**
3333
* Fragment for creating, viewing, editing, and deleting review reminders.
3434
*/
3535
class ScheduleReminders : Fragment(R.layout.fragment_schedule_reminders) {
3636
/**
37-
* If this flag is true, the user is viewing and editing all reminders in the entire app from a unified dashboard.
38-
* If this flag is false, the user is viewing and editing reminders for a single deck.
37+
* Whether this fragment has been opened to edit all review reminders or just a specific deck's reminders.
38+
* @see ReviewReminderScope
3939
*/
40-
private var isInGlobalScope = false
40+
private val scheduleRemindersScope: ReviewReminderScope by lazy {
41+
BundleCompat.getParcelable(
42+
requireArguments(),
43+
EXTRAS_SCOPE_KEY,
44+
ReviewReminderScope::class.java,
45+
) ?: ReviewReminderScope.Global
46+
}
4147

42-
/**
43-
* This private variable is only used for the deck-specific editing scope.
44-
* In global scope, it is set to -1.
45-
*/
46-
private var did: DeckId = -1L
48+
private lateinit var toolbar: MaterialToolbar
4749

4850
override fun onViewCreated(
4951
view: View,
5052
savedInstanceState: Bundle?,
5153
) {
5254
super.onViewCreated(view, savedInstanceState)
5355

54-
val toolbar =
55-
view.findViewById<MaterialToolbar>(R.id.toolbar).apply {
56-
setTitle(R.string.schedule_reminders_do_not_translate)
57-
setNavigationOnClickListener {
58-
requireActivity().onBackPressedDispatcher.onBackPressed()
59-
}
60-
}
56+
// Set up toolbar
57+
toolbar = view.findViewById(R.id.toolbar)
58+
reloadToolbarText()
59+
(requireActivity() as AppCompatActivity).setSupportActionBar(toolbar)
60+
}
6161

62-
// Retrieve arguments, update toolbar accordingly
63-
isInGlobalScope = requireArguments().getBoolean(EXTRAS_GLOBAL_SCOPE_KEY, true)
64-
if (!isInGlobalScope) {
65-
// Get the deck ID from arguments
66-
did = requireArguments().getLong(EXTRAS_DECK_ID_KEY)
67-
if (did == -1L) {
68-
throw IllegalArgumentException("A deck ID must be provided when using the deck-specific editing scope of ScheduleReminders")
69-
}
70-
// Retrieve the deck name and set it as the toolbar subtitle
71-
launchCatchingTask {
72-
toolbar.subtitle =
73-
withCol {
74-
decks.name(did)
75-
}
76-
}
62+
private fun reloadToolbarText() {
63+
Timber.d("Reloading toolbar text")
64+
toolbar.title = getString(R.string.schedule_reminders_do_not_translate)
65+
when (val scope = scheduleRemindersScope) {
66+
is ReviewReminderScope.Global -> {}
67+
is ReviewReminderScope.DeckSpecific ->
68+
launchCatchingTask {
69+
toolbar.subtitle = scope.getDeckName()
70+
}
7771
}
7872
}
7973

8074
companion object {
81-
private const val EXTRAS_GLOBAL_SCOPE_KEY = "global_scope"
82-
private const val EXTRAS_DECK_ID_KEY = "did"
75+
/**
76+
* Arguments key for passing the [ReviewReminderScope] to open this fragment with.
77+
*/
78+
private const val EXTRAS_SCOPE_KEY = "scope"
8379

8480
/**
8581
* Creates an intent to start the ScheduleReminders fragment.
8682
* @param context
87-
* @param isInGlobalScope Whether the fragment should be opened in global or deck-specific scope.
88-
* @param did The ID of the deck being edited if [isInGlobalScope] is false. Defaults to null otherwise.
83+
* @param scope The editing scope of the ScheduleReminders fragment.
8984
* @return The new intent.
9085
*/
9186
fun getIntent(
9287
context: Context,
93-
isInGlobalScope: Boolean,
94-
did: DeckId? = null,
88+
scope: ReviewReminderScope,
9589
): Intent =
9690
SingleFragmentActivity
9791
.getIntent(
9892
context,
9993
ScheduleReminders::class,
10094
Bundle().apply {
101-
putBoolean(EXTRAS_GLOBAL_SCOPE_KEY, isInGlobalScope)
102-
putLong(EXTRAS_DECK_ID_KEY, did ?: -1L)
95+
putParcelable(EXTRAS_SCOPE_KEY, scope)
10396
},
10497
).apply {
105-
Timber.i("launching ScheduleReminders for %s", did?.toString() ?: "all decks")
98+
Timber.i("launching ScheduleReminders for $scope scope")
10699
}
107100
}
108101
}

AnkiDroid/src/main/java/com/ichi2/anki/reviewreminders/ScheduleRemindersDestination.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ import com.ichi2.anki.libanki.DeckId
2222
import com.ichi2.anki.utils.Destination
2323

2424
class ScheduleRemindersDestination(
25-
private val isInGlobalScope: Boolean,
26-
private val did: DeckId? = null,
25+
private val did: DeckId,
2726
) : Destination {
28-
override fun toIntent(context: Context): Intent = ScheduleReminders.getIntent(context, isInGlobalScope, did)
27+
override fun toIntent(context: Context): Intent =
28+
ScheduleReminders.getIntent(
29+
context,
30+
ReviewReminderScope.DeckSpecific(did),
31+
)
2932
}

0 commit comments

Comments
 (0)