From 10c8e6e1a4964121c92d19e372cef68545f27a22 Mon Sep 17 00:00:00 2001 From: Sneha Datta Date: Thu, 3 Oct 2024 16:23:08 +0530 Subject: [PATCH 1/3] Fix #5404: Migrate away from onBackPressed for remaining activities (#5526) ## Explanation Fixes #5404 This PR migrates deprecated `onBackPressed` usage to `OnBackPressedDispatcher` callback in the following activities and presenters. - ProfileEditActivity - ProfileEditActivityPresenter - QuestionPlayerActivityPresenter - WalkthroughFinalFragmentPresenter ## Essential Checklist - [x] The PR title and explanation each start with "Fix #bugnum: " (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".) - [x] Any changes to [scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets) files have their rationale included in the PR explanation. - [x] The PR follows the [style guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide). - [x] The PR does not contain any unnecessary code changes from Android Studio ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)). - [x] The PR is made from a branch that's **not** called "develop" and is up-to-date with "develop". - [x] The PR is **assigned** to the appropriate reviewers ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)). ## For UI-specific PRs only If your PR includes UI-related changes, then: - Add screenshots for portrait/landscape for both a tablet & phone of the before & after UI changes - For the screenshots above, include both English and pseudo-localized (RTL) screenshots (see [RTL guide](https://github.com/oppia/oppia-android/wiki/RTL-Guidelines)) - Add a video showing the full UX flow with a screen reader enabled (see [accessibility guide](https://github.com/oppia/oppia-android/wiki/Accessibility-A11y-Guide)) - For PRs introducing new UI elements or color changes, both light and dark mode screenshots must be included - Add a screenshot demonstrating that you ran affected Espresso tests locally & that they're passing --------- Co-authored-by: Adhiambo Peres <59600948+adhiamboperes@users.noreply.github.com> Co-authored-by: Mr. 17 --- .../app/settings/profile/ProfileEditActivity.kt | 15 ++++++++++++--- .../profile/ProfileEditActivityPresenter.kt | 3 +-- .../questionplayer/QuestionPlayerActivity.kt | 14 ++++++++++---- .../QuestionPlayerActivityPresenter.kt | 3 +-- .../app/walkthrough/WalkthroughActivity.kt | 14 ++++++++++---- .../end/WalkthroughFinalFragmentPresenter.kt | 3 +-- 6 files changed, 35 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivity.kt b/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivity.kt index c595bd367ca..2698cfe96a7 100644 --- a/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivity.kt +++ b/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivity.kt @@ -3,6 +3,7 @@ package org.oppia.android.app.settings.profile import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.activity.OnBackPressedCallback import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAutoLocalizedAppCompatActivity import org.oppia.android.app.model.ProfileEditActivityParams @@ -43,17 +44,25 @@ class ProfileEditActivity : InjectableAutoLocalizedAppCompatActivity() { super.onCreate(savedInstanceState) (activityComponent as ActivityComponentImpl).inject(this) profileEditActivityPresenter.handleOnCreate() + + onBackPressedDispatcher.addCallback( + this, + object : OnBackPressedCallback(/* enabled = */ true) { + override fun handleOnBackPressed() { + this@ProfileEditActivity.handleBackPress() + } + } + ) } - override fun onBackPressed() { + private fun handleBackPress() { val args = intent.getProtoExtra( PROFILE_EDIT_ACTIVITY_PARAMS_KEY, ProfileEditActivityParams.getDefaultInstance() ) val isMultipane = args?.isMultipane ?: false if (isMultipane) { - @Suppress("DEPRECATION") // TODO(#5404): Migrate to a back pressed dispatcher. - super.onBackPressed() + finish() } else { val intent = Intent(this, ProfileListActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) diff --git a/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivityPresenter.kt index ea67fb89474..b89f8857de2 100644 --- a/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivityPresenter.kt @@ -31,8 +31,7 @@ class ProfileEditActivityPresenter @Inject constructor( toolbar.setNavigationOnClickListener { if (isMultipane) { - @Suppress("DEPRECATION") // TODO(#5404): Migrate to a back pressed dispatcher. - activity.onBackPressed() + activity.onBackPressedDispatcher.onBackPressed() } else { val intent = Intent(activity, ProfileListActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) diff --git a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivity.kt b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivity.kt index 70239733952..027cbd7011f 100644 --- a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivity.kt +++ b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivity.kt @@ -3,6 +3,7 @@ package org.oppia.android.app.topic.questionplayer import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.activity.OnBackPressedCallback import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAutoLocalizedAppCompatActivity import org.oppia.android.app.hintsandsolution.HintsAndSolutionListener @@ -56,11 +57,16 @@ class QuestionPlayerActivity : val profileId = intent.extractCurrentUserProfileId() questionPlayerActivityPresenter.handleOnCreate(profileId) - } - override fun onBackPressed() { - showStopExplorationDialogFragment() - questionPlayerActivityPresenter.setReadingTextSizeNormal() + onBackPressedDispatcher.addCallback( + this, + object : OnBackPressedCallback(/* enabled = */ true) { + override fun handleOnBackPressed() { + showStopExplorationDialogFragment() + questionPlayerActivityPresenter.setReadingTextSizeNormal() + } + } + ) } override fun restartSession() = questionPlayerActivityPresenter.restartSession() diff --git a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityPresenter.kt index 523ebf2cc4d..345941e95e1 100644 --- a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityPresenter.kt @@ -61,8 +61,7 @@ class QuestionPlayerActivityPresenter @Inject constructor( activity.setSupportActionBar(binding.questionPlayerToolbar) binding.questionPlayerToolbar.setNavigationOnClickListener { - @Suppress("DEPRECATION") // TODO(#5404): Migrate to a back pressed dispatcher. - activity.onBackPressed() + activity.onBackPressedDispatcher.onBackPressed() } retrieveReadingTextSize().observe( diff --git a/app/src/main/java/org/oppia/android/app/walkthrough/WalkthroughActivity.kt b/app/src/main/java/org/oppia/android/app/walkthrough/WalkthroughActivity.kt index 083b293bad7..d3d7a7081e3 100644 --- a/app/src/main/java/org/oppia/android/app/walkthrough/WalkthroughActivity.kt +++ b/app/src/main/java/org/oppia/android/app/walkthrough/WalkthroughActivity.kt @@ -3,6 +3,7 @@ package org.oppia.android.app.walkthrough import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.activity.OnBackPressedCallback import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAutoLocalizedAppCompatActivity import org.oppia.android.app.model.ProfileId @@ -22,6 +23,15 @@ class WalkthroughActivity : super.onCreate(savedInstanceState) (activityComponent as ActivityComponentImpl).inject(this) walkthroughActivityPresenter.handleOnCreate() + + onBackPressedDispatcher.addCallback( + this, + object : OnBackPressedCallback(/* enabled = */ true) { + override fun handleOnBackPressed() { + walkthroughActivityPresenter.handleSystemBack() + } + } + ) } override fun currentPage(walkthroughPage: Int) { @@ -33,10 +43,6 @@ class WalkthroughActivity : walkthroughActivityPresenter.changePage(walkthroughPage) } - override fun onBackPressed() { - walkthroughActivityPresenter.handleSystemBack() - } - companion object { fun createWalkthroughActivityIntent(context: Context, internalProfileId: Int): Intent { diff --git a/app/src/main/java/org/oppia/android/app/walkthrough/end/WalkthroughFinalFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/walkthrough/end/WalkthroughFinalFragmentPresenter.kt index abd286f77d8..078d79af431 100644 --- a/app/src/main/java/org/oppia/android/app/walkthrough/end/WalkthroughFinalFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/walkthrough/end/WalkthroughFinalFragmentPresenter.kt @@ -103,7 +103,6 @@ class WalkthroughFinalFragmentPresenter @Inject constructor( } override fun goBack() { - @Suppress("DEPRECATION") // TODO(#5404): Migrate to a back pressed dispatcher. - activity.onBackPressed() + activity.onBackPressedDispatcher.onBackPressed() } } From 5e140e989949bee89b1b266b535608bd2f839615 Mon Sep 17 00:00:00 2001 From: Sneha Datta Date: Wed, 9 Oct 2024 15:06:52 +0530 Subject: [PATCH 2/3] Fix #5404: Migrate away from onBackPressed for RevisionCardActivity (#5548) ## Explanation Fixes #5404 This PR migrates deprecated `onBackPressed `usage to `OnBackPressedDispatcher` callback in the RevisonCardActivity and RevisionCardActivityPresenter. ## Essential Checklist - [x] The PR title and explanation each start with "Fix #bugnum: " (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".) - [x] Any changes to [scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets) files have their rationale included in the PR explanation. - [x] The PR follows the [style guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide). - [x] The PR does not contain any unnecessary code changes from Android Studio ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)). - [x] The PR is made from a branch that's **not** called "develop" and is up-to-date with "develop". - [x] The PR is **assigned** to the appropriate reviewers ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)). ## For UI-specific PRs only If your PR includes UI-related changes, then: - Add screenshots for portrait/landscape for both a tablet & phone of the before & after UI changes - For the screenshots above, include both English and pseudo-localized (RTL) screenshots (see [RTL guide](https://github.com/oppia/oppia-android/wiki/RTL-Guidelines)) - Add a video showing the full UX flow with a screen reader enabled (see [accessibility guide](https://github.com/oppia/oppia-android/wiki/Accessibility-A11y-Guide)) - For PRs introducing new UI elements or color changes, both light and dark mode screenshots must be included - Add a screenshot demonstrating that you ran affected Espresso tests locally & that they're passing --- .../topic/revisioncard/RevisionCardActivity.kt | 17 ++++++++++------- .../RevisionCardActivityPresenter.kt | 3 +-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivity.kt b/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivity.kt index 7606c7ea5ad..1dc30c6fd9e 100644 --- a/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivity.kt +++ b/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivity.kt @@ -3,6 +3,7 @@ package org.oppia.android.app.topic.revisioncard import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.activity.OnBackPressedCallback import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAutoLocalizedAppCompatActivity import org.oppia.android.app.model.ProfileId @@ -56,6 +57,15 @@ class RevisionCardActivity : subtopicListSize ) } + onBackPressedDispatcher.addCallback( + this, + object : OnBackPressedCallback(/* enabled = */ true) { + override fun handleOnBackPressed() { + revisionCardActivityPresenter.setReadingTextSizeMedium() + onReturnToTopicRequested() + } + } + ) } override fun handleOnOptionsItemSelected(itemId: Int) { @@ -115,13 +125,6 @@ class RevisionCardActivity : revisionCardActivityPresenter.dismissConceptCard() } - // TODO(#5404): Migrate to a back pressed dispatcher. - @Deprecated("Deprecated in Java") - override fun onBackPressed() { - revisionCardActivityPresenter.setReadingTextSizeMedium() - onReturnToTopicRequested() - } - override fun onDefaultFontSizeLoaded(readingTextSize: ReadingTextSize) { revisionCardActivityPresenter.loadRevisionCardFragment(readingTextSize) } diff --git a/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityPresenter.kt index af41963e498..c77afb97738 100644 --- a/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityPresenter.kt @@ -83,8 +83,7 @@ class RevisionCardActivityPresenter @Inject constructor( binding.revisionCardToolbar.setNavigationOnClickListener { (activity as ReturnToTopicClickListener).onReturnToTopicRequested() fontScaleConfigurationUtil.adjustFontScale(activity, ReadingTextSize.MEDIUM_TEXT_SIZE) - @Suppress("DEPRECATION") // TODO(#5404): Migrate to a back pressed dispatcher. - activity.onBackPressed() + activity.onBackPressedDispatcher.onBackPressed() } if (!accessibilityService.isScreenReaderEnabled()) { binding.revisionCardToolbarTitle.setOnClickListener { From 8d0328cd9ce5389bebc56aad4c59fb090c5a5522 Mon Sep 17 00:00:00 2001 From: Subhajit Mallick <153619690+subhajitxyz@users.noreply.github.com> Date: Sat, 12 Oct 2024 10:48:49 +0530 Subject: [PATCH 3/3] Add replaceRegexWithBlank function --- .../state/itemviewmodel/ContentViewModel.kt | 30 ++++++++++++++++++- app/src/main/res/layout/content_item.xml | 1 + 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/ContentViewModel.kt b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/ContentViewModel.kt index 5a581ea586b..88c72d94734 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/ContentViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/ContentViewModel.kt @@ -1,5 +1,8 @@ package org.oppia.android.app.player.state.itemviewmodel +import android.text.Spannable +import android.text.SpannableStringBuilder + /** [StateItemViewModel] for content-card state. */ class ContentViewModel( val htmlContent: CharSequence, @@ -7,4 +10,29 @@ class ContentViewModel( val hasConversationView: Boolean, val isSplitView: Boolean, val supportsConceptCards: Boolean -) : StateItemViewModel(ViewType.CONTENT) +) : StateItemViewModel(ViewType.CONTENT) { + + private val underscoreRegex = Regex("(?<=\\s|[,.;?!])_{3,}(?=\\s|[,.;?!])") + private val replacementText = "Blank" + + /** + * Replaces "2+ underscores, with space/punctuation on both sides" in the input text with a + * replacement string "blank", returning a Spannable. + * Adjusts offsets to handle text length changes during replacements. + */ + fun replaceRegexWithBlank(inputText: CharSequence): Spannable { + val spannableStringBuilder = SpannableStringBuilder(inputText) + val matches = underscoreRegex.findAll(inputText) + var lengthOffset = 0 + + for (match in matches) { + val matchStart = match.range.first + lengthOffset + val matchEnd = match.range.last + 1 + lengthOffset + spannableStringBuilder.replace(matchStart, matchEnd, replacementText) + + // Adjust offset due to change in length (difference between old and new text length) + lengthOffset += replacementText.length - (matchEnd - matchStart) + } + return spannableStringBuilder + } +} diff --git a/app/src/main/res/layout/content_item.xml b/app/src/main/res/layout/content_item.xml index c8571f1706f..09b1eb682ce 100644 --- a/app/src/main/res/layout/content_item.xml +++ b/app/src/main/res/layout/content_item.xml @@ -48,6 +48,7 @@ android:minWidth="48dp" android:minHeight="48dp" android:text="@{htmlContent}" + android:contentDescription="@{viewModel.replaceRegexWithBlank(htmlContent)}" android:textColor="@color/component_color_shared_primary_text_color" android:textColorLink="@color/component_color_shared_link_text_color" android:textSize="16sp"