Repository navigation
feat(reminders): release review reminders - #22887
ericli3690 wants to merge 4 commits into
Conversation
|
Snapshot diff report vs
All 16 changed screenshotsCustomStudyScreenshotTest
DeckPickerTabletScreenshotTest
PreferencesScreenshotTest
ReviewRemindersScreenshotTest
StudyOptionsScreenshotTest
|
|
I've checked the screenshot test diffs and they're all due to review reminders now being public. Ex. the bell icon showing up in the DeckPicker app bar. |
|
@ericli3690 your agent seems to have bypassed the rules, we don't want co-authored... in the commits, ensure you double check before pushing the changes |
83aaf60 to
1de97b9
Compare
|
@criticalAY Oops, sorry about that. Will make sure to enforce in the future 👍 Fixed! |
mikehardy
left a comment
There was a problem hiding this comment.
Assisted-by: Grok 4.7
Thank you. The flag, the old settings screen, and the widget hook are gone together, and the upgrade test covers both sentinels and the unset key.
Rebased four commits onto current main locally with a clean replay; no force-push.
Local testing: lintAll, ktlintCheck, lint-rules:test; jacocoUnitTestReport; TEST_RELEASE_BUILD=true emulator suite on emulator-5556 / API35_GAPI. Lint, unit, and emulator lanes all passed.
RemoveLegacyNotificationPrefs is preference upgrade 30, after ResetAnalyticsOptIn2 at 29. performUpgrade runs upgrade and then stores that version. getPendingUpgrades keeps instances whose version is above the stored one, and getLatestVersion is the max of those ids.
HeaderPreference.showBadgeWhen calls refreshBadge, which sets isBadged. The setter wraps the current icon in BadgeDrawable and tints R.drawable.badge_drawable with badgeWarningColor. A second refresh while the condition is unchanged returns before wrapping again. Turning the condition off restores the inner drawable. onBindViewHolder sets the state description to settings_header_badge_state (New) only when the icon is a BadgeDrawable, and clears it on recycle. The listener is stored on the fragment because SharedPreferences keeps listeners in a WeakHashMap.
showIntroIfNeeded runs at the end of ScheduleRemindersFragment.onViewCreated. It uses the child FragmentManager. showDialogFragmentImpl executes pending transactions, removes any dialog under DIALOG_FRAGMENT_TAG, and commits the intro on the back stack with executePendingTransactions before the boolean is cleared. A later view creation finds the boolean false. The fragment manager restores the dialog itself.
The old daily alarm is AlarmManager.setRepeating with request code 0 and Intent(context, NotificationService::class.java), which has no action. BootService no longer schedules or cancels it. NotificationService.onReceiveBroadcast returns when intent.action is null, and returns again when the reminder id or scope parcel is missing. After reboot that alarm is gone, and boot only restores review-reminder alarms plus the widget rollover alarms. WidgetStatus.update launches the small-widget job only when widgetSmallEnabled is true. It no longer reads a notification preference or calls widgetNotificationScheduler.
some acceptable findings, no action required, just leaving for posterity: the legacy setRepeating daily wakeup is left in place until reboot; BootService.wasRun still says AnkiDroidApp runs this receiver though app start calls scheduleAllNotifications directly.
Screenshot changes have been detected, so leaving this for a good manual look.
|
(not pushing for changes, just opinion): how would you feel about moving the dialog into a default 'empty state' screen, rather than something that a user will see only once |
|
@david-allison Do you think we should still keep the little orange dot next to the icon for users who had legacy notifications in the past? EDIT: Actually, wait, changing my mind. I think the existing UI is intuitive as is. The dialog is more to explain to users who had legacy notifications in the past that "AnkiDroid now has review reminders". That sentence wouldn't belong on the main screen. IMO either we keep the dialog with this kind of text, or we don't have a dialog at all. The main screen doesn't need extra text cluttering it up. Put another way, perhaps we should change the dialog text to be "Your old legacy notification has been removed. AnkiDroid now has improved review reminders. Try setting one!" or something like that; the dialog is for explaining the migration, not the feature. |
|
Ahh - that works for a dialog. It doesn't need to be combative ("we've removed your notifications"). Go more for a style of "we've upgraded our notifications, [hope you enjoy them]" and it sounds good to go. (have fun with the text 😁). |
Review reminders are now available to all users, replacing the legacy notifications system. The 'Enable new notifications' developer option and its `newReviewReminders` flag are removed, and the app behaves as if it were enabled. Removed: * the 'Notifications' settings screen and its strings * the legacy due-cards notification, its daily alarm and the widget hooks which triggered it * `@LegacyNotifications` and `NotificationPreferences` The legacy alarm survives app updates until the device restarts. When it fires, `NotificationService` ignores it, as its intent has no action. Assisted-by: Claude Opus 5.5
Adds a preference upgrade removing the preferences which were only used by the legacy notifications system, including the `newReviewReminders` developer flag. Users who had a legacy due-cards notification enabled have the new `shouldShowReviewRemindersIntro` preference set, so review reminders can be introduced to them. Assisted-by: Claude Opus 5.5
Any header in the main settings menu can now show a dot at the top-right of its icon, to draw the user's attention to it: `HeaderPreference.showBadgeWhen`. The condition is re-checked whenever a preference changes, so a badge clears as soon as its condition does, including on large screens, where the header list stays visible beside the opened screen. Screen readers announce badged headers as 'New'. Assisted-by: Claude Opus 5.5
Users who had a legacy due-cards notification (`shouldShowReviewRemindersIntro`) now see: * a badge on the 'Review reminders' settings header * `ReviewRemindersIntroDialog` when review reminders are first opened Opening review reminders from anywhere, including a deck, clears the preference, so the badge disappears and the dialog shows only once. Assisted-by: Claude Opus 5.5
1de97b9 to
554cc77
Compare
|
@david-allison Updated to be:
See screenshot in the PR description! Let me know if you dislike this copy or want to change it. Also rebased, but otherwise no other changes. Also, does this PR need a strings sync? |
|
It should trigger the strings bot... CI is a little backed up right now EDIT: 🤖 Beep boop; you broke the strings bot, I'll add the label 🤖 🤣 |
Note
Assisted-by: Claude Opus 5.5
Purpose / Description
This is the big one!
Releases review reminders to the general public, deleting the dev gate and all legacy notification code.
Migrates preferences accordingly. Users who previously had a legacy notification will see an orange warning dot (modelled after the sync warning dot) next to the review reminders setting in Settings. The dot disappears after ScheduleRemindersFragment is viewed once. These users also see a new dialogue when they first open ScheduleRemindersFragment.
Users who freshly install the app, or who did not have legacy notifications in the past and who upgrade the app, will not see any new visual cues. We will rely on the changelog to signpost that review reminders have arrived.
Fixes
Approach
Might as well do it all in one PR. In particular, I can't really implement the new UI cues if the actual legacy-notification-removal PR is not present yet. The four commits here should be cleanly revertable if issues occur upon release. We should carefully stage the release out to alpha, beta, etc. I will personally be more available and on hand to patch issues.
How Has This Been Tested?
Learning
Woopee! I've learned a lot contributing to AnkiDroid for the last year and a bit. Really wish we could have launched sooner, but life got in the way. Even software development as a skill and craft has changed so much since early 2025...
Checklist