From d74576dae6ec2e6a8d14226ae47ab2f87ef6c881 Mon Sep 17 00:00:00 2001
From: MOHIT GUPTA <76530270+MohitGupta121@users.noreply.github.com>
Date: Mon, 14 Aug 2023 09:08:50 -0600
Subject: [PATCH 01/34] Fix #4607 : [Developer Video] How to use an
Accessibility Scanner? (#5129)
## Explanation
Fix #4607 : [Developer Video] How to use an Accessibility Scanner?
## 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: ...".)
- [ ] 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))
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing
---
wiki/Accessibility-A11y-Guide.md | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/wiki/Accessibility-A11y-Guide.md b/wiki/Accessibility-A11y-Guide.md
index 7e95ad24bc5..692560e18b2 100644
--- a/wiki/Accessibility-A11y-Guide.md
+++ b/wiki/Accessibility-A11y-Guide.md
@@ -8,6 +8,7 @@
- [Using a11y scanner in android](#using-a11y-scanner-in-android)
- [Using Talkback in android](#using-talkback-in-android)
- [Useful Resources](#useful-resources)
+ - [Developer Videos](#developer-videos)
- [Using AccessibilityTestRule in Espresso Tests](#using-accessibilitytestrule-in-espresso-tests)
- [Auditing the app](#auditing-the-app)
- [General Tips to make app Accessible](#general-tips-to-make-app-accessible)
@@ -31,11 +32,12 @@ There are various manual and automated tests to check if app is accessible by al
**[Accessibility Scanner](https://support.google.com/accessibility/android/answer/6376570?hl=en)** : Using Accessibility Scanner we can take screenshots of each and every screen in the Oppia-app manually and the Accessibility Scanner app will give the output for the individual screenshot mentioning all the errors.
+[Here](https://youtu.be/LF5AgGI5H3A) is a video tutorial on how to set up and use the Accessibility Scanner.
+
**Screen Reader**: Screen readers like **Talkback** can be used to test the app manually. Talkback app is used by blind people to navigate to different items in the screen and get audio based output. This app will not give any error like Accessibility Scanner.
**[AccessibilityChecks](https://developer.android.com/guide/topics/ui/accessibility/testing#automated)**: Developers can activate the `AccessibilityChecks` in all `Espresso` test cases which will give errors related to accessibility.
-
## Setting up Accessibility Scanner and Talkback
### Setup Play Store in mobile emulator
@@ -78,13 +80,15 @@ TalkBack is the Google **screen reader** included on Android devices. TalkBack g
5. Read all the instructions written on the screen as using Talkback requires specific steps.
6. Turn on **Use Service** -> **Allow**
-
### Useful Resources
* [Android A11Y Overview](https://support.google.com/accessibility/android/answer/6006564)
* [Using A11Y Menu](https://support.google.com/accessibility/android/answer/9078941)
* [Getting started with Talkback](https://support.google.com/accessibility/android/answer/6283677)
* [Display speech output as Text: Talkback](https://developer.android.com/guide/topics/ui/accessibility/testing#optional_talkback_developer_settings)
+### Developer Videos
+* [How to use Accessibility Scanner? - Tutorial](https://youtu.be/LF5AgGI5H3A)
+ * [Presentation Slides](https://docs.google.com/presentation/d/1PM_gs3TV2LVKFv6WuF9CUQHWbK7koepAxypzxeZTFzE/edit?usp=sharing)
## Using AccessibilityTestRule in Espresso Tests
[AccessibilityTestRule](https://github.com/oppia/oppia-android/blob/develop/testing/src/main/java/org/oppia/android/testing/AccessibilityTestRule.kt) is a JUnit rule to enable `AccessibilityChecks` in all Espresso Tests. This rule covers all errors shown by Accessibility Scanner and more but only for all those UI elements which are getting used in the test case.
From c5b11fe5126072e929f9bfaab8bb42074016a3c9 Mon Sep 17 00:00:00 2001
From: MOHIT GUPTA <76530270+MohitGupta121@users.noreply.github.com>
Date: Tue, 5 Sep 2023 14:13:29 -0600
Subject: [PATCH 02/34] Fix #5094 : [Wiki update] Bazel build failed in mac m1
(#5139)
## Explanation
Fix #5094 : [Wiki update] Bazel build failed in mac m1
## 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: ...".)
- [ ] 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))
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing
---
wiki/Troubleshooting-Installation.md | 36 ++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/wiki/Troubleshooting-Installation.md b/wiki/Troubleshooting-Installation.md
index 55d14907a1d..d88c4bf01ad 100644
--- a/wiki/Troubleshooting-Installation.md
+++ b/wiki/Troubleshooting-Installation.md
@@ -10,10 +10,13 @@ Here are some general troubleshooting tips for oppia-android. The specific platf
1. If you find any error related to `cURL`, please set up cURL on your machine. For Linux, you can use `sudo apt install curl`. No need to set up `cURL` for Windows as you are using git bash command line.
+
2. If you find any error which says `java: command not found`, please check you have Java installed correctly in your machine and the [environment path variable](https://www.java.com/en/download/help/path.html) is also set up correctly.
+
3. If you find any error related to Kotlin or Java/Checkstyle while pushing the code, please check [this link](https://github.com/oppia/oppia-android/wiki/Android-Studio-UI-based-Github-workflow#how-to-fix-push-failures).
+
4. If you see the error
```
@@ -22,6 +25,7 @@ Here are some general troubleshooting tips for oppia-android. The specific platf
then please follow the 2nd step mentioned in [this wiki](https://github.com/oppia/oppia-android/wiki/Installing-Oppia-Android#install-oppia-android) for Mac with Apple silicon(M1/M2) chips.
+
5. If you see the error
```
@@ -70,6 +74,7 @@ Here are some general troubleshooting tips for oppia-android. The specific platf
```
[Steps](https://docs.bazel.build/versions/main/tutorial/android-app.html#integrate-with-the-android-sdk) to add ANDROID_HOME environment variable.
+
2. If you encounter the following:
```
@@ -79,11 +84,42 @@ Here are some general troubleshooting tips for oppia-android. The specific platf
Try to delete the `.bazelrc` file to solve the above error.
+
3. **java.lang.ClassNotFoundException: com.android.tools.r8.compatdx.CompatDx**
If, when building the app binary, you encounter a failure that indicates that the CompatDx file cannot be found, this is likely due to you using a newer version of the Android build tools. You can manually downgrade to an older version of build-tools (particularly 29.0.2). Unfortunately, this can't be done through Android Studio but it can be done over a terminal. Follow the instructions listed [here](https://github.com/oppia/oppia-android/issues/3024#issuecomment-884513455) to downgrade your build tools & then try to build the app again.
+4. If you encounter this error while building bazel in Mac M1:
+ ```
+ ERROR: /Users/OpenSource/oppia-android/model/src/main/proto/BUILD.bazel:167:20: Generating JavaLite proto_library //model/src/main/proto:profile_proto failed: (Segmentation fault): protoc failed: error executing command bazel-out/darwin-opt-exec-2B5CBBC6/bin/external/com_google_protobuf/protoc '--proto_path=bazel-out/android-armeabi-v7a-fastbuild/bin/model/src/main/proto/_virtual_imports/languages_proto' ... (remaining 8 argument(s) skipped)
+
+ Use --sandbox_debug to see verbose messages from the sandbox protoc failed: error executing command bazel-out/darwin-opt-exec-2B5CBBC6/bin/external/com_google_protobuf/protoc '--proto_path=bazel-out/android-armeabi-v7a-fastbuild/bin/model/src/main/proto/_virtual_imports/languages_proto' ... (remaining 8 argument(s) skipped)
+ ```
+Bazel requires Xcode commandline tools to build on M1, and the Xcode license also needs to be accepted.
+
+ **Follow these steps to solve this error:**
+
+- Install the commandline tools: `xcode-select --install`
+
+- Accept the Xcode licence: `sudo xcodebuild -licence`
+
+- Reset the xcode select path: `sudo xcode-select -r `
+
+ - Set the xcode select path to use CommandLineTools: `sudo xcode-select -s /Library/Developer/CommandLineTools`
+
+- Confirm that the path was correctly set. The expected output is: `/Library/Developer/CommandLineTools`
+
+ xcode-select -p
+
+After successfully running the above commands, build the app using Bazel by running the following command:
+
+ ```
+ bazel clean --expunge
+ bazel build //:oppia --noexperimental_check_desugar_deps
+ ```
+The `--noexperimental_check_desugar_deps` flag is explained in the [bazel blog](https://blog.bazel.build/2018/12/19/bazel-0.21.html#android).
+
### Can’t find a particular issue?
If the error you get is not in the Troubleshooting section above, please create an issue providing all the necessary information and assign it to **@MohitGupta121**.
From 7668bf08235faca71c07858293158766487aa0bf Mon Sep 17 00:00:00 2001
From: Vishwajith Shettigar
<76042077+Vishwajith-Shettigar@users.noreply.github.com>
Date: Wed, 6 Sep 2023 02:25:41 +0530
Subject: [PATCH 03/34] Fix #4735 Text unit is set in dp instead of sp (#5134)
## Explanation
Fix #4735 , Added toolbar in admin_pin_activity xml file inorder to
control the title size using sp.
## 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
Before fix
Admin pin activity
| Light mode|
|--------|
|![before
light](https://github.com/oppia/oppia-android/assets/76042077/e80cd747-b04c-43c5-96b9-848dc5db3400)
|
After fix
|Light mode| Dark mode|
|-----------|--------------|
|
![afterlightmode](https://github.com/oppia/oppia-android/assets/76042077/4445ebd1-3fde-40f4-a4cb-cb3716aad43e)
|
![afterdarkmode](https://github.com/oppia/oppia-android/assets/76042077/98bd0994-5f4d-464f-b170-d21e167a9eaa)
|
Co-authored-by: Adhiambo Peres <59600948+adhiamboperes@users.noreply.github.com>
---
app/src/main/AndroidManifest.xml | 1 +
.../android/app/profile/AdminPinActivity.kt | 5 ++++
.../app/profile/AdminPinActivityPresenter.kt | 10 ++++---
.../main/res/layout/admin_pin_activity.xml | 26 ++++++++++++++++---
app/src/main/res/values/styles.xml | 4 +++
5 files changed, 39 insertions(+), 7 deletions(-)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a27551a2005..897fc034879 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -138,6 +138,7 @@
(activity, R.layout.admin_pin_activity)
+ activity.setSupportActionBar(binding.adminPinToolbar)
+ activity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
+ activity.supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_close_white_24dp)
+ activity.supportActionBar?.setHomeActionContentDescription(R.string.admin_auth_close)
+
binding.apply {
lifecycleOwner = activity
viewModel = adminViewModel
}
+ binding.adminPinToolbar.title = resourceHandler
+ .getStringInLocale(R.string.admin_auth_activity_add_profiles_title)
// [onTextChanged] is a extension function defined at [TextInputEditTextHelper]
binding.adminPinInputPinEditText.onTextChanged { pin ->
pin?.let {
diff --git a/app/src/main/res/layout/admin_pin_activity.xml b/app/src/main/res/layout/admin_pin_activity.xml
index e40ed050b9d..f22760b80dd 100644
--- a/app/src/main/res/layout/admin_pin_activity.xml
+++ b/app/src/main/res/layout/admin_pin_activity.xml
@@ -13,14 +13,32 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
+
+
+
+ android:scrollbars="none"
+ android:background="@color/component_color_shared_screen_secondary_background_color"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/admin_pin_toolbar"
+ >
@anim/slide_up
@anim/slide_down
+
+
From a1ba8bd3dab65d4213192918b8d4216330cb5a7e Mon Sep 17 00:00:00 2001
From: Vishwajith Shettigar
<76042077+Vishwajith-Shettigar@users.noreply.github.com>
Date: Thu, 7 Sep 2023 18:06:05 +0530
Subject: [PATCH 04/34] Fix #5142 Edit text foreground and background contrast
ratio issue in Light mode (#5144)
## Explanation
Fix #5142, changed text input default stroke color.
Added color resource file names component_color_text_layout.xml in order
to give stroke color
## 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
Berore fix
| Light mode| Dark mode|
|--------|--------|
|
![contarstlight_before](https://github.com/oppia/oppia-android/assets/76042077/0fcb4613-a7fb-4320-ae88-792704d61950)|![contastdark_before](https://github.com/oppia/oppia-android/assets/76042077/d36c6c13-654a-4603-8cef-80472dacf0d3)|
Afterfix
| Light mode| Dark mode|
|--------|--------|
|![newnew](https://github.com/oppia/oppia-android/assets/76042077/ef50252b-7c21-41ab-baee-2f244e87644b)|![contrastdark_after](https://github.com/oppia/oppia-android/assets/76042077/e4418fb6-9fb1-4c32-8c54-339235303abb)|
Screen recording after fix
Light mode
https://github.com/oppia/oppia-android/assets/76042077/943629a3-2b4a-4459-bbf9-0f0246860ffd
Dark mode
https://github.com/oppia/oppia-android/assets/76042077/c85256a0-5f99-4577-82e4-b95ce0d24027
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))
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing
---
app/src/main/res/color/component_color_text_layout.xml | 5 +++++
app/src/main/res/values-night/color_palette.xml | 2 ++
app/src/main/res/values/color_palette.xml | 2 ++
app/src/main/res/values/styles.xml | 2 +-
4 files changed, 10 insertions(+), 1 deletion(-)
create mode 100644 app/src/main/res/color/component_color_text_layout.xml
diff --git a/app/src/main/res/color/component_color_text_layout.xml b/app/src/main/res/color/component_color_text_layout.xml
new file mode 100644
index 00000000000..9795672d6eb
--- /dev/null
+++ b/app/src/main/res/color/component_color_text_layout.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/values-night/color_palette.xml b/app/src/main/res/values-night/color_palette.xml
index 7bb64f94cb7..299d498bfc6 100644
--- a/app/src/main/res/values-night/color_palette.xml
+++ b/app/src/main/res/values-night/color_palette.xml
@@ -225,4 +225,6 @@
@color/color_def_white@color/color_def_oppia_green@color/color_def_pale_green
+ @color/color_def_black_87
+ @color/color_def_white
diff --git a/app/src/main/res/values/color_palette.xml b/app/src/main/res/values/color_palette.xml
index 50e8f6caa30..13113daf937 100644
--- a/app/src/main/res/values/color_palette.xml
+++ b/app/src/main/res/values/color_palette.xml
@@ -265,4 +265,6 @@
@color/color_def_chooser_grey@color/color_def_persian_green@color/color_def_grey
+ @color/color_def_black_87
+ @color/color_def_black_87
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 2be703def67..149d87fd1d1 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -170,7 +170,7 @@
@dimen/text_input_layout_corner_radius@dimen/text_input_layout_corner_radius@dimen/text_input_layout_corner_radius
- @color/component_color_shared_text_input_layout_stroke_color
+ @color/component_color_text_layout@dimen/text_input_layout_stroke_widthtrue@color/component_color_shared_text_input_layout_error_color
From 5e74b842d565ace32bd6f839f4b835037cd3cd36 Mon Sep 17 00:00:00 2001
From: MOHIT GUPTA <76530270+MohitGupta121@users.noreply.github.com>
Date: Tue, 12 Sep 2023 09:31:45 -0600
Subject: [PATCH 05/34] Fix #4608 : [Developer Video] How to use Talkback -
screen reader and what does its output mean? (#5148)
## Explanation
Fix #4608 : [Developer Video] How to use Talkback - screen reader and
what does its output mean?
## 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)).
---
wiki/Accessibility-A11y-Guide.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/wiki/Accessibility-A11y-Guide.md b/wiki/Accessibility-A11y-Guide.md
index 692560e18b2..54e713469f4 100644
--- a/wiki/Accessibility-A11y-Guide.md
+++ b/wiki/Accessibility-A11y-Guide.md
@@ -80,6 +80,8 @@ TalkBack is the Google **screen reader** included on Android devices. TalkBack g
5. Read all the instructions written on the screen as using Talkback requires specific steps.
6. Turn on **Use Service** -> **Allow**
+[Here](https://youtu.be/xpIM9xlowjs) is a video tutorial on "How to use Talkback and what does its output mean?".
+
### Useful Resources
* [Android A11Y Overview](https://support.google.com/accessibility/android/answer/6006564)
* [Using A11Y Menu](https://support.google.com/accessibility/android/answer/9078941)
@@ -89,6 +91,8 @@ TalkBack is the Google **screen reader** included on Android devices. TalkBack g
### Developer Videos
* [How to use Accessibility Scanner? - Tutorial](https://youtu.be/LF5AgGI5H3A)
* [Presentation Slides](https://docs.google.com/presentation/d/1PM_gs3TV2LVKFv6WuF9CUQHWbK7koepAxypzxeZTFzE/edit?usp=sharing)
+* [How to use Talkback and what does its output mean? - Tutorial](https://youtu.be/xpIM9xlowjs)
+ * [Presentation Slides](https://docs.google.com/presentation/d/17SeKJLKT-rUNa_Yupe97bMFSsjTNzp83jX-lZPKEtnQ/edit?usp=sharing)
## Using AccessibilityTestRule in Espresso Tests
[AccessibilityTestRule](https://github.com/oppia/oppia-android/blob/develop/testing/src/main/java/org/oppia/android/testing/AccessibilityTestRule.kt) is a JUnit rule to enable `AccessibilityChecks` in all Espresso Tests. This rule covers all errors shown by Accessibility Scanner and more but only for all those UI elements which are getting used in the test case.
From b643538dc4c0a38796675101da0d048472618a3e Mon Sep 17 00:00:00 2001
From: MOHIT GUPTA <76530270+MohitGupta121@users.noreply.github.com>
Date: Tue, 12 Sep 2023 15:43:40 -0600
Subject: [PATCH 06/34] Fix #3122 : Dark theme make colors of the images
distorted (#5141)
## Explanation
Fix #3122 : Dark theme make the colors of the images distorted
Solution: Images change their color to white when Dark mode is turned
on. That's why we force disabling dark mode for Image Views prevents
android from force-inverting the colors in the images.
## 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
| Before Fix | After Fix |
| ------ | ------ |
| | |
| Before Fix | After Fix |
| ------ | ------ |
| | |
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))
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing
---
.../res/layout/profile_progress_recently_played_story_card.xml | 1 +
app/src/main/res/layout/promoted_story_card.xml | 1 +
app/src/main/res/layout/recently_played_story_card.xml | 1 +
3 files changed, 3 insertions(+)
diff --git a/app/src/main/res/layout/profile_progress_recently_played_story_card.xml b/app/src/main/res/layout/profile_progress_recently_played_story_card.xml
index 78a4576dbdd..5730c5b283e 100755
--- a/app/src/main/res/layout/profile_progress_recently_played_story_card.xml
+++ b/app/src/main/res/layout/profile_progress_recently_played_story_card.xml
@@ -37,6 +37,7 @@
android:importantForAccessibility="no"
app:entityId="@{viewModel.promotedStory.storyId}"
app:entityType="@{viewModel.entityType}"
+ android:forceDarkAllowed="false"
app:layout_constraintDimensionRatio="4:3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
diff --git a/app/src/main/res/layout/promoted_story_card.xml b/app/src/main/res/layout/promoted_story_card.xml
index 739f4bf4b57..91e711e0dae 100755
--- a/app/src/main/res/layout/promoted_story_card.xml
+++ b/app/src/main/res/layout/promoted_story_card.xml
@@ -35,6 +35,7 @@
android:importantForAccessibility="no"
app:entityId="@{viewModel.promotedStory.storyId}"
app:entityType="@{viewModel.entityType}"
+ android:forceDarkAllowed="false"
app:layout_constraintDimensionRatio="H, 16:9"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
diff --git a/app/src/main/res/layout/recently_played_story_card.xml b/app/src/main/res/layout/recently_played_story_card.xml
index 9a85ae3f8c1..6dff08a05de 100755
--- a/app/src/main/res/layout/recently_played_story_card.xml
+++ b/app/src/main/res/layout/recently_played_story_card.xml
@@ -38,6 +38,7 @@
android:importantForAccessibility="no"
app:entityId="@{viewModel.promotedStory.storyId}"
app:entityType="@{viewModel.entityType}"
+ android:forceDarkAllowed="false"
app:layout_constraintDimensionRatio="4:3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
From 89e80325f172c2da7e97f51b2ba3d9e7e5727c9f Mon Sep 17 00:00:00 2001
From: XichengSpencer <74568012+XichengSpencer@users.noreply.github.com>
Date: Fri, 15 Sep 2023 08:08:56 -0400
Subject: [PATCH 07/34] Fix #4790 Talkback will read toolbar title clickable
(#5027)
Fix #4790 For toolbars that have marquee effects, add additional checks
so that the effect will only be enabled when the accessibility service
is not on.
Also updated the existing test for the marquee effect. The test now
checks if the effect is set and activated correctly depending on the
accessibility service status.
Update the test setting to ensure that test behavior is correctly
simulated.
## Explanation
Whenever users use vocal assisting tools such as talkback, the
accessibility service we inject in the field will be enabled. We will
choose either to use a marquee effect for visual display, or just pure
vocal display when the user enables the service.
For a toolbar that doesn't have an individual view for the toolbar
title, setting 'onNavgation..listener' will make the whole toolbar
clickable, and talkback will read "double click.."-
While we want to keep the navigation function, we can use getChildAt(0)
to set the listener to just the nav icon.
## 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
- 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))
Exploration Activity:
- Normal:
https://github.com/oppia/oppia-android/assets/74568012/74f6eaf8-8560-4d1a-bfb4-d378177e31b6
- Talkback On:
https://github.com/oppia/oppia-android/assets/74568012/11285aee-ed5e-4355-97b1-c18df646efd7
Topic Fragment:
- Talkback On:
https://github.com/oppia/oppia-android/assets/74568012/f8cec635-b1c3-4540-afcb-990a42a9a38b
## Issue with Espresso test:
when readerOff, toolbar.title.click() behaves different from manual
test.
- Video record for manual test
Listener function is set and is called when click is performed.
Regardless of title length, is selected will always be modified.
https://github.com/oppia/oppia-android/assets/74568012/7f9a04b6-e3e3-4803-9465-89543b091458
- Video record for espresso test
Listener function is set but not called when click is performed.
The isSelected attribute does not been modified after click
https://github.com/oppia/oppia-android/assets/74568012/c2984b5f-c9fe-4a35-a36f-27d05a935210
## Solution to Solve Error in Espresso Tests.
- Setting the accessibility service before starting the activity solves
accessibility service not correctly set except in TopicFragmentTest.
**Reason** The set listener code in the app executes before setting the
accessibility service in the test.
- Add markSpotlightSeen before the start of the activity.
**Reason** The spotlight might cause the toolbar unable to reach to
simulate a click.
---
.../LicenseTextViewerActivityPresenter.kt | 8 +-
.../ExplorationActivityPresenter.kt | 96 ++++++++------
.../app/story/StoryFragmentPresenter.kt | 22 ++--
.../app/topic/TopicFragmentPresenter.kt | 17 ++-
.../RevisionCardActivityPresenter.kt | 31 +++--
.../exploration/ExplorationActivityTest.kt | 118 ++++++++++++++----
.../android/app/story/StoryFragmentTest.kt | 57 +++++++--
.../LicenseTextViewerActivityTest.kt | 96 +++++++++++++-
.../android/app/topic/TopicFragmentTest.kt | 96 ++++++++++++--
.../revisioncard/RevisionCardActivityTest.kt | 99 ++++++++++++---
10 files changed, 515 insertions(+), 125 deletions(-)
diff --git a/app/src/main/java/org/oppia/android/app/help/thirdparty/LicenseTextViewerActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/help/thirdparty/LicenseTextViewerActivityPresenter.kt
index d4c5c34b262..64ecbf6e897 100644
--- a/app/src/main/java/org/oppia/android/app/help/thirdparty/LicenseTextViewerActivityPresenter.kt
+++ b/app/src/main/java/org/oppia/android/app/help/thirdparty/LicenseTextViewerActivityPresenter.kt
@@ -6,6 +6,7 @@ import org.oppia.android.R
import org.oppia.android.app.activity.ActivityScope
import org.oppia.android.app.translation.AppLanguageResourceHandler
import org.oppia.android.databinding.LicenseTextViewerActivityBinding
+import org.oppia.android.util.accessibility.AccessibilityService
import javax.inject.Inject
/** The presenter for [LicenseTextViewerActivity]. */
@@ -14,6 +15,7 @@ class LicenseTextViewerActivityPresenter @Inject constructor(
private val activity: AppCompatActivity,
private val resourceHandler: AppLanguageResourceHandler
) {
+ @Inject lateinit var accessibilityService: AccessibilityService
/** Handles onCreate() method of the [LicenseTextViewerActivity]. */
fun handleOnCreate(dependencyIndex: Int, licenseIndex: Int) {
@@ -44,8 +46,10 @@ class LicenseTextViewerActivityPresenter @Inject constructor(
(activity as LicenseTextViewerActivity).finish()
}
- binding.licenseTextViewerActivityToolbarTitle.setOnClickListener {
- binding.licenseTextViewerActivityToolbarTitle.isSelected = true
+ if (!accessibilityService.isScreenReaderEnabled()) {
+ binding.licenseTextViewerActivityToolbarTitle.setOnClickListener {
+ binding.licenseTextViewerActivityToolbarTitle.isSelected = true
+ }
}
if (getLicenseTextViewerFragment() == null) {
diff --git a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivityPresenter.kt
index 5d1d0414196..3efadb513de 100644
--- a/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivityPresenter.kt
+++ b/app/src/main/java/org/oppia/android/app/player/exploration/ExplorationActivityPresenter.kt
@@ -38,6 +38,7 @@ import org.oppia.android.domain.exploration.ExplorationDataController
import org.oppia.android.domain.oppialogger.OppiaLogger
import org.oppia.android.domain.survey.SurveyGatingController
import org.oppia.android.domain.translation.TranslationController
+import org.oppia.android.util.accessibility.AccessibilityService
import org.oppia.android.util.data.AsyncResult
import org.oppia.android.util.data.DataProviders.Companion.toLiveData
import javax.inject.Inject
@@ -61,6 +62,9 @@ class ExplorationActivityPresenter @Inject constructor(
private val resourceHandler: AppLanguageResourceHandler,
private val surveyGatingController: SurveyGatingController
) {
+ @Inject
+ lateinit var accessibilityService: AccessibilityService
+
private lateinit var explorationToolbar: Toolbar
private lateinit var explorationToolbarTitle: TextView
private lateinit var profileId: ProfileId
@@ -89,7 +93,7 @@ class ExplorationActivityPresenter @Inject constructor(
parentScreen: ExplorationActivityParams.ParentScreen,
isCheckpointingEnabled: Boolean
) {
- binding = DataBindingUtil.setContentView(
+ binding = DataBindingUtil.setContentView(
activity,
R.layout.exploration_activity
)
@@ -102,8 +106,10 @@ class ExplorationActivityPresenter @Inject constructor(
explorationToolbarTitle = binding.explorationToolbarTitle
activity.setSupportActionBar(explorationToolbar)
- binding.explorationToolbarTitle.setOnClickListener {
- binding.explorationToolbarTitle.isSelected = true
+ if (!accessibilityService.isScreenReaderEnabled()) {
+ binding.explorationToolbarTitle.setOnClickListener {
+ binding.explorationToolbarTitle.isSelected = true
+ }
}
binding.explorationToolbar.setNavigationOnClickListener {
@@ -181,7 +187,11 @@ class ExplorationActivityPresenter @Inject constructor(
activity.supportFragmentManager.beginTransaction().add(
R.id.exploration_fragment_placeholder,
ExplorationFragment.newInstance(
- profileId, topicId, storyId, explorationId, readingTextSize
+ profileId,
+ topicId,
+ storyId,
+ explorationId,
+ readingTextSize
),
TAG_EXPLORATION_FRAGMENT
).commitNow()
@@ -211,7 +221,8 @@ class ExplorationActivityPresenter @Inject constructor(
}
R.id.action_help -> {
val intent = HelpActivity.createHelpActivityIntent(
- activity, profileId.internalId,
+ activity,
+ profileId.internalId,
/* isFromNavigationDrawer= */false
)
fontScaleConfigurationUtil.adjustFontScale(activity, ReadingTextSize.MEDIUM_TEXT_SIZE)
@@ -266,7 +277,8 @@ class ExplorationActivityPresenter @Inject constructor(
// without deleting any checkpoints.
if (::oldestCheckpointExplorationId.isInitialized) {
explorationDataController.deleteExplorationProgressById(
- profileId, oldestCheckpointExplorationId
+ profileId,
+ oldestCheckpointExplorationId
)
}
stopExploration(isCompletion = false)
@@ -340,7 +352,8 @@ class ExplorationActivityPresenter @Inject constructor(
explorationLiveData.observe(activity) {
explorationToolbarTitle.text =
translationController.extractString(
- it.exploration.translatableTitle, it.writtenTranslationContext
+ it.exploration.translatableTitle,
+ it.writtenTranslationContext
)
}
}
@@ -363,7 +376,9 @@ class ExplorationActivityPresenter @Inject constructor(
return when (ephemeralExpResult) {
is AsyncResult.Failure -> {
oppiaLogger.e(
- "ExplorationActivity", "Failed to retrieve answer outcome", ephemeralExpResult.error
+ "ExplorationActivity",
+ "Failed to retrieve answer outcome",
+ ephemeralExpResult.error
)
EphemeralExploration.getDefaultInstance()
}
@@ -472,7 +487,9 @@ class ExplorationActivityPresenter @Inject constructor(
}
is AsyncResult.Failure -> {
oppiaLogger.e(
- "ExplorationActivity", "Failed to retrieve oldest saved checkpoint details.", it.error
+ "ExplorationActivity",
+ "Failed to retrieve oldest saved checkpoint details.",
+ it.error
)
}
is AsyncResult.Pending -> {} // Wait for an actual result.
@@ -512,41 +529,40 @@ class ExplorationActivityPresenter @Inject constructor(
private fun maybeShowSurveyDialog(profileId: ProfileId, topicId: String) {
surveyGatingController.maybeShowSurvey(profileId, topicId).toLiveData()
.observe(
- activity,
- { gatingResult ->
- when (gatingResult) {
- is AsyncResult.Pending -> {
- oppiaLogger.d("ExplorationActivity", "A gating decision is pending")
- }
- is AsyncResult.Failure -> {
- oppiaLogger.e(
- "ExplorationActivity",
- "Failed to retrieve gating decision",
- gatingResult.error
- )
+ activity
+ ) { gatingResult ->
+ when (gatingResult) {
+ is AsyncResult.Pending -> {
+ oppiaLogger.d("ExplorationActivity", "A gating decision is pending")
+ }
+ is AsyncResult.Failure -> {
+ oppiaLogger.e(
+ "ExplorationActivity",
+ "Failed to retrieve gating decision",
+ gatingResult.error
+ )
+ backPressActivitySelector()
+ }
+ is AsyncResult.Success -> {
+ if (gatingResult.value) {
+ val dialogFragment =
+ SurveyWelcomeDialogFragment.newInstance(
+ profileId,
+ topicId,
+ explorationId,
+ SURVEY_QUESTIONS
+ )
+ val transaction = activity.supportFragmentManager.beginTransaction()
+ transaction
+ .add(dialogFragment, TAG_SURVEY_WELCOME_DIALOG)
+ .addToBackStack(null)
+ .commit()
+ } else {
backPressActivitySelector()
}
- is AsyncResult.Success -> {
- if (gatingResult.value) {
- val dialogFragment =
- SurveyWelcomeDialogFragment.newInstance(
- profileId,
- topicId,
- explorationId,
- SURVEY_QUESTIONS
- )
- val transaction = activity.supportFragmentManager.beginTransaction()
- transaction
- .add(dialogFragment, TAG_SURVEY_WELCOME_DIALOG)
- .addToBackStack(null)
- .commit()
- } else {
- backPressActivitySelector()
- }
- }
}
}
- )
+ }
}
companion object {
diff --git a/app/src/main/java/org/oppia/android/app/story/StoryFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/story/StoryFragmentPresenter.kt
index 7ec6ce8317d..2433999b826 100644
--- a/app/src/main/java/org/oppia/android/app/story/StoryFragmentPresenter.kt
+++ b/app/src/main/java/org/oppia/android/app/story/StoryFragmentPresenter.kt
@@ -65,16 +65,17 @@ class StoryFragmentPresenter @Inject constructor(
private lateinit var linearSmoothScroller: RecyclerView.SmoothScroller
private lateinit var profileId: ProfileId
- @Inject lateinit var storyViewModel: StoryViewModel
@Inject lateinit var accessibilityService: AccessibilityService
+ @Inject lateinit var storyViewModel: StoryViewModel
+
fun handleCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
internalProfileId: Int,
topicId: String,
storyId: String
- ): View? {
+ ): View {
binding = StoryFragmentBinding.inflate(
inflater,
container,
@@ -89,9 +90,10 @@ class StoryFragmentPresenter @Inject constructor(
binding.storyToolbar.setNavigationOnClickListener {
(activity as StoryActivity).finish()
}
-
- binding.storyToolbarTitle.setOnClickListener {
- binding.storyToolbarTitle.isSelected = true
+ if (!accessibilityService.isScreenReaderEnabled()) {
+ binding.storyToolbarTitle.setOnClickListener {
+ binding.storyToolbarTitle.isSelected = true
+ }
}
linearLayoutManager = LinearLayoutManager(activity.applicationContext)
@@ -274,11 +276,17 @@ class StoryFragmentPresenter @Inject constructor(
// one.
val startPlayingProvider = if (canHavePartialProgressSaved) {
explorationDataController.startPlayingNewExploration(
- profileId.internalId, topicId, storyId, explorationId
+ profileId.internalId,
+ topicId,
+ storyId,
+ explorationId
)
} else {
explorationDataController.replayExploration(
- profileId.internalId, topicId, storyId, explorationId
+ profileId.internalId,
+ topicId,
+ storyId,
+ explorationId
)
}
startPlayingProvider.toLiveData().observe(fragment) { result ->
diff --git a/app/src/main/java/org/oppia/android/app/topic/TopicFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/topic/TopicFragmentPresenter.kt
index b94b7db6029..b7bb9548635 100644
--- a/app/src/main/java/org/oppia/android/app/topic/TopicFragmentPresenter.kt
+++ b/app/src/main/java/org/oppia/android/app/topic/TopicFragmentPresenter.kt
@@ -20,6 +20,7 @@ import org.oppia.android.app.translation.AppLanguageResourceHandler
import org.oppia.android.databinding.TopicFragmentBinding
import org.oppia.android.domain.oppialogger.OppiaLogger
import org.oppia.android.domain.oppialogger.analytics.AnalyticsController
+import org.oppia.android.util.accessibility.AccessibilityService
import org.oppia.android.util.platformparameter.EnableExtraTopicTabsUi
import org.oppia.android.util.platformparameter.PlatformParameterValue
import javax.inject.Inject
@@ -35,6 +36,9 @@ class TopicFragmentPresenter @Inject constructor(
@EnableExtraTopicTabsUi private val enableExtraTopicTabsUi: PlatformParameterValue,
private val resourceHandler: AppLanguageResourceHandler
) {
+ @Inject
+ lateinit var accessibilityService: AccessibilityService
+
private lateinit var tabLayout: TabLayout
private var internalProfileId: Int = -1
private lateinit var topicId: String
@@ -48,7 +52,7 @@ class TopicFragmentPresenter @Inject constructor(
topicId: String,
storyId: String,
isConfigChanged: Boolean
- ): View? {
+ ): View {
val binding = TopicFragmentBinding.inflate(
inflater,
container,
@@ -64,11 +68,11 @@ class TopicFragmentPresenter @Inject constructor(
binding.topicToolbar.setNavigationOnClickListener {
(activity as TopicActivity).finish()
}
-
- binding.topicToolbar.setOnClickListener {
- binding.topicToolbarTitle.isSelected = true
+ if (!accessibilityService.isScreenReaderEnabled()) {
+ binding.topicToolbarTitle.setOnClickListener {
+ binding.topicToolbarTitle.isSelected = true
+ }
}
-
viewModel.setInternalProfileId(internalProfileId)
viewModel.setTopicId(topicId)
binding.viewModel = viewModel
@@ -152,7 +156,8 @@ class TopicFragmentPresenter @Inject constructor(
TopicTab.REVISION -> oppiaLogger.createOpenRevisionTabContext(topicId)
}
analyticsController.logImportantEvent(
- eventContext, ProfileId.newBuilder().apply { internalId = internalProfileId }.build()
+ eventContext,
+ ProfileId.newBuilder().apply { internalId = internalProfileId }.build()
)
}
}
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 0a1fd1b287f..62f5b68f886 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
@@ -5,7 +5,6 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.LiveData
-import androidx.lifecycle.Observer
import androidx.lifecycle.Transformations
import org.oppia.android.R
import org.oppia.android.app.activity.ActivityScope
@@ -19,6 +18,7 @@ import org.oppia.android.domain.oppialogger.OppiaLogger
import org.oppia.android.domain.oppialogger.analytics.AnalyticsController
import org.oppia.android.domain.topic.TopicController
import org.oppia.android.domain.translation.TranslationController
+import org.oppia.android.util.accessibility.AccessibilityService
import org.oppia.android.util.data.AsyncResult
import org.oppia.android.util.data.DataProviders.Companion.toLiveData
import javax.inject.Inject
@@ -32,6 +32,7 @@ class RevisionCardActivityPresenter @Inject constructor(
private val topicController: TopicController,
private val translationController: TranslationController
) {
+ @Inject lateinit var accessibilityService: AccessibilityService
private lateinit var revisionCardToolbar: Toolbar
private lateinit var revisionCardToolbarTitle: TextView
@@ -66,9 +67,12 @@ class RevisionCardActivityPresenter @Inject constructor(
binding.revisionCardToolbar.setNavigationOnClickListener {
(activity as ReturnToTopicClickListener).onReturnToTopicRequested()
}
- binding.revisionCardToolbarTitle.setOnClickListener {
- binding.revisionCardToolbarTitle.isSelected = true
+ if (!accessibilityService.isScreenReaderEnabled()) {
+ binding.revisionCardToolbarTitle.setOnClickListener {
+ binding.revisionCardToolbarTitle.isSelected = true
+ }
}
+
subscribeToSubtopicTitle()
binding.actionBottomSheetOptionsMenu.setOnClickListener {
@@ -89,14 +93,18 @@ class RevisionCardActivityPresenter @Inject constructor(
return when (itemId) {
R.id.action_options -> {
val intent = OptionsActivity.createOptionsActivity(
- activity, profileId.internalId, isFromNavigationDrawer = false
+ activity,
+ profileId.internalId,
+ isFromNavigationDrawer = false
)
activity.startActivity(intent)
true
}
R.id.action_help -> {
val intent = HelpActivity.createHelpActivityIntent(
- activity, profileId.internalId, isFromNavigationDrawer = false
+ activity,
+ profileId.internalId,
+ isFromNavigationDrawer = false
)
activity.startActivity(intent)
true
@@ -117,11 +125,10 @@ class RevisionCardActivityPresenter @Inject constructor(
private fun subscribeToSubtopicTitle() {
subtopicLiveData.observe(
- activity,
- Observer {
- revisionCardToolbarTitle.text = it
- }
- )
+ activity
+ ) {
+ revisionCardToolbarTitle.text = it
+ }
}
private val subtopicLiveData: LiveData by lazy {
@@ -143,7 +150,9 @@ class RevisionCardActivityPresenter @Inject constructor(
when (revisionCardResult) {
is AsyncResult.Failure -> {
oppiaLogger.e(
- "RevisionCardActivity", "Failed to retrieve Revision Card", revisionCardResult.error
+ "RevisionCardActivity",
+ "Failed to retrieve Revision Card",
+ revisionCardResult.error
)
EphemeralRevisionCard.getDefaultInstance()
}
diff --git a/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt
index a8c1bea4d8c..bb97f37ed2c 100644
--- a/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt
+++ b/app/src/sharedTest/java/org/oppia/android/app/player/exploration/ExplorationActivityTest.kt
@@ -265,7 +265,9 @@ class ExplorationActivityTest {
// TODO(#388): Fill in remaining tests for this activity.
@get:Rule
var explorationActivityTestRule: ActivityTestRule = ActivityTestRule(
- ExplorationActivity::class.java, /* initialTouchMode= */ true, /* launchActivity= */ false
+ ExplorationActivity::class.java, /* initialTouchMode= */
+ true, /* launchActivity= */
+ false
)
@Test
@@ -325,8 +327,9 @@ class ExplorationActivityTest {
}
@Test
- fun testExploration_toolbarTitle_marqueeInRtl_isDisplayedCorrectly() {
+ fun testExploration_toolbarTitle_readerOff_marqueeInRtl_isDisplayedCorrectly() {
markAllSpotlightsSeen()
+ fakeAccessibilityService.setScreenReaderEnabled(false)
explorationActivityTestRule.launchActivity(
createExplorationActivityIntent(
internalProfileId,
@@ -342,12 +345,37 @@ class ExplorationActivityTest {
onView(withId(R.id.exploration_toolbar_title)).perform(click())
assertThat(explorationToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(explorationToolbarTitle.isSelected).isEqualTo(true)
assertThat(explorationToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
}
@Test
- fun testExploration_toolbarTitle_marqueeInLtr_isDisplayedCorrectly() {
+ fun testExploration_toolbarTitle_readerOn_marqueeInRtl_isDisplayedCorrectly() {
markAllSpotlightsSeen()
+ fakeAccessibilityService.setScreenReaderEnabled(true)
+ explorationActivityTestRule.launchActivity(
+ createExplorationActivityIntent(
+ internalProfileId,
+ TEST_TOPIC_ID_0,
+ TEST_STORY_ID_0,
+ TEST_EXPLORATION_ID_2,
+ shouldSavePartialProgress = false
+ )
+ )
+ val explorationToolbarTitle: TextView =
+ explorationActivityTestRule.activity.findViewById(R.id.exploration_toolbar_title)
+ ViewCompat.setLayoutDirection(explorationToolbarTitle, ViewCompat.LAYOUT_DIRECTION_RTL)
+
+ onView(withId(R.id.exploration_toolbar_title)).perform(click())
+ assertThat(explorationToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(explorationToolbarTitle.isSelected).isEqualTo(false)
+ assertThat(explorationToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
+ }
+
+ @Test
+ fun testExploration_toolbarTitle_readerOff_marqueeInLtr_isDisplayedCorrectly() {
+ markAllSpotlightsSeen()
+ fakeAccessibilityService.setScreenReaderEnabled(false)
explorationActivityTestRule.launchActivity(
createExplorationActivityIntent(
internalProfileId,
@@ -362,10 +390,34 @@ class ExplorationActivityTest {
ViewCompat.setLayoutDirection(explorationToolbarTitle, ViewCompat.LAYOUT_DIRECTION_LTR)
onView(withId(R.id.exploration_toolbar_title)).perform(click())
+ assertThat(explorationToolbarTitle.isSelected).isEqualTo(true)
assertThat(explorationToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
assertThat(explorationToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
}
+ @Test
+ fun testExploration_toolbarTitle_readerOn_marqueeInLtr_isDisplayedCorrectly() {
+ markAllSpotlightsSeen()
+ fakeAccessibilityService.setScreenReaderEnabled(true)
+ explorationActivityTestRule.launchActivity(
+ createExplorationActivityIntent(
+ internalProfileId,
+ TEST_TOPIC_ID_0,
+ TEST_STORY_ID_0,
+ TEST_EXPLORATION_ID_2,
+ shouldSavePartialProgress = false
+ )
+ )
+ val explorationToolbarTitle: TextView =
+ explorationActivityTestRule.activity.findViewById(R.id.exploration_toolbar_title)
+ ViewCompat.setLayoutDirection(explorationToolbarTitle, ViewCompat.LAYOUT_DIRECTION_LTR)
+
+ onView(withId(R.id.exploration_toolbar_title)).perform(click())
+ assertThat(explorationToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(explorationToolbarTitle.isSelected).isEqualTo(false)
+ assertThat(explorationToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
+ }
+
@Test
fun testExploration_configurationChange_toolbarTitle_isDisplayedSuccessfully() {
launch(
@@ -801,8 +853,10 @@ class ExplorationActivityTest {
setUpAudio()
launch(
createExplorationActivityIntent(
- internalProfileId, RATIOS_TOPIC_ID,
- RATIOS_STORY_ID_0, RATIOS_EXPLORATION_ID_0,
+ internalProfileId,
+ RATIOS_TOPIC_ID,
+ RATIOS_STORY_ID_0,
+ RATIOS_EXPLORATION_ID_0,
shouldSavePartialProgress = false
)
).use {
@@ -828,8 +882,10 @@ class ExplorationActivityTest {
setUpAudio()
launch(
createExplorationActivityIntent(
- internalProfileId, RATIOS_TOPIC_ID,
- RATIOS_STORY_ID_0, RATIOS_EXPLORATION_ID_0,
+ internalProfileId,
+ RATIOS_TOPIC_ID,
+ RATIOS_STORY_ID_0,
+ RATIOS_EXPLORATION_ID_0,
shouldSavePartialProgress = false
)
).use {
@@ -856,8 +912,10 @@ class ExplorationActivityTest {
setUpAudio()
launch(
createExplorationActivityIntent(
- internalProfileId, RATIOS_TOPIC_ID,
- RATIOS_STORY_ID_0, RATIOS_EXPLORATION_ID_0,
+ internalProfileId,
+ RATIOS_TOPIC_ID,
+ RATIOS_STORY_ID_0,
+ RATIOS_EXPLORATION_ID_0,
shouldSavePartialProgress = false
)
).use {
@@ -939,8 +997,10 @@ class ExplorationActivityTest {
setUpAudio()
launch(
createExplorationActivityIntent(
- internalProfileId, RATIOS_TOPIC_ID,
- RATIOS_STORY_ID_0, RATIOS_EXPLORATION_ID_0,
+ internalProfileId,
+ RATIOS_TOPIC_ID,
+ RATIOS_STORY_ID_0,
+ RATIOS_EXPLORATION_ID_0,
shouldSavePartialProgress = false
)
).use {
@@ -980,8 +1040,10 @@ class ExplorationActivityTest {
setUpAudio()
launch(
createExplorationActivityIntent(
- internalProfileId, RATIOS_TOPIC_ID,
- RATIOS_STORY_ID_0, RATIOS_EXPLORATION_ID_0,
+ internalProfileId,
+ RATIOS_TOPIC_ID,
+ RATIOS_STORY_ID_0,
+ RATIOS_EXPLORATION_ID_0,
shouldSavePartialProgress = false
)
).use {
@@ -1131,8 +1193,10 @@ class ExplorationActivityTest {
networkConnectionUtil.setCurrentConnectionStatus(ProdConnectionStatus.LOCAL)
launch(
createExplorationActivityIntent(
- internalProfileId, RATIOS_TOPIC_ID,
- RATIOS_STORY_ID_0, RATIOS_EXPLORATION_ID_0,
+ internalProfileId,
+ RATIOS_TOPIC_ID,
+ RATIOS_STORY_ID_0,
+ RATIOS_EXPLORATION_ID_0,
shouldSavePartialProgress = false
)
).use {
@@ -2071,7 +2135,7 @@ class ExplorationActivityTest {
internalProfileId,
TEST_TOPIC_ID_0,
TEST_STORY_ID_0,
- TEST_EXPLORATION_ID_2,
+ TEST_EXPLORATION_ID_2
)
testCoroutineDispatchers.runCurrent()
onView(withId(R.id.action_bottom_sheet_options_menu)).perform(click())
@@ -2131,7 +2195,7 @@ class ExplorationActivityTest {
internalProfileId,
TEST_TOPIC_ID_0,
TEST_STORY_ID_0,
- TEST_EXPLORATION_ID_2,
+ TEST_EXPLORATION_ID_2
)
testCoroutineDispatchers.runCurrent()
onView(withId(R.id.action_bottom_sheet_options_menu)).perform(click())
@@ -2165,7 +2229,7 @@ class ExplorationActivityTest {
internalProfileId,
TEST_TOPIC_ID_0,
TEST_STORY_ID_0,
- TEST_EXPLORATION_ID_2,
+ TEST_EXPLORATION_ID_2
)
testCoroutineDispatchers.runCurrent()
onView(withId(R.id.action_bottom_sheet_options_menu)).perform(click())
@@ -2219,7 +2283,8 @@ class ExplorationActivityTest {
// Espresso can't load Robolectric into its classpath).
if (isOnRobolectric()) {
val dataSource = createAudioDataSource(
- explorationId = RATIOS_EXPLORATION_ID_0, audioFileName = "content-en-057j51i2es.mp3"
+ explorationId = RATIOS_EXPLORATION_ID_0,
+ audioFileName = "content-en-057j51i2es.mp3"
)
addShadowMediaPlayerException(dataSource!!, IOException("Test does not have networking"))
}
@@ -2230,10 +2295,12 @@ class ExplorationActivityTest {
// Espresso can't load Robolectric into its classpath).
if (isOnRobolectric()) {
val dataSource = createAudioDataSource(
- explorationId = FRACTIONS_EXPLORATION_ID_0, audioFileName = "content-en-nb3k4zuyir.mp3"
+ explorationId = FRACTIONS_EXPLORATION_ID_0,
+ audioFileName = "content-en-nb3k4zuyir.mp3"
)
val dataSource2 = createAudioDataSource(
- explorationId = FRACTIONS_EXPLORATION_ID_0, audioFileName = "content-hi-en-l8ik9pdxj2a.mp3"
+ explorationId = FRACTIONS_EXPLORATION_ID_0,
+ audioFileName = "content-hi-en-l8ik9pdxj2a.mp3"
)
addShadowMediaPlayerException(dataSource!!, IOException("Test does not have networking"))
addShadowMediaPlayerException(dataSource2!!, IOException("Test does not have networking"))
@@ -2245,7 +2312,9 @@ class ExplorationActivityTest {
val shadowMediaPlayerClass = classLoader.loadClass("org.robolectric.shadows.ShadowMediaPlayer")
val addException =
shadowMediaPlayerClass.getDeclaredMethod(
- "addException", dataSource.javaClass, IOException::class.java
+ "addException",
+ dataSource.javaClass,
+ IOException::class.java
)
addException.invoke(/* obj= */ null, dataSource, exception)
}
@@ -2261,7 +2330,9 @@ class ExplorationActivityTest {
val dataSourceClass = classLoader.loadClass("org.robolectric.shadows.util.DataSource")
val toDataSource =
dataSourceClass.getDeclaredMethod(
- "toDataSource", String::class.java, Map::class.java
+ "toDataSource",
+ String::class.java,
+ Map::class.java
)
return toDataSource.invoke(/* obj= */ null, audioUrl, /* headers= */ null)
}
@@ -2426,7 +2497,6 @@ class ExplorationActivityTest {
CpuPerformanceSnapshotterModule::class, ExplorationProgressModule::class
]
)
-
interface TestApplicationComponent : ApplicationComponent {
@Component.Builder
interface Builder : ApplicationComponent.Builder
diff --git a/app/src/sharedTest/java/org/oppia/android/app/story/StoryFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/story/StoryFragmentTest.kt
index 56cf2a883ea..21202b8915d 100644
--- a/app/src/sharedTest/java/org/oppia/android/app/story/StoryFragmentTest.kt
+++ b/app/src/sharedTest/java/org/oppia/android/app/story/StoryFragmentTest.kt
@@ -186,7 +186,9 @@ class StoryFragmentTest {
@get:Rule
var activityTestRule: ActivityTestRule = ActivityTestRule(
- StoryActivity::class.java, /* initialTouchMode= */ true, /* launchActivity= */ false
+ StoryActivity::class.java, /* initialTouchMode= */
+ true, /* launchActivity= */
+ false
)
private val internalProfileId = 0
@@ -227,9 +229,27 @@ class StoryFragmentTest {
}
}
- @Test // TODO(#4212): Error -> Only the original thread that created a view hierarchy can touch
- // its view
- fun testStoryFragment_toolbarTitle_marqueeInRtl_isDisplayedCorrectly() {
+ // TODO(#4212): Error -> Only the original thread that created a view hierarchy can touch its view
+ @Test
+ fun testStoryFragment_toolbarTitle_readerOff_marqueeInRtl_isDisplayedCorrectly() {
+ accessibilityService.setScreenReaderEnabled(false)
+ activityTestRule.launchActivity(createFractionsStoryActivityIntent())
+ testCoroutineDispatchers.runCurrent()
+
+ val storyToolbarTitle: TextView =
+ activityTestRule.activity.findViewById(R.id.story_toolbar_title)
+ ViewCompat.setLayoutDirection(storyToolbarTitle, ViewCompat.LAYOUT_DIRECTION_RTL)
+
+ onView(withId(R.id.story_toolbar_title)).perform(click())
+ assertThat(storyToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(storyToolbarTitle.isSelected).isEqualTo(true)
+ assertThat(storyToolbarTitle.textAlignment).isEqualTo(TEXT_ALIGNMENT_VIEW_START)
+ }
+
+ // TODO(#4212): Error -> Only the original thread that created a view hierarchy can touch its view
+ @Test
+ fun testStoryFragment_toolbarTitle_readerOn_marqueeInRtl_isDisplayedCorrectly() {
+ accessibilityService.setScreenReaderEnabled(true)
activityTestRule.launchActivity(createFractionsStoryActivityIntent())
testCoroutineDispatchers.runCurrent()
@@ -239,12 +259,30 @@ class StoryFragmentTest {
onView(withId(R.id.story_toolbar_title)).perform(click())
assertThat(storyToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(storyToolbarTitle.isSelected).isEqualTo(false)
assertThat(storyToolbarTitle.textAlignment).isEqualTo(TEXT_ALIGNMENT_VIEW_START)
}
- @Test // TODO(#4212): Error -> Only the original thread that created a view hierarchy can touch
- // its view
- fun testStoryFragment_toolbarTitle_marqueeInLtr_isDisplayedCorrectly() {
+ // TODO(#4212): Error -> Only the original thread that created a view hierarchy can touch its view
+ @Test
+ fun testStoryFragment_toolbarTitle_readerOff_marqueeInLtr_isDisplayedCorrectly() {
+ accessibilityService.setScreenReaderEnabled(false)
+ activityTestRule.launchActivity(createFractionsStoryActivityIntent())
+ testCoroutineDispatchers.runCurrent()
+
+ val storyToolbarTitle: TextView =
+ activityTestRule.activity.findViewById(R.id.story_toolbar_title)
+ ViewCompat.setLayoutDirection(storyToolbarTitle, ViewCompat.LAYOUT_DIRECTION_LTR)
+ onView(withId(R.id.story_toolbar_title)).perform(click())
+ assertThat(storyToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(storyToolbarTitle.isSelected).isEqualTo(true)
+ assertThat(storyToolbarTitle.textAlignment).isEqualTo(TEXT_ALIGNMENT_VIEW_START)
+ }
+
+ // TODO(#4212): Error -> Only the original thread that created a view hierarchy can touch its view
+ @Test
+ fun testStoryFragment_toolbarTitle_readerOn_marqueeInLtr_isDisplayedCorrectly() {
+ accessibilityService.setScreenReaderEnabled(true)
activityTestRule.launchActivity(createFractionsStoryActivityIntent())
testCoroutineDispatchers.runCurrent()
@@ -254,6 +292,7 @@ class StoryFragmentTest {
onView(withId(R.id.story_toolbar_title)).perform(click())
assertThat(storyToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(storyToolbarTitle.isSelected).isEqualTo(false)
assertThat(storyToolbarTitle.textAlignment).isEqualTo(TEXT_ALIGNMENT_VIEW_START)
}
@@ -877,7 +916,9 @@ class StoryFragmentTest {
private fun TextView.getClickableSpans(): List> {
val viewText = text
return (viewText as Spannable).getSpans(
- /* start= */ 0, /* end= */ text.length, ClickableSpan::class.java
+ /* start= */ 0, /* end= */
+ text.length,
+ ClickableSpan::class.java
).map {
viewText.subSequence(viewText.getSpanStart(it), viewText.getSpanEnd(it)).toString() to it
}
diff --git a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseTextViewerActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseTextViewerActivityTest.kt
index c0a51d20a14..93dc07a0ade 100644
--- a/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseTextViewerActivityTest.kt
+++ b/app/src/sharedTest/java/org/oppia/android/app/thirdparty/LicenseTextViewerActivityTest.kt
@@ -3,8 +3,15 @@ package org.oppia.android.app.thirdparty
import android.app.Application
import android.content.Context
import android.content.Intent
+import android.text.TextUtils
+import android.view.View
+import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.ViewCompat
import androidx.test.core.app.ApplicationProvider
+import androidx.test.espresso.Espresso
+import androidx.test.espresso.action.ViewActions
+import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.ActivityTestRule
import com.google.common.truth.Truth.assertThat
@@ -70,6 +77,7 @@ import org.oppia.android.testing.robolectric.RobolectricModule
import org.oppia.android.testing.threading.TestDispatcherModule
import org.oppia.android.testing.time.FakeOppiaClockModule
import org.oppia.android.util.accessibility.AccessibilityTestModule
+import org.oppia.android.util.accessibility.FakeAccessibilityService
import org.oppia.android.util.caching.AssetModule
import org.oppia.android.util.caching.testing.CachingTestModule
import org.oppia.android.util.gcsresource.GcsResourceModule
@@ -110,6 +118,9 @@ class LicenseTextViewerActivityTest {
/* launchActivity= */ false
)
+ @Inject
+ lateinit var fakeAccessibilityService: FakeAccessibilityService
+
@Inject
lateinit var context: Context
@@ -145,6 +156,90 @@ class LicenseTextViewerActivityTest {
)
}
+ @Test
+ fun testExploration_toolbarTitle_readerOff_marqueeInRtl_isDisplayedCorrectly() {
+ fakeAccessibilityService.setScreenReaderEnabled(false)
+ activityTestRule.launchActivity(
+ createLicenseTextViewerActivityIntent(
+ dependencyIndex = 0,
+ licenseIndex = 0
+ )
+ )
+
+ val activityToolbarTitle: TextView =
+ activityTestRule.activity.findViewById(R.id.license_text_viewer_activity_toolbar_title)
+ ViewCompat.setLayoutDirection(activityToolbarTitle, ViewCompat.LAYOUT_DIRECTION_RTL)
+
+ Espresso.onView(ViewMatchers.withId(R.id.license_text_viewer_activity_toolbar_title))
+ .perform(ViewActions.click())
+ assertThat(activityToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(activityToolbarTitle.isSelected).isEqualTo(true)
+ assertThat(activityToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
+ }
+
+ @Test
+ fun testExploration_toolbarTitle_readerOn_marqueeInRtl_isDisplayedCorrectly() {
+ fakeAccessibilityService.setScreenReaderEnabled(true)
+ activityTestRule.launchActivity(
+ createLicenseTextViewerActivityIntent(
+ dependencyIndex = 0,
+ licenseIndex = 0
+ )
+ )
+
+ val activityToolbarTitle: TextView =
+ activityTestRule.activity.findViewById(R.id.license_text_viewer_activity_toolbar_title)
+ ViewCompat.setLayoutDirection(activityToolbarTitle, ViewCompat.LAYOUT_DIRECTION_RTL)
+
+ Espresso.onView(ViewMatchers.withId(R.id.license_text_viewer_activity_toolbar_title))
+ .perform(ViewActions.click())
+ assertThat(activityToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(activityToolbarTitle.isSelected).isEqualTo(false)
+ assertThat(activityToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
+ }
+
+ @Test
+ fun testExploration_toolbarTitle_readerOff_marqueeInLtr_isDisplayedCorrectly() {
+ fakeAccessibilityService.setScreenReaderEnabled(false)
+ activityTestRule.launchActivity(
+ createLicenseTextViewerActivityIntent(
+ dependencyIndex = 0,
+ licenseIndex = 0
+ )
+ )
+
+ val activityToolbarTitle: TextView =
+ activityTestRule.activity.findViewById(R.id.license_text_viewer_activity_toolbar_title)
+ ViewCompat.setLayoutDirection(activityToolbarTitle, ViewCompat.LAYOUT_DIRECTION_LTR)
+
+ Espresso.onView(ViewMatchers.withId(R.id.license_text_viewer_activity_toolbar_title))
+ .perform(ViewActions.click())
+ assertThat(activityToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(activityToolbarTitle.isSelected).isEqualTo(true)
+ assertThat(activityToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
+ }
+
+ @Test
+ fun testExploration_toolbarTitle_readerOn_marqueeInLtr_isDisplayedCorrectly() {
+ fakeAccessibilityService.setScreenReaderEnabled(true)
+ activityTestRule.launchActivity(
+ createLicenseTextViewerActivityIntent(
+ dependencyIndex = 0,
+ licenseIndex = 0
+ )
+ )
+
+ val activityToolbarTitle: TextView =
+ activityTestRule.activity.findViewById(R.id.license_text_viewer_activity_toolbar_title)
+ ViewCompat.setLayoutDirection(activityToolbarTitle, ViewCompat.LAYOUT_DIRECTION_LTR)
+
+ Espresso.onView(ViewMatchers.withId(R.id.license_text_viewer_activity_toolbar_title))
+ .perform(ViewActions.click())
+ assertThat(activityToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(activityToolbarTitle.isSelected).isEqualTo(false)
+ assertThat(activityToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
+ }
+
private fun setUpTestApplicationComponent() {
ApplicationProvider.getApplicationContext().inject(this)
}
@@ -191,7 +286,6 @@ class LicenseTextViewerActivityTest {
CpuPerformanceSnapshotterModule::class, ExplorationProgressModule::class
]
)
-
interface TestApplicationComponent : ApplicationComponent {
@Component.Builder
diff --git a/app/src/sharedTest/java/org/oppia/android/app/topic/TopicFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/topic/TopicFragmentTest.kt
index b9b565bb011..333cab9044e 100644
--- a/app/src/sharedTest/java/org/oppia/android/app/topic/TopicFragmentTest.kt
+++ b/app/src/sharedTest/java/org/oppia/android/app/topic/TopicFragmentTest.kt
@@ -105,6 +105,7 @@ import org.oppia.android.testing.threading.TestDispatcherModule
import org.oppia.android.testing.time.FakeOppiaClock
import org.oppia.android.testing.time.FakeOppiaClockModule
import org.oppia.android.util.accessibility.AccessibilityTestModule
+import org.oppia.android.util.accessibility.FakeAccessibilityService
import org.oppia.android.util.caching.AssetModule
import org.oppia.android.util.caching.testing.CachingTestModule
import org.oppia.android.util.gcsresource.GcsResourceModule
@@ -142,19 +143,36 @@ private const val REVISION_TAB_POSITION_EXTRA_TABS_DISABLED = 1
qualifiers = "port-xxhdpi"
)
class TopicFragmentTest {
- @get:Rule val initializeDefaultLocaleRule = InitializeDefaultLocaleRule()
- @get:Rule val oppiaTestRule = OppiaTestRule()
+ @get:Rule
+ val initializeDefaultLocaleRule = InitializeDefaultLocaleRule()
+
+ @get:Rule
+ val oppiaTestRule = OppiaTestRule()
@get:Rule
var activityTestRule: ActivityTestRule = ActivityTestRule(
- TopicActivity::class.java, /* initialTouchMode= */ true, /* launchActivity= */ false
+ TopicActivity::class.java, /* initialTouchMode= */
+ true, /* launchActivity= */
+ false
)
- @Inject lateinit var testCoroutineDispatchers: TestCoroutineDispatchers
- @Inject lateinit var spotlightStateController: SpotlightStateController
- @Inject lateinit var fakeOppiaClock: FakeOppiaClock
- @Inject lateinit var storyProgressTestHelper: StoryProgressTestHelper
- @Inject lateinit var fakeAnalyticsEventLogger: FakeAnalyticsEventLogger
+ @Inject
+ lateinit var testCoroutineDispatchers: TestCoroutineDispatchers
+
+ @Inject
+ lateinit var spotlightStateController: SpotlightStateController
+
+ @Inject
+ lateinit var fakeOppiaClock: FakeOppiaClock
+
+ @Inject
+ lateinit var storyProgressTestHelper: StoryProgressTestHelper
+
+ @Inject
+ lateinit var fakeAnalyticsEventLogger: FakeAnalyticsEventLogger
+
+ @Inject
+ lateinit var fakeAccessibilityService: FakeAccessibilityService
@field:[Inject EnableExtraTopicTabsUi]
lateinit var enableExtraTopicTabsUi: PlatformParameterValue
@@ -315,8 +333,10 @@ class TopicFragmentTest {
}
@Test
- fun testTopicFragment_toolbarTitle_marqueeInRtl_isDisplayedCorrectly() {
+ fun testTopicFragment_toolbarTitle_readerOff_marqueeInRtl_isDisplayedCorrectly() {
initializeApplicationComponent(false)
+ markSpotlightSeen(TOPIC_LESSON_TAB)
+ fakeAccessibilityService.setScreenReaderEnabled(false)
activityTestRule.launchActivity(
createTopicActivityIntent(
internalProfileId,
@@ -330,12 +350,58 @@ class TopicFragmentTest {
onView(withId(R.id.topic_toolbar_title)).perform(click())
assertThat(topicToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(topicToolbarTitle.isSelected).isEqualTo(true)
assertThat(topicToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
}
@Test
- fun testTopicFragment_toolbarTitle_marqueeInLtr_isDisplayedCorrectly() {
+ fun testTopicFragment_toolbarTitle_readerOn_marqueeInRtl_isDisplayedCorrectly() {
initializeApplicationComponent(false)
+ markSpotlightSeen(TOPIC_LESSON_TAB)
+ fakeAccessibilityService.setScreenReaderEnabled(true)
+ activityTestRule.launchActivity(
+ createTopicActivityIntent(
+ internalProfileId,
+ FRACTIONS_TOPIC_ID
+ )
+ )
+ testCoroutineDispatchers.runCurrent()
+ val topicToolbarTitle: TextView =
+ activityTestRule.activity.findViewById(R.id.topic_toolbar_title)
+ ViewCompat.setLayoutDirection(topicToolbarTitle, ViewCompat.LAYOUT_DIRECTION_RTL)
+
+ onView(withId(R.id.topic_toolbar_title)).perform(click())
+ assertThat(topicToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(topicToolbarTitle.isSelected).isEqualTo(false)
+ assertThat(topicToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
+ }
+
+ @Test
+ fun testTopicFragment_toolbarTitle_readerOff_marqueeInLtr_isDisplayedCorrectly() {
+ initializeApplicationComponent(false)
+ markSpotlightSeen(TOPIC_LESSON_TAB)
+ fakeAccessibilityService.setScreenReaderEnabled(false)
+ activityTestRule.launchActivity(
+ createTopicActivityIntent(
+ internalProfileId,
+ FRACTIONS_TOPIC_ID
+ )
+ )
+ testCoroutineDispatchers.runCurrent()
+ val topicToolbarTitle: TextView =
+ activityTestRule.activity.findViewById(R.id.topic_toolbar_title)
+ ViewCompat.setLayoutDirection(topicToolbarTitle, ViewCompat.LAYOUT_DIRECTION_LTR)
+ onView(withId(R.id.topic_toolbar_title)).perform(click())
+ assertThat(topicToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(topicToolbarTitle.isSelected).isEqualTo(true)
+ assertThat(topicToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
+ }
+
+ @Test
+ fun testTopicFragment_toolbarTitle_readerOn_marqueeInLtr_isDisplayedCorrectly() {
+ initializeApplicationComponent(false)
+ markSpotlightSeen(TOPIC_LESSON_TAB)
+ fakeAccessibilityService.setScreenReaderEnabled(true)
activityTestRule.launchActivity(
createTopicActivityIntent(
internalProfileId,
@@ -348,6 +414,7 @@ class TopicFragmentTest {
ViewCompat.setLayoutDirection(topicToolbarTitle, ViewCompat.LAYOUT_DIRECTION_LTR)
onView(withId(R.id.topic_toolbar_title)).perform(click())
assertThat(topicToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(topicToolbarTitle.isSelected).isEqualTo(false)
assertThat(topicToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
}
@@ -812,7 +879,9 @@ class TopicFragmentTest {
*/
private fun createTopicActivityIntent(internalProfileId: Int, topicId: String): Intent {
return TopicActivity.createTopicActivityIntent(
- ApplicationProvider.getApplicationContext(), internalProfileId, topicId
+ ApplicationProvider.getApplicationContext(),
+ internalProfileId,
+ topicId
)
}
@@ -827,7 +896,10 @@ class TopicFragmentTest {
storyId: String
): Intent {
return TopicActivity.createTopicPlayStoryActivityIntent(
- ApplicationProvider.getApplicationContext(), internalProfileId, topicId, storyId
+ ApplicationProvider.getApplicationContext(),
+ internalProfileId,
+ topicId,
+ storyId
)
}
diff --git a/app/src/sharedTest/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityTest.kt b/app/src/sharedTest/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityTest.kt
index 19fff7196b7..d28d3428aa9 100644
--- a/app/src/sharedTest/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityTest.kt
+++ b/app/src/sharedTest/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityTest.kt
@@ -11,7 +11,6 @@ import androidx.test.core.app.ActivityScenario
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.Espresso.pressBack
-import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.withContentDescription
@@ -93,6 +92,7 @@ import org.oppia.android.testing.threading.TestCoroutineDispatchers
import org.oppia.android.testing.threading.TestDispatcherModule
import org.oppia.android.testing.time.FakeOppiaClockModule
import org.oppia.android.util.accessibility.AccessibilityTestModule
+import org.oppia.android.util.accessibility.FakeAccessibilityService
import org.oppia.android.util.caching.AssetModule
import org.oppia.android.util.caching.testing.CachingTestModule
import org.oppia.android.util.gcsresource.GcsResourceModule
@@ -124,14 +124,29 @@ private const val FRACTIONS_SUBTOPIC_LIST_SIZE = 4
qualifiers = "port-xxhdpi"
)
class RevisionCardActivityTest {
- @get:Rule val initializeDefaultLocaleRule = InitializeDefaultLocaleRule()
- @get:Rule val oppiaTestRule = OppiaTestRule()
+ @get:Rule
+ val initializeDefaultLocaleRule = InitializeDefaultLocaleRule()
- @Inject lateinit var context: Context
- @Inject lateinit var testCoroutineDispatchers: TestCoroutineDispatchers
- @Inject lateinit var translationController: TranslationController
- @Inject lateinit var monitorFactory: DataProviderTestMonitor.Factory
- @Inject lateinit var fakeAnalyticsEventLogger: FakeAnalyticsEventLogger
+ @get:Rule
+ val oppiaTestRule = OppiaTestRule()
+
+ @Inject
+ lateinit var context: Context
+
+ @Inject
+ lateinit var testCoroutineDispatchers: TestCoroutineDispatchers
+
+ @Inject
+ lateinit var translationController: TranslationController
+
+ @Inject
+ lateinit var monitorFactory: DataProviderTestMonitor.Factory
+
+ @Inject
+ lateinit var fakeAnalyticsEventLogger: FakeAnalyticsEventLogger
+
+ @Inject
+ lateinit var fakeAccessibilityService: FakeAccessibilityService
private val profileId = ProfileId.newBuilder().apply { internalId = 1 }.build()
@@ -149,7 +164,11 @@ class RevisionCardActivityTest {
@Test
fun testActivity_createIntent_verifyScreenNameInIntent() {
val currentScreenName = RevisionCardActivity.createRevisionCardActivityIntent(
- context, 1, FRACTIONS_TOPIC_ID, 1, FRACTIONS_SUBTOPIC_LIST_SIZE
+ context,
+ 1,
+ FRACTIONS_TOPIC_ID,
+ 1,
+ FRACTIONS_SUBTOPIC_LIST_SIZE
).extractCurrentAppScreenName()
assertThat(currentScreenName).isEqualTo(ScreenName.REVISION_CARD_ACTIVITY)
@@ -172,7 +191,30 @@ class RevisionCardActivityTest {
}
@Test
- fun testRevisionCardActivity_toolbarTitle_marqueeInRtl_isDisplayedCorrectly() {
+ fun testRevisionCardActivity_toolbarTitle_readerOff_marqueeInRtl_isDisplayedCorrectly() {
+ fakeAccessibilityService.setScreenReaderEnabled(false)
+ launchRevisionCardActivity(
+ profileId = profileId,
+ topicId = FRACTIONS_TOPIC_ID,
+ subtopicId = 1
+ ).use { scenario ->
+ scenario.onActivity { activity ->
+
+ val revisionCardToolbarTitle: TextView =
+ activity.findViewById(R.id.revision_card_toolbar_title)
+ ViewCompat.setLayoutDirection(revisionCardToolbarTitle, ViewCompat.LAYOUT_DIRECTION_RTL)
+
+ onView(withId(R.id.revision_card_toolbar_title)).perform(click())
+ assertThat(revisionCardToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(revisionCardToolbarTitle.isSelected).isEqualTo(true)
+ assertThat(revisionCardToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
+ }
+ }
+ }
+
+ @Test
+ fun testRevisionCardActivity_toolbarTitle_readerOn_marqueeInRtl_isDisplayedCorrectly() {
+ fakeAccessibilityService.setScreenReaderEnabled(true)
launchRevisionCardActivity(
profileId = profileId,
topicId = FRACTIONS_TOPIC_ID,
@@ -184,15 +226,17 @@ class RevisionCardActivityTest {
activity.findViewById(R.id.revision_card_toolbar_title)
ViewCompat.setLayoutDirection(revisionCardToolbarTitle, ViewCompat.LAYOUT_DIRECTION_RTL)
- onView(withId(R.id.revision_card_toolbar_title)).perform(ViewActions.click())
+ onView(withId(R.id.revision_card_toolbar_title)).perform(click())
assertThat(revisionCardToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(revisionCardToolbarTitle.isSelected).isEqualTo(false)
assertThat(revisionCardToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
}
}
}
@Test
- fun testRevisionCardActivity_toolbarTitle_marqueeInLtr_isDisplayedCorrectly() {
+ fun testRevisionCardActivity_toolbarTitle_readerOff_marqueeInLtr_isDisplayedCorrectly() {
+ fakeAccessibilityService.setScreenReaderEnabled(false)
launchRevisionCardActivity(
profileId = profileId,
topicId = FRACTIONS_TOPIC_ID,
@@ -206,6 +250,29 @@ class RevisionCardActivityTest {
onView(withId(R.id.revision_card_toolbar_title)).perform(click())
assertThat(revisionCardToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(revisionCardToolbarTitle.isSelected).isEqualTo(true)
+ assertThat(revisionCardToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
+ }
+ }
+ }
+
+ @Test
+ fun testRevisionCardActivity_toolbarTitle_readerOn_marqueeInLtr_isDisplayedCorrectly() {
+ fakeAccessibilityService.setScreenReaderEnabled(true)
+ launchRevisionCardActivity(
+ profileId = profileId,
+ topicId = FRACTIONS_TOPIC_ID,
+ subtopicId = 1
+ ).use { scenario ->
+ scenario.onActivity { activity ->
+
+ val revisionCardToolbarTitle: TextView =
+ activity.findViewById(R.id.revision_card_toolbar_title)
+ ViewCompat.setLayoutDirection(revisionCardToolbarTitle, ViewCompat.LAYOUT_DIRECTION_LTR)
+
+ onView(withId(R.id.revision_card_toolbar_title)).perform(click())
+ assertThat(revisionCardToolbarTitle.ellipsize).isEqualTo(TextUtils.TruncateAt.MARQUEE)
+ assertThat(revisionCardToolbarTitle.isSelected).isEqualTo(false)
assertThat(revisionCardToolbarTitle.textAlignment).isEqualTo(View.TEXT_ALIGNMENT_VIEW_START)
}
}
@@ -367,9 +434,13 @@ class RevisionCardActivityTest {
private fun createRevisionCardActivityIntent(
internalProfileId: Int,
topicId: String,
- subtopicId: Int,
+ subtopicId: Int
) = RevisionCardActivity.createRevisionCardActivityIntent(
- context, internalProfileId, topicId, subtopicId, FRACTIONS_SUBTOPIC_LIST_SIZE
+ context,
+ internalProfileId,
+ topicId,
+ subtopicId,
+ FRACTIONS_SUBTOPIC_LIST_SIZE
)
private fun updateContentLanguage(profileId: ProfileId, language: OppiaLanguage) {
From c28b8eed8fe3c730d6a2b02d4aa73ee3208e8018 Mon Sep 17 00:00:00 2001
From: Adhiambo Peres <59600948+adhiamboperes@users.noreply.github.com>
Date: Tue, 19 Sep 2023 23:31:45 +0300
Subject: [PATCH 08/34] Fix #5075: Exempt Existing Vectors from ColorHex Checks
(#5123)
## Explanation
Fixes #5075.
This PR adds back the color hex regex check removed in #5076. This
requires a static check exemption for two vectors in the `drawable`
directory, `survey_nps_radio_selected_color.xml` and
`survey_nps_radio_unselected_color.xml`.
The check `file_path_regex: "app/src/main/res/drawable.*?/.+?\\.xml"`
blanket checks all drawables, including vectors. Since these cannot
fully be changed to use component colors yet, I think that the best
approach is to exempt them from the check.
This is a replacement of PR #5081, since #5081 would nolonger be a clean
revert.
## 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))
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing
---------
Co-authored-by: Ben Henning
---
...unded_primary_button_grey_shadow_color.xml | 2 +-
.../main/res/values-night/color_palette.xml | 1 +
app/src/main/res/values/color_defs.xml | 1 +
app/src/main/res/values/color_palette.xml | 1 +
app/src/main/res/values/component_colors.xml | 1 +
.../file_content_validation_checks.textproto | 13 ++++++++
.../regex/RegexPatternValidationCheckTest.kt | 32 ++++++++++++++++++-
7 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/app/src/main/res/drawable/rounded_primary_button_grey_shadow_color.xml b/app/src/main/res/drawable/rounded_primary_button_grey_shadow_color.xml
index cb6db57bdcf..1566be1839b 100644
--- a/app/src/main/res/drawable/rounded_primary_button_grey_shadow_color.xml
+++ b/app/src/main/res/drawable/rounded_primary_button_grey_shadow_color.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/app/src/main/res/values-night/color_palette.xml b/app/src/main/res/values-night/color_palette.xml
index 299d498bfc6..610b29c2ac1 100644
--- a/app/src/main/res/values-night/color_palette.xml
+++ b/app/src/main/res/values-night/color_palette.xml
@@ -227,4 +227,5 @@
@color/color_def_pale_green@color/color_def_black_87@color/color_def_white
+ @color/color_def_black_25
diff --git a/app/src/main/res/values/color_defs.xml b/app/src/main/res/values/color_defs.xml
index 446a12a3a70..9fdaccaaf51 100644
--- a/app/src/main/res/values/color_defs.xml
+++ b/app/src/main/res/values/color_defs.xml
@@ -143,4 +143,5 @@
#E8E8E8#E2F5F4
+ #25000000
diff --git a/app/src/main/res/values/color_palette.xml b/app/src/main/res/values/color_palette.xml
index 13113daf937..a542be65211 100644
--- a/app/src/main/res/values/color_palette.xml
+++ b/app/src/main/res/values/color_palette.xml
@@ -267,4 +267,5 @@
@color/color_def_grey@color/color_def_black_87@color/color_def_black_87
+ @color/color_def_black_25
diff --git a/app/src/main/res/values/component_colors.xml b/app/src/main/res/values/component_colors.xml
index f72584f767f..2ea45c834a7 100644
--- a/app/src/main/res/values/component_colors.xml
+++ b/app/src/main/res/values/component_colors.xml
@@ -301,4 +301,5 @@
@color/color_palette_survey_disabled_button_text_color@color/color_palette_button_text_color@color/color_palette_edit_text_unselected_color
+ @color/color_palette_button_shadow_color
diff --git a/scripts/assets/file_content_validation_checks.textproto b/scripts/assets/file_content_validation_checks.textproto
index 677e7ebcb9e..a53a46416f4 100644
--- a/scripts/assets/file_content_validation_checks.textproto
+++ b/scripts/assets/file_content_validation_checks.textproto
@@ -353,6 +353,19 @@ file_content_checks {
prohibited_content_regex: "@color/(?!component_color_).+|\"#\\p{XDigit}+\""
failure_message: "Only colors from component_colors.xml may be used in layouts."
}
+file_content_checks {
+ file_path_regex: "app/src/main/res/drawable.*?/.+?\\.xml"
+ prohibited_content_regex: "@color/(?!component_color_).+|\"#\\p{XDigit}+\""
+ failure_message: "Only colors from component_colors.xml may be used in drawables except vector assets."
+ exempted_file_patterns: "app/src/main/res/drawable.*?/(ic_|lesson_thumbnail_graphic_).+?\\.xml"
+ exempted_file_patterns: "app/src/main/res/drawable/full_oppia_logo.xml"
+ exempted_file_patterns: "app/src/main/res/drawable/rounded_white_background_with_shadow.xml"
+ exempted_file_patterns: "app/src/main/res/drawable/profile_image_shadow.xml"
+ exempted_file_patterns: "app/src/main/res/drawable/selected_region_background.xml"
+ exempted_file_patterns: "app/src/main/res/drawable/splash_page.xml"
+ exempted_file_patterns: "app/src/main/res/drawable/survey_nps_radio_selected_color.xml"
+ exempted_file_patterns: "app/src/main/res/drawable/survey_nps_radio_unselected_color.xml"
+}
file_content_checks {
file_path_regex: "app/src/main/java/org/oppia/android/app.?/.+(ActivityPresenter|FragmentPresenter|ViewPresenter|Activity|Fragment|View)\\.kt"
prohibited_content_regex: "R.color.(?!component_color_).+"
diff --git a/scripts/src/javatests/org/oppia/android/scripts/regex/RegexPatternValidationCheckTest.kt b/scripts/src/javatests/org/oppia/android/scripts/regex/RegexPatternValidationCheckTest.kt
index ae1d4fa60ff..20fd219f857 100644
--- a/scripts/src/javatests/org/oppia/android/scripts/regex/RegexPatternValidationCheckTest.kt
+++ b/scripts/src/javatests/org/oppia/android/scripts/regex/RegexPatternValidationCheckTest.kt
@@ -173,6 +173,8 @@ class RegexPatternValidationCheckTest {
"Only colors from color_defs.xml may be used in color_palette.xml."
private val doesNotReferenceColorFromComponentColorInLayouts =
"Only colors from component_colors.xml may be used in layouts."
+ private val doesNotReferenceColorFromComponentColorInDrawables =
+ "Only colors from component_colors.xml may be used in drawables except vector assets."
private val doesNotReferenceColorFromComponentColorInKotlinFiles =
"Only colors from component_colors.xml may be used in Kotlin Files (Activities, Fragments, " +
"Views and Presenters)."
@@ -2343,7 +2345,35 @@ class RegexPatternValidationCheckTest {
)
}
- // TODO(#5075): Add test for drawables file that checks color uses only component colors
+ @Test
+ fun testFileContent_xmlDrawables_includesNonColorComponentReferences_fileContentIsNotCorrect() {
+ val prohibitedContent =
+ """
+ android:color="@color/component_color_shared_primary_text_color"
+ android:color="@color/color_defs_shared_primary_text_color"
+ android:color="@color/color_palette_primary_text_color"
+ android:color="#003933"
+ """.trimIndent()
+ tempFolder.newFolder("testfiles", "app", "src", "main", "res", "drawable")
+ val stringFilePath = "app/src/main/res/drawable/test_layout.xml"
+ tempFolder.newFile("testfiles/$stringFilePath").writeText(prohibitedContent)
+
+ val exception = assertThrows(Exception::class) {
+ runScript()
+ }
+
+ // Verify that all patterns are properly detected & prohibited.
+ assertThat(exception).hasMessageThat().contains(REGEX_CHECK_FAILED_OUTPUT_INDICATOR)
+ assertThat(outContent.toString().trim())
+ .isEqualTo(
+ """
+ $stringFilePath:2: $doesNotReferenceColorFromComponentColorInDrawables
+ $stringFilePath:3: $doesNotReferenceColorFromComponentColorInDrawables
+ $stringFilePath:4: $doesNotReferenceColorFromComponentColorInDrawables
+ $wikiReferenceNote
+ """.trimIndent()
+ )
+ }
@Test
fun testFileContent_kotlinFiles_includesNonColorComponentReferences_fileContentIsNotCorrect() {
From cfce93c26bd3a22bcb80313908b36bb26f8aabae Mon Sep 17 00:00:00 2001
From: XichengSpencer <74568012+XichengSpencer@users.noreply.github.com>
Date: Fri, 22 Sep 2023 12:21:13 -0400
Subject: [PATCH 09/34] Fix #3843 Split Concatenated TextView (#5151)
## Explanation
Fix #3843 Instead of using 1 textview to display a concatenated string,
now have 1 textview for story progress, 1 for bar separator, and 1 for
topic progress.
## 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))
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing
|LTR|RTL|
|---|---|
|![Screenshot_20230913_170309](https://github.com/oppia/oppia-android/assets/74568012/5d10ee41-41cb-46f1-b37d-b368e247c108)|![Screenshot_20230913_170148](https://github.com/oppia/oppia-android/assets/74568012/d5ee32ce-1899-4e5c-825c-3070f5e132ad)|
|![Screenshot_20230913_165312](https://github.com/oppia/oppia-android/assets/74568012/4435074e-41b3-4b0b-9dd1-7cfc1b3bfd72)|![Screenshot_20230913_170218](https://github.com/oppia/oppia-android/assets/74568012/476060ea-15b8-4636-afa0-89fdb130d05b)|
## Tests
![Screenshot 2023-09-15
101749](https://github.com/oppia/oppia-android/assets/74568012/2ee79906-22e8-42a0-b3b6-b71676b50f92)
---------
Co-authored-by: Adhiambo Peres <59600948+adhiamboperes@users.noreply.github.com>
---
.../drawer/NavigationDrawerHeaderViewModel.kt | 37 ++++++++------
.../layout/nav_header_navigation_drawer.xml | 51 +++++++++++++++----
.../NavigationDrawerActivityProdTest.kt | 30 +++++++++--
3 files changed, 89 insertions(+), 29 deletions(-)
diff --git a/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerHeaderViewModel.kt b/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerHeaderViewModel.kt
index b46e7a63275..d75c0d03287 100644
--- a/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerHeaderViewModel.kt
+++ b/app/src/main/java/org/oppia/android/app/drawer/NavigationDrawerHeaderViewModel.kt
@@ -22,7 +22,10 @@ class NavigationDrawerHeaderViewModel @Inject constructor(
val profile = ObservableField(Profile.getDefaultInstance())
private var ongoingTopicCount = DEFAULT_ONGOING_TOPIC_COUNT
private var completedStoryCount = DEFAULT_COMPLETED_STORY_COUNT
- val profileProgressText: ObservableField = ObservableField(computeProfileProgressText())
+ val profileTopicProgressText: ObservableField =
+ ObservableField(computeProfileTopicProgressText())
+ val profileStoryProgressText: ObservableField =
+ ObservableField(computeProfileStoryProgressText())
fun onHeaderClicked() {
routeToProfileProgressListener.routeToProfileProgress(profile.get()!!.id.internalId)
@@ -30,25 +33,29 @@ class NavigationDrawerHeaderViewModel @Inject constructor(
fun setOngoingTopicProgress(ongoingTopicCount: Int) {
this.ongoingTopicCount = ongoingTopicCount
- profileProgressText.set(computeProfileProgressText())
+ profileTopicProgressText.set(computeProfileTopicProgressText())
}
fun setCompletedStoryProgress(completedStoryCount: Int) {
this.completedStoryCount = completedStoryCount
- profileProgressText.set(computeProfileProgressText())
+ profileStoryProgressText.set(computeProfileStoryProgressText())
}
- private fun computeProfileProgressText(): String {
- // TODO(#3843): Either combine these strings into one or use separate views to display them.
- val completedStoryCountText =
- resourceHandler.getQuantityStringInLocaleWithWrapping(
- R.plurals.completed_story_count, completedStoryCount, completedStoryCount.toString()
- )
- val ongoingTopicCountText =
- resourceHandler.getQuantityStringInLocaleWithWrapping(
- R.plurals.ongoing_topic_count, ongoingTopicCount, ongoingTopicCount.toString()
- )
- val barSeparator = resourceHandler.getStringInLocale(R.string.bar_separator)
- return "$completedStoryCountText$barSeparator$ongoingTopicCountText"
+ private fun computeProfileStoryProgressText(): String {
+ return resourceHandler.getQuantityStringInLocaleWithWrapping(
+ R.plurals.completed_story_count,
+ completedStoryCount,
+ completedStoryCount.toString()
+ )
+ }
+
+ fun getBarSeparator() = resourceHandler.getStringInLocale(R.string.bar_separator)
+
+ private fun computeProfileTopicProgressText(): String {
+ return resourceHandler.getQuantityStringInLocaleWithWrapping(
+ R.plurals.ongoing_topic_count,
+ ongoingTopicCount,
+ ongoingTopicCount.toString()
+ )
}
}
diff --git a/app/src/main/res/layout/nav_header_navigation_drawer.xml b/app/src/main/res/layout/nav_header_navigation_drawer.xml
index eb9d9a0ccad..d85e97e337b 100644
--- a/app/src/main/res/layout/nav_header_navigation_drawer.xml
+++ b/app/src/main/res/layout/nav_header_navigation_drawer.xml
@@ -27,10 +27,10 @@
-
+ android:orientation="horizontal">
+
+
+
+
+
+
+
diff --git a/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityProdTest.kt b/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityProdTest.kt
index bce54aac8a1..08512202fb7 100644
--- a/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityProdTest.kt
+++ b/app/src/sharedTest/java/org/oppia/android/app/testing/NavigationDrawerActivityProdTest.kt
@@ -256,7 +256,7 @@ class NavigationDrawerActivityProdTest {
}
@Test
- fun testNavDrawer_openNavDrawer_oneTopicInProgress_profileProgressIsDisplayedCorrectly() {
+ fun testNavDrawer_openNavDrawer_oneTopicInProgress_profileStoryProgressIsDisplayedCorrectly() {
storyProfileTestHelper.markCompletedRatiosStory1Exp0(
ProfileId.newBuilder().setInternalId(
internalProfileId
@@ -270,10 +270,32 @@ class NavigationDrawerActivityProdTest {
it.openNavigationDrawer()
onView(
allOf(
- withId(R.id.profile_progress_text_view),
- isDescendantOfA(withId(R.id.header_linear_layout))
+ withId(R.id.profile_story_progress_text_view),
+ isDescendantOfA(withId(R.id.progress_linear_layout))
+ )
+ ).check(matches(withText("1 Story Completed")))
+ }
+ }
+
+ @Test
+ fun testNavDrawer_openNavDrawer_oneTopicInProgress_profileTopicProgressIsDisplayedCorrectly() {
+ storyProfileTestHelper.markCompletedRatiosStory1Exp0(
+ ProfileId.newBuilder().setInternalId(
+ internalProfileId
+ ).build(),
+ timestampOlderThanOneWeek = false
+ )
+ launch(
+ createNavigationDrawerActivityIntent(internalProfileId)
+ ).use {
+ testCoroutineDispatchers.runCurrent()
+ it.openNavigationDrawer()
+ onView(
+ allOf(
+ withId(R.id.profile_topic_progress_text_view),
+ isDescendantOfA(withId(R.id.progress_linear_layout))
)
- ).check(matches(withText("1 Story Completed | 1 Topic in Progress")))
+ ).check(matches(withText("1 Topic in Progress")))
}
}
From 08981272a8136b8da0be7c4197480790c36bf100 Mon Sep 17 00:00:00 2001
From: aayushimathur6 <92685651+aayushimathur6@users.noreply.github.com>
Date: Sun, 24 Sep 2023 09:28:47 +0530
Subject: [PATCH 10/34] Fix #3841: Combine time and quantity plurals (#5153)
## Explanation
Fixes #3841
This PR involves Combining plurals and quantity strings from:
` %s ago`
and
```
a minute%s minutes
```
to
```
a minute ago%s minutes ago
```
## 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))
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing
| BEFORE | AFTER |
| ------------- | ------------- |
|
![Before](https://github.com/oppia/oppia-android/assets/92685651/f3daf711-b96d-4ca7-8e49-d13c14769fb4)|
![after](https://github.com/oppia/oppia-android/assets/92685651/e303564a-9961-49fb-8258-75743bc5fb51)
|
|
![arabicbefore](https://github.com/oppia/oppia-android/assets/92685651/9c9d5c34-9ebb-42c3-9176-f69775f28e58)
|![afterarabic](https://github.com/oppia/oppia-android/assets/92685651/471799da-10e9-4691-beb5-3b87edea1e8f)
|
---------
Co-authored-by: Adhiambo Peres <59600948+adhiamboperes@users.noreply.github.com>
---
.../databinding/TextViewBindingAdapters.java | 14 +++++--------
app/src/main/res/values/strings.xml | 20 +++++++++----------
2 files changed, 15 insertions(+), 19 deletions(-)
diff --git a/app/src/main/java/org/oppia/android/app/databinding/TextViewBindingAdapters.java b/app/src/main/java/org/oppia/android/app/databinding/TextViewBindingAdapters.java
index 349c680f221..591e8c88738 100644
--- a/app/src/main/java/org/oppia/android/app/databinding/TextViewBindingAdapters.java
+++ b/app/src/main/java/org/oppia/android/app/databinding/TextViewBindingAdapters.java
@@ -83,13 +83,13 @@ private static String getTimeAgo(View view, long lastVisitedTimestamp) {
} else if (timeDifferenceMillis < TimeUnit.MINUTES.toMillis(50)) {
return getPluralString(
resourceHandler,
- R.plurals.minutes,
+ R.plurals.minutes_ago,
(int) TimeUnit.MILLISECONDS.toMinutes(timeDifferenceMillis)
);
} else if (timeDifferenceMillis < TimeUnit.DAYS.toMillis(1)) {
return getPluralString(
resourceHandler,
- R.plurals.hours,
+ R.plurals.hours_ago,
(int) TimeUnit.MILLISECONDS.toHours(timeDifferenceMillis)
);
} else if (timeDifferenceMillis < TimeUnit.DAYS.toMillis(2)) {
@@ -97,7 +97,7 @@ private static String getTimeAgo(View view, long lastVisitedTimestamp) {
}
return getPluralString(
resourceHandler,
- R.plurals.days,
+ R.plurals.days_ago,
(int) TimeUnit.MILLISECONDS.toDays(timeDifferenceMillis)
);
}
@@ -107,13 +107,9 @@ private static String getPluralString(
@PluralsRes int pluralsResId,
int count
) {
- // TODO(#3841): Combine these strings together.
- return resourceHandler.getStringInLocaleWithWrapping(
- R.string.time_ago,
- resourceHandler.getQuantityStringInLocaleWithWrapping(
+ return resourceHandler.getQuantityStringInLocaleWithWrapping(
pluralsResId, count, String.valueOf(count)
- )
- );
+ );
}
private static long ensureTimestampIsInMilliseconds(long lastVisitedTimestamp) {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 408a4095aca..3f48fef86cc 100755
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -468,7 +468,6 @@
just nowrecently
- %s agoyesterdayReturn to topicReturn to lesson
@@ -481,17 +480,18 @@
UpDown%s %s
-
- a minute
- %s minutes
+
+ 0 minutes ago
+ a minute ago
+ %s minutes ago
-
- an hour
- %s hours
+
+ an hour ago
+ %s hours ago
-
- a day
- %s days
+
+ a day ago
+ %s days agotopic_revision_recyclerview_tag
From 42ee1bdf74de28f79d9424c3ee90b3713198f332 Mon Sep 17 00:00:00 2001
From: masclot <103062089+masclot@users.noreply.github.com>
Date: Thu, 28 Sep 2023 02:51:48 +0200
Subject: [PATCH 11/34] Fixes #4539: Replace CaseSensitiveEquals by Equals in
dev assets (#5154)
## Explanation
Fixes #4539: Replace the rule type CaseSensitiveEquals by Equals in dev
assets. This only affects the topics used in dev environment. The rule
type CaseSensitiveEquals is no longer supported.
## 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))
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing
**Videos**
|current|new|
|-|-|
|[fix_for_CaseSensitiveEquals_current.webm](https://github.com/oppia/oppia-android/assets/103062089/0ad9f1e9-a991-4908-8576-1aba964fadcb)|[fix_for_CaseSensitiveEquals_new.webm](https://github.com/oppia/oppia-android/assets/103062089/298270d9-6af2-4cb8-a9f0-6445e5abfdd6)|
**Screenshots**
|current|new|
|-|-|
|![Screenshot
fix_for_CaseSensitiveEquals_current](https://github.com/oppia/oppia-android/assets/103062089/b135fce1-270e-46d9-b819-82833011988d)|![Screenshot
fix_for_CaseSensitiveEquals_new](https://github.com/oppia/oppia-android/assets/103062089/443f966f-717b-4fab-b17a-11d52e817737)|
---------
Co-authored-by: Adhiambo Peres <59600948+adhiamboperes@users.noreply.github.com>
---
domain/src/main/assets/2mzzFVDLuAj8.json | 6 +++---
domain/src/main/assets/2mzzFVDLuAj8.textproto | 6 +++---
domain/src/main/assets/5NWuolNcwH6e.json | 4 ++--
domain/src/main/assets/5NWuolNcwH6e.textproto | 4 ++--
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/domain/src/main/assets/2mzzFVDLuAj8.json b/domain/src/main/assets/2mzzFVDLuAj8.json
index 9a7eed87bb2..4e5fa088efd 100644
--- a/domain/src/main/assets/2mzzFVDLuAj8.json
+++ b/domain/src/main/assets/2mzzFVDLuAj8.json
@@ -2463,7 +2463,7 @@
}
}
}, {
- "rule_type": "CaseSensitiveEquals",
+ "rule_type": "Equals",
"inputs": {
"x": {
"contentId": "14186351-eee4-40fa-8f20-960306cfe465",
@@ -2818,7 +2818,7 @@
}
}
}, {
- "rule_type": "CaseSensitiveEquals",
+ "rule_type": "Equals",
"inputs": {
"x": {
"contentId": "c78bf24e-b510-4bac-a107-28a03dfa1c22",
@@ -2826,7 +2826,7 @@
}
}
}, {
- "rule_type": "CaseSensitiveEquals",
+ "rule_type": "Equals",
"inputs": {
"x": {
"contentId": "338cb82a-5e6f-460a-8fa0-5a2510c1a31e",
diff --git a/domain/src/main/assets/2mzzFVDLuAj8.textproto b/domain/src/main/assets/2mzzFVDLuAj8.textproto
index dcd355095d0..f8cdd2299d4 100644
--- a/domain/src/main/assets/2mzzFVDLuAj8.textproto
+++ b/domain/src/main/assets/2mzzFVDLuAj8.textproto
@@ -3011,7 +3011,7 @@ states {
}
}
}
- rule_type: "CaseSensitiveEquals"
+ rule_type: "Equals"
}
}
answer_groups {
@@ -3472,7 +3472,7 @@ states {
}
}
}
- rule_type: "CaseSensitiveEquals"
+ rule_type: "Equals"
}
rule_specs {
input {
@@ -3484,7 +3484,7 @@ states {
}
}
}
- rule_type: "CaseSensitiveEquals"
+ rule_type: "Equals"
}
}
answer_groups {
diff --git a/domain/src/main/assets/5NWuolNcwH6e.json b/domain/src/main/assets/5NWuolNcwH6e.json
index d334766c022..dcf1da3fe0f 100644
--- a/domain/src/main/assets/5NWuolNcwH6e.json
+++ b/domain/src/main/assets/5NWuolNcwH6e.json
@@ -861,7 +861,7 @@
}
}
}, {
- "rule_type": "CaseSensitiveEquals",
+ "rule_type": "Equals",
"inputs": {
"x": {
"contentId": "947c6855-b9e6-459d-a8f6-2b239e51d37f",
@@ -2176,7 +2176,7 @@
}
}
}, {
- "rule_type": "CaseSensitiveEquals",
+ "rule_type": "Equals",
"inputs": {
"x": {
"contentId": "5d0d1769-2754-4f6a-9690-ba3675ce953d",
diff --git a/domain/src/main/assets/5NWuolNcwH6e.textproto b/domain/src/main/assets/5NWuolNcwH6e.textproto
index cac4f82089f..3b8c323fd19 100644
--- a/domain/src/main/assets/5NWuolNcwH6e.textproto
+++ b/domain/src/main/assets/5NWuolNcwH6e.textproto
@@ -1121,7 +1121,7 @@ states {
}
}
}
- rule_type: "CaseSensitiveEquals"
+ rule_type: "Equals"
}
}
default_outcome {
@@ -2807,7 +2807,7 @@ states {
}
}
}
- rule_type: "CaseSensitiveEquals"
+ rule_type: "Equals"
}
rule_specs {
input {
From 41f74fc2bbc1d6f909d38ab3e6ee4da0f322bd06 Mon Sep 17 00:00:00 2001
From: "Mr. 17"
Date: Fri, 29 Sep 2023 20:32:05 +0530
Subject: [PATCH 12/34] Fix #5079: Gradle Build Failed - Task
:utility:kaptGenerateStubsDebugKotlin FAILED (#5162)
## Explanation
Fixes #5079
The error message indicates that there's a compatibility issue with the
Java version being used for the project. The `Unsupported class file
major version 59` suggests that the code in the model.jar (project
:model) file is compiled with a Java version higher than the one being
used by the project.
This PR explicitly set the source and target compatibility to Java 8 for
the project. This ensures that the project uses Java 8, which is
compatible with class files compiled with major version 59 (Java 15).
By making this change, we ensure that the project's Java version aligns
with the Java version used to compile the model.jar file, thus resolving
the compatibility issue and allowing the build process to proceed
without errors.
## 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))
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing
---
model/build.gradle | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/model/build.gradle b/model/build.gradle
index 619f1237d8b..f68c303c551 100644
--- a/model/build.gradle
+++ b/model/build.gradle
@@ -38,3 +38,8 @@ sourceSets {
}
}
}
+
+java {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+}
From 9bbf94aa3ca4a775f658c5dfe7f3e38fca402cc6 Mon Sep 17 00:00:00 2001
From: "Mr. 17"
Date: Sat, 30 Sep 2023 09:27:29 +0530
Subject: [PATCH 13/34] Fix #5136: Modifies all caps buttons to sentence case
(#5157)
## Explanation
Fixes #5136
This PR changes all caps buttons to sentence case. All buttons mentioned
in this
[comment](https://github.com/oppia/oppia-android/issues/5136#issuecomment-1731446317)
are changed either by directly changing its `android:textAllCaps` to
`false` in the layout files or by changing its style in the `styles.xml`
file.
## 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))
- Add a screenshot demonstrating that you ran affected Espresso tests
locally & that they're passing
## Screenshots
### _layout_
|Screen / Dialog|Button ID|Screenshots|
|--|--|--|
|`activity_input_interaction_view_test.xml`|`submit_button`|
|`add_profile_activity.xml`|`add_profile_activity_create_button`|
|`admin_auth_activity.xml`|`admin_auth_submit_button`|
|`admin_pin_activity.xml`|`submit_button`|
|`concept_card_fragment_test_activity.xml`|`open_dialog_0`
`open_dialog_1`|
|`exploration_test_activity.xml`|`play_exploration_button`|
|`hint_summary.xml`|`reveal_hint_button`|![image](https://github.com/oppia/oppia-android/assets/84731134/fa55e84f-df00-47fc-9064-6ba57dc91337)|
|`math_expression_parser_fragment.xml`|`parse_math_expression_button`|![image](https://github.com/oppia/oppia-android/assets/84731134/97678f0a-294f-40e9-a057-cd59843a07c9)|
|`onboarding_slide_final.xml`|`get_started_button`|![image](https://github.com/oppia/oppia-android/assets/84731134/44dab2e5-af61-42b6-a9be-977f0c3487a3)|
|`profile_list_control_buttons.xml`|`learner_analytics_share_ids_and_events_button`
`learner_analytics_upload_logs_now_button`|
|`profile_rename_fragment.xml`|`profile_rename_save_button`|![image](https://github.com/oppia/oppia-android/assets/84731134/6834670a-6225-45a1-a845-f41bc464a711)|
|`profile_reset_pin_fragment.xml`|`profile_reset_save_button`|
|`replay_button_item.xml`|`replay_button`|
|`return_to_lesson_button_item.xml`|`return_to_lesson_button`|![image](https://github.com/oppia/oppia-android/assets/84731134/fa55e84f-df00-47fc-9064-6ba57dc91337)|
|`return_to_topic_button_item.xml`|`return_to_topic_button`|
|`solution_summary.xml`|`show_solution_button`|
|`state_fragment_test_activity.xml`|`play_test_exploration_button`|
|`submit_button_item.xml`|`submit_answer_button`|![image](https://github.com/oppia/oppia-android/assets/84731134/eed9fb84-b4d8-4d65-a665-813c641debc5)|
|`topic_practice_footer_view.xml`|`topic_practice_start_button`|
|`walkthrough_welcome_fragment.xml`|`walkthrough_welcome_next_button`|
### _layout-land_
|Screen / Dialog|Button ID|Screenshots|
|--|--|--|
|`onboarding_slide_final.xml`|`get_started_button`|![image](https://github.com/oppia/oppia-android/assets/84731134/ce6df192-62ee-481b-83ea-49a56a4dfbe3)|
|`walkthrough_welcome_fragment.xml`|`walkthrough_welcome_next_button`|
### _layout-sw600dp-land_
|Screen / Dialog|Button ID|
|--|--|
|`onboarding_slide_final.xml`|`get_started_button`|
### _layout-sw600dp-port_
|Screen / Dialog|Button ID|
|--|--|
|`onboarding_slide_final.xml`|`get_started_button`|
---------
Co-authored-by: Adhiambo Peres <59600948+adhiamboperes@users.noreply.github.com>
---
app/src/main/res/layout-land/onboarding_slide_final.xml | 1 +
app/src/main/res/layout-land/resume_lesson_fragment.xml | 4 ++--
.../res/layout-sw600dp-land/onboarding_slide_final.xml | 1 +
.../res/layout-sw600dp-land/resume_lesson_fragment.xml | 4 ++--
.../res/layout-sw600dp-port/onboarding_slide_final.xml | 1 +
app/src/main/res/layout/add_profile_activity.xml | 1 -
.../res/layout/concept_card_fragment_test_activity.xml | 6 ++++--
app/src/main/res/layout/exploration_test_activity.xml | 3 ++-
app/src/main/res/layout/hint_summary.xml | 1 +
.../main/res/layout/math_expression_parser_fragment.xml | 1 -
app/src/main/res/layout/onboarding_slide_final.xml | 1 +
app/src/main/res/layout/profile_rename_fragment.xml | 1 -
app/src/main/res/layout/profile_reset_pin_fragment.xml | 1 -
app/src/main/res/layout/resume_lesson_fragment.xml | 4 ++--
app/src/main/res/layout/solution_summary.xml | 1 +
app/src/main/res/layout/state_fragment_test_activity.xml | 1 +
app/src/main/res/values-v21/themes.xml | 1 +
app/src/main/res/values/strings.xml | 8 ++++----
app/src/main/res/values/styles.xml | 6 +++---
app/src/main/res/values/themes.xml | 2 ++
.../oppia/android/app/player/audio/AudioFragmentTest.kt | 2 +-
.../app/player/exploration/ExplorationActivityTest.kt | 2 +-
.../android/app/player/state/StateFragmentLocalTest.kt | 2 +-
23 files changed, 32 insertions(+), 23 deletions(-)
diff --git a/app/src/main/res/layout-land/onboarding_slide_final.xml b/app/src/main/res/layout-land/onboarding_slide_final.xml
index 6881cdcbcce..a62021edc69 100644
--- a/app/src/main/res/layout-land/onboarding_slide_final.xml
+++ b/app/src/main/res/layout-land/onboarding_slide_final.xml
@@ -79,6 +79,7 @@
android:text="@string/get_started"
android:textColor="@color/component_color_shared_secondary_4_text_color"
android:textSize="14sp"
+ android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/slide_image_view"
app:layout_constraintTop_toBottomOf="@id/slide_description_text_view" />
diff --git a/app/src/main/res/layout-land/resume_lesson_fragment.xml b/app/src/main/res/layout-land/resume_lesson_fragment.xml
index 41675fc3d42..e317a2eff27 100644
--- a/app/src/main/res/layout-land/resume_lesson_fragment.xml
+++ b/app/src/main/res/layout-land/resume_lesson_fragment.xml
@@ -81,7 +81,7 @@
android:minWidth="144dp"
android:minHeight="@dimen/clickable_item_min_height"
android:text="@string/start_over_lesson_button"
- android:textAllCaps="true"
+ android:textAllCaps="false"
android:textColor="@color/component_color_shared_secondary_button_background_trim_color"
android:textSize="14sp"
app:backgroundTint="@null"
@@ -100,7 +100,7 @@
android:minWidth="144dp"
android:minHeight="@dimen/clickable_item_min_height"
android:text="@string/resume_lesson_button"
- android:textAllCaps="true"
+ android:textAllCaps="false"
android:textColor="@color/component_color_shared_secondary_4_text_color"
android:textSize="14sp"
app:backgroundTint="@null"
diff --git a/app/src/main/res/layout-sw600dp-land/onboarding_slide_final.xml b/app/src/main/res/layout-sw600dp-land/onboarding_slide_final.xml
index 2877085c736..b33f3480486 100644
--- a/app/src/main/res/layout-sw600dp-land/onboarding_slide_final.xml
+++ b/app/src/main/res/layout-sw600dp-land/onboarding_slide_final.xml
@@ -73,6 +73,7 @@
android:text="@string/get_started"
android:textColor="@color/component_color_shared_secondary_4_text_color"
android:textSize="14sp"
+ android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="@+id/slide_title_text_view"
app:layout_constraintStart_toStartOf="@+id/slide_title_text_view"
app:layout_constraintTop_toBottomOf="@id/slide_description_text_view" />
diff --git a/app/src/main/res/layout-sw600dp-land/resume_lesson_fragment.xml b/app/src/main/res/layout-sw600dp-land/resume_lesson_fragment.xml
index bd3bad52c20..5997f1069a4 100644
--- a/app/src/main/res/layout-sw600dp-land/resume_lesson_fragment.xml
+++ b/app/src/main/res/layout-sw600dp-land/resume_lesson_fragment.xml
@@ -111,7 +111,7 @@
android:minWidth="144dp"
android:minHeight="@dimen/clickable_item_min_height"
android:text="@string/start_over_lesson_button"
- android:textAllCaps="true"
+ android:textAllCaps="false"
android:textColor="@color/component_color_shared_secondary_button_background_trim_color"
android:textSize="14sp"
app:backgroundTint="@null"
@@ -130,7 +130,7 @@
android:minWidth="144dp"
android:minHeight="@dimen/clickable_item_min_height"
android:text="@string/resume_lesson_button"
- android:textAllCaps="true"
+ android:textAllCaps="false"
android:textColor="@color/component_color_shared_secondary_4_text_color"
android:textSize="14sp"
app:backgroundTint="@null"
diff --git a/app/src/main/res/layout-sw600dp-port/onboarding_slide_final.xml b/app/src/main/res/layout-sw600dp-port/onboarding_slide_final.xml
index ce4f739f08d..7d56635942f 100644
--- a/app/src/main/res/layout-sw600dp-port/onboarding_slide_final.xml
+++ b/app/src/main/res/layout-sw600dp-port/onboarding_slide_final.xml
@@ -80,6 +80,7 @@
android:text="@string/get_started"
android:textColor="@color/component_color_shared_secondary_4_text_color"
android:textSize="20sp"
+ android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/slide_description_text_view" />
diff --git a/app/src/main/res/layout/add_profile_activity.xml b/app/src/main/res/layout/add_profile_activity.xml
index 6a0c53c3282..417092d77a1 100644
--- a/app/src/main/res/layout/add_profile_activity.xml
+++ b/app/src/main/res/layout/add_profile_activity.xml
@@ -237,7 +237,6 @@
android:enabled="@{viewModel.isButtonActive()}"
android:gravity="center"
android:text="@string/add_profile_create_btn"
- android:textAllCaps="true"
android:textColor="@{viewModel.isButtonActive() ? @color/component_color_shared_secondary_4_text_color : @color/component_color_shared_button_inactive_text_color }"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/add_profile_activity_pin_constraint_layout" />
diff --git a/app/src/main/res/layout/concept_card_fragment_test_activity.xml b/app/src/main/res/layout/concept_card_fragment_test_activity.xml
index 9fbbdcb7b6f..4894aac319d 100644
--- a/app/src/main/res/layout/concept_card_fragment_test_activity.xml
+++ b/app/src/main/res/layout/concept_card_fragment_test_activity.xml
@@ -7,11 +7,13 @@
android:id="@+id/open_dialog_0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="Concept Card 1" />
+ android:text="Concept Card 1"
+ android:textAllCaps="false"/>
+ android:text="Concept Card 2"
+ android:textAllCaps="false" />
diff --git a/app/src/main/res/layout/exploration_test_activity.xml b/app/src/main/res/layout/exploration_test_activity.xml
index 3ecfb09afe5..d693b80a73c 100644
--- a/app/src/main/res/layout/exploration_test_activity.xml
+++ b/app/src/main/res/layout/exploration_test_activity.xml
@@ -10,7 +10,8 @@
android:id="@+id/play_exploration_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="Play exploration" />
+ android:text="Play exploration"
+ android:textAllCaps="false"/>
diff --git a/app/src/main/res/layout/onboarding_slide_final.xml b/app/src/main/res/layout/onboarding_slide_final.xml
index ea11c502df8..ee4bc712c2b 100644
--- a/app/src/main/res/layout/onboarding_slide_final.xml
+++ b/app/src/main/res/layout/onboarding_slide_final.xml
@@ -81,6 +81,7 @@
android:text="@string/get_started"
android:textColor="@color/component_color_shared_secondary_4_text_color"
android:textSize="14sp"
+ android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/slide_description_text_view" />
diff --git a/app/src/main/res/layout/profile_rename_fragment.xml b/app/src/main/res/layout/profile_rename_fragment.xml
index a295c823615..2c78c153a4b 100644
--- a/app/src/main/res/layout/profile_rename_fragment.xml
+++ b/app/src/main/res/layout/profile_rename_fragment.xml
@@ -61,7 +61,6 @@
android:clickable="@{viewModel.inputName.length > 0}"
android:enabled="@{viewModel.inputName.length > 0}"
android:text="@string/profile_rename_save"
- android:textAllCaps="true"
android:textColor="@{viewModel.inputName.length > 0 ? @color/component_color_shared_secondary_4_text_color : @color/component_color_shared_button_inactive_text_color }"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
diff --git a/app/src/main/res/layout/profile_reset_pin_fragment.xml b/app/src/main/res/layout/profile_reset_pin_fragment.xml
index 98a19bb8e75..009f5ca5388 100644
--- a/app/src/main/res/layout/profile_reset_pin_fragment.xml
+++ b/app/src/main/res/layout/profile_reset_pin_fragment.xml
@@ -105,7 +105,6 @@
android:clickable="@{viewModel.isButtonActive()}"
android:enabled="@{viewModel.isButtonActive()}"
android:text="@string/profile_rename_save"
- android:textAllCaps="true"
android:textColor="@{viewModel.isButtonActive() ? @color/component_color_shared_secondary_4_text_color : @color/component_color_shared_button_inactive_text_color }"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/profile_reset_input_confirm_pin" />
diff --git a/app/src/main/res/layout/resume_lesson_fragment.xml b/app/src/main/res/layout/resume_lesson_fragment.xml
index 4a2ee1e4fd6..9b07c7743ba 100644
--- a/app/src/main/res/layout/resume_lesson_fragment.xml
+++ b/app/src/main/res/layout/resume_lesson_fragment.xml
@@ -96,7 +96,7 @@
android:minWidth="144dp"
android:minHeight="@dimen/clickable_item_min_height"
android:text="@string/start_over_lesson_button"
- android:textAllCaps="true"
+ android:textAllCaps="false"
android:textColor="@color/component_color_shared_secondary_button_background_trim_color"
android:textSize="14sp"
app:backgroundTint="@null"
@@ -114,7 +114,7 @@
android:minWidth="144dp"
android:minHeight="@dimen/clickable_item_min_height"
android:text="@string/resume_lesson_button"
- android:textAllCaps="true"
+ android:textAllCaps="false"
android:textColor="@color/component_color_shared_secondary_4_text_color"
android:textSize="14sp"
app:backgroundTint="@null"
diff --git a/app/src/main/res/layout/solution_summary.xml b/app/src/main/res/layout/solution_summary.xml
index 4c71087fc2f..9a6e50ed026 100644
--- a/app/src/main/res/layout/solution_summary.xml
+++ b/app/src/main/res/layout/solution_summary.xml
@@ -80,6 +80,7 @@
android:text="@string/show_solution"
android:textColor="@color/component_color_hints_and_solution_summary_button_text_color"
android:textSize="14sp"
+ android:textAllCaps="false"
android:visibility="@{viewModel.isSolutionRevealed()? View.GONE : View.VISIBLE}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
diff --git a/app/src/main/res/layout/state_fragment_test_activity.xml b/app/src/main/res/layout/state_fragment_test_activity.xml
index ed973f239e2..168334e4845 100644
--- a/app/src/main/res/layout/state_fragment_test_activity.xml
+++ b/app/src/main/res/layout/state_fragment_test_activity.xml
@@ -32,6 +32,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Play exploration"
+ android:textAllCaps="false"
android:visibility="@{viewModel.hasExplorationStarted ? View.GONE : View.VISIBLE}" />
diff --git a/app/src/main/res/values-v21/themes.xml b/app/src/main/res/values-v21/themes.xml
index dea4baa8df3..4b80e568427 100644
--- a/app/src/main/res/values-v21/themes.xml
+++ b/app/src/main/res/values-v21/themes.xml
@@ -42,5 +42,6 @@
@color/component_color_shared_primary_dark_text_color@style/textAllCaps@style/textAllCaps
+ false
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 3f48fef86cc..91bddd9bb59 100755
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -15,13 +15,13 @@
Play audioPause audio%s audio is unavailable.
- OK
+ OkCancelAudio LanguageCurrently OfflineMake sure Wi-Fi or cellular data is turned on, then try again.
- OK
- OK
+ Ok
+ OkCancelCurrently on Cellular DataStreaming audio may use a lot of cellular data.
@@ -376,7 +376,7 @@
Rename ProfileNew Name
- save
+ SaveReset PINEnter a new PIN for the user to enter when accessing their profile.
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 149d87fd1d1..815ceccc4b7 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -68,7 +68,7 @@
@drawable/state_button_primary_backgroundsans-serif-medium@dimen/clickable_item_min_height
- true
+ false@color/component_color_shared_secondary_4_text_color14sp
@@ -125,7 +125,7 @@
wrap_contentwrap_content8dp
- true
+ false@android:color/transparent#5600000014sp
@@ -418,7 +418,7 @@
144dp4dp@color/component_color_shared_secondary_button_background_trim_color
- true
+ false@color/component_color_shared_secondary_button_background_trim_color14sp
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 133c3165692..53afcd7a7db 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -38,6 +38,7 @@
@color/component_color_shared_primary_dark_text_color@color/component_color_shared_dialogs_radio_button_unchecked_color@color/component_color_shared_dialogs_radio_button_checked_color
+ false