From 10c8e6e1a4964121c92d19e372cef68545f27a22 Mon Sep 17 00:00:00 2001 From: Sneha Datta Date: Thu, 3 Oct 2024 16:23:08 +0530 Subject: [PATCH 01/16] Fix #5404: Migrate away from onBackPressed for remaining activities (#5526) ## Explanation Fixes #5404 This PR migrates deprecated `onBackPressed` usage to `OnBackPressedDispatcher` callback in the following activities and presenters. - ProfileEditActivity - ProfileEditActivityPresenter - QuestionPlayerActivityPresenter - WalkthroughFinalFragmentPresenter ## Essential Checklist - [x] The PR title and explanation each start with "Fix #bugnum: " (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".) - [x] Any changes to [scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets) files have their rationale included in the PR explanation. - [x] The PR follows the [style guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide). - [x] The PR does not contain any unnecessary code changes from Android Studio ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)). - [x] The PR is made from a branch that's **not** called "develop" and is up-to-date with "develop". - [x] The PR is **assigned** to the appropriate reviewers ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)). ## For UI-specific PRs only If your PR includes UI-related changes, then: - Add screenshots for portrait/landscape for both a tablet & phone of the before & after UI changes - For the screenshots above, include both English and pseudo-localized (RTL) screenshots (see [RTL guide](https://github.com/oppia/oppia-android/wiki/RTL-Guidelines)) - Add a video showing the full UX flow with a screen reader enabled (see [accessibility guide](https://github.com/oppia/oppia-android/wiki/Accessibility-A11y-Guide)) - For PRs introducing new UI elements or color changes, both light and dark mode screenshots must be included - Add a screenshot demonstrating that you ran affected Espresso tests locally & that they're passing --------- Co-authored-by: Adhiambo Peres <59600948+adhiamboperes@users.noreply.github.com> Co-authored-by: Mr. 17 --- .../app/settings/profile/ProfileEditActivity.kt | 15 ++++++++++++--- .../profile/ProfileEditActivityPresenter.kt | 3 +-- .../questionplayer/QuestionPlayerActivity.kt | 14 ++++++++++---- .../QuestionPlayerActivityPresenter.kt | 3 +-- .../app/walkthrough/WalkthroughActivity.kt | 14 ++++++++++---- .../end/WalkthroughFinalFragmentPresenter.kt | 3 +-- 6 files changed, 35 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivity.kt b/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivity.kt index c595bd367ca..2698cfe96a7 100644 --- a/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivity.kt +++ b/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivity.kt @@ -3,6 +3,7 @@ package org.oppia.android.app.settings.profile import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.activity.OnBackPressedCallback import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAutoLocalizedAppCompatActivity import org.oppia.android.app.model.ProfileEditActivityParams @@ -43,17 +44,25 @@ class ProfileEditActivity : InjectableAutoLocalizedAppCompatActivity() { super.onCreate(savedInstanceState) (activityComponent as ActivityComponentImpl).inject(this) profileEditActivityPresenter.handleOnCreate() + + onBackPressedDispatcher.addCallback( + this, + object : OnBackPressedCallback(/* enabled = */ true) { + override fun handleOnBackPressed() { + this@ProfileEditActivity.handleBackPress() + } + } + ) } - override fun onBackPressed() { + private fun handleBackPress() { val args = intent.getProtoExtra( PROFILE_EDIT_ACTIVITY_PARAMS_KEY, ProfileEditActivityParams.getDefaultInstance() ) val isMultipane = args?.isMultipane ?: false if (isMultipane) { - @Suppress("DEPRECATION") // TODO(#5404): Migrate to a back pressed dispatcher. - super.onBackPressed() + finish() } else { val intent = Intent(this, ProfileListActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) diff --git a/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivityPresenter.kt index ea67fb89474..b89f8857de2 100644 --- a/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/settings/profile/ProfileEditActivityPresenter.kt @@ -31,8 +31,7 @@ class ProfileEditActivityPresenter @Inject constructor( toolbar.setNavigationOnClickListener { if (isMultipane) { - @Suppress("DEPRECATION") // TODO(#5404): Migrate to a back pressed dispatcher. - activity.onBackPressed() + activity.onBackPressedDispatcher.onBackPressed() } else { val intent = Intent(activity, ProfileListActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) diff --git a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivity.kt b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivity.kt index 70239733952..027cbd7011f 100644 --- a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivity.kt +++ b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivity.kt @@ -3,6 +3,7 @@ package org.oppia.android.app.topic.questionplayer import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.activity.OnBackPressedCallback import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAutoLocalizedAppCompatActivity import org.oppia.android.app.hintsandsolution.HintsAndSolutionListener @@ -56,11 +57,16 @@ class QuestionPlayerActivity : val profileId = intent.extractCurrentUserProfileId() questionPlayerActivityPresenter.handleOnCreate(profileId) - } - override fun onBackPressed() { - showStopExplorationDialogFragment() - questionPlayerActivityPresenter.setReadingTextSizeNormal() + onBackPressedDispatcher.addCallback( + this, + object : OnBackPressedCallback(/* enabled = */ true) { + override fun handleOnBackPressed() { + showStopExplorationDialogFragment() + questionPlayerActivityPresenter.setReadingTextSizeNormal() + } + } + ) } override fun restartSession() = questionPlayerActivityPresenter.restartSession() diff --git a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityPresenter.kt index 523ebf2cc4d..345941e95e1 100644 --- a/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/topic/questionplayer/QuestionPlayerActivityPresenter.kt @@ -61,8 +61,7 @@ class QuestionPlayerActivityPresenter @Inject constructor( activity.setSupportActionBar(binding.questionPlayerToolbar) binding.questionPlayerToolbar.setNavigationOnClickListener { - @Suppress("DEPRECATION") // TODO(#5404): Migrate to a back pressed dispatcher. - activity.onBackPressed() + activity.onBackPressedDispatcher.onBackPressed() } retrieveReadingTextSize().observe( diff --git a/app/src/main/java/org/oppia/android/app/walkthrough/WalkthroughActivity.kt b/app/src/main/java/org/oppia/android/app/walkthrough/WalkthroughActivity.kt index 083b293bad7..d3d7a7081e3 100644 --- a/app/src/main/java/org/oppia/android/app/walkthrough/WalkthroughActivity.kt +++ b/app/src/main/java/org/oppia/android/app/walkthrough/WalkthroughActivity.kt @@ -3,6 +3,7 @@ package org.oppia.android.app.walkthrough import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.activity.OnBackPressedCallback import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAutoLocalizedAppCompatActivity import org.oppia.android.app.model.ProfileId @@ -22,6 +23,15 @@ class WalkthroughActivity : super.onCreate(savedInstanceState) (activityComponent as ActivityComponentImpl).inject(this) walkthroughActivityPresenter.handleOnCreate() + + onBackPressedDispatcher.addCallback( + this, + object : OnBackPressedCallback(/* enabled = */ true) { + override fun handleOnBackPressed() { + walkthroughActivityPresenter.handleSystemBack() + } + } + ) } override fun currentPage(walkthroughPage: Int) { @@ -33,10 +43,6 @@ class WalkthroughActivity : walkthroughActivityPresenter.changePage(walkthroughPage) } - override fun onBackPressed() { - walkthroughActivityPresenter.handleSystemBack() - } - companion object { fun createWalkthroughActivityIntent(context: Context, internalProfileId: Int): Intent { diff --git a/app/src/main/java/org/oppia/android/app/walkthrough/end/WalkthroughFinalFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/walkthrough/end/WalkthroughFinalFragmentPresenter.kt index abd286f77d8..078d79af431 100644 --- a/app/src/main/java/org/oppia/android/app/walkthrough/end/WalkthroughFinalFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/walkthrough/end/WalkthroughFinalFragmentPresenter.kt @@ -103,7 +103,6 @@ class WalkthroughFinalFragmentPresenter @Inject constructor( } override fun goBack() { - @Suppress("DEPRECATION") // TODO(#5404): Migrate to a back pressed dispatcher. - activity.onBackPressed() + activity.onBackPressedDispatcher.onBackPressed() } } From 5e140e989949bee89b1b266b535608bd2f839615 Mon Sep 17 00:00:00 2001 From: Sneha Datta Date: Wed, 9 Oct 2024 15:06:52 +0530 Subject: [PATCH 02/16] Fix #5404: Migrate away from onBackPressed for RevisionCardActivity (#5548) ## Explanation Fixes #5404 This PR migrates deprecated `onBackPressed `usage to `OnBackPressedDispatcher` callback in the RevisonCardActivity and RevisionCardActivityPresenter. ## Essential Checklist - [x] The PR title and explanation each start with "Fix #bugnum: " (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".) - [x] Any changes to [scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets) files have their rationale included in the PR explanation. - [x] The PR follows the [style guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide). - [x] The PR does not contain any unnecessary code changes from Android Studio ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)). - [x] The PR is made from a branch that's **not** called "develop" and is up-to-date with "develop". - [x] The PR is **assigned** to the appropriate reviewers ([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)). ## For UI-specific PRs only If your PR includes UI-related changes, then: - Add screenshots for portrait/landscape for both a tablet & phone of the before & after UI changes - For the screenshots above, include both English and pseudo-localized (RTL) screenshots (see [RTL guide](https://github.com/oppia/oppia-android/wiki/RTL-Guidelines)) - Add a video showing the full UX flow with a screen reader enabled (see [accessibility guide](https://github.com/oppia/oppia-android/wiki/Accessibility-A11y-Guide)) - For PRs introducing new UI elements or color changes, both light and dark mode screenshots must be included - Add a screenshot demonstrating that you ran affected Espresso tests locally & that they're passing --- .../topic/revisioncard/RevisionCardActivity.kt | 17 ++++++++++------- .../RevisionCardActivityPresenter.kt | 3 +-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivity.kt b/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivity.kt index 7606c7ea5ad..1dc30c6fd9e 100644 --- a/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivity.kt +++ b/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivity.kt @@ -3,6 +3,7 @@ package org.oppia.android.app.topic.revisioncard import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.activity.OnBackPressedCallback import org.oppia.android.app.activity.ActivityComponentImpl import org.oppia.android.app.activity.InjectableAutoLocalizedAppCompatActivity import org.oppia.android.app.model.ProfileId @@ -56,6 +57,15 @@ class RevisionCardActivity : subtopicListSize ) } + onBackPressedDispatcher.addCallback( + this, + object : OnBackPressedCallback(/* enabled = */ true) { + override fun handleOnBackPressed() { + revisionCardActivityPresenter.setReadingTextSizeMedium() + onReturnToTopicRequested() + } + } + ) } override fun handleOnOptionsItemSelected(itemId: Int) { @@ -115,13 +125,6 @@ class RevisionCardActivity : revisionCardActivityPresenter.dismissConceptCard() } - // TODO(#5404): Migrate to a back pressed dispatcher. - @Deprecated("Deprecated in Java") - override fun onBackPressed() { - revisionCardActivityPresenter.setReadingTextSizeMedium() - onReturnToTopicRequested() - } - override fun onDefaultFontSizeLoaded(readingTextSize: ReadingTextSize) { revisionCardActivityPresenter.loadRevisionCardFragment(readingTextSize) } diff --git a/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityPresenter.kt b/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityPresenter.kt index af41963e498..c77afb97738 100644 --- a/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/topic/revisioncard/RevisionCardActivityPresenter.kt @@ -83,8 +83,7 @@ class RevisionCardActivityPresenter @Inject constructor( binding.revisionCardToolbar.setNavigationOnClickListener { (activity as ReturnToTopicClickListener).onReturnToTopicRequested() fontScaleConfigurationUtil.adjustFontScale(activity, ReadingTextSize.MEDIUM_TEXT_SIZE) - @Suppress("DEPRECATION") // TODO(#5404): Migrate to a back pressed dispatcher. - activity.onBackPressed() + activity.onBackPressedDispatcher.onBackPressed() } if (!accessibilityService.isScreenReaderEnabled()) { binding.revisionCardToolbarTitle.setOnClickListener { From b938a4ccf43dd4f95fd03480d43811f89147fbea Mon Sep 17 00:00:00 2001 From: RD Rama Devi <122200035+Rd4dev@users.noreply.github.com> Date: Thu, 12 Dec 2024 05:52:41 +0530 Subject: [PATCH 03/16] Fix #5508: Skipping redundant code coverage and APK/AAB report comments (#5580) ## Explanation Fix #5508 TODO: - [Done] - ~~Update Indents and latest upstream changes~~ ### This PR includes **1. Code Coverage Comment:** - In previous implementations, redundant code coverage reports could accumulate, even when they provided no additional information, leading to cluttered PR threads. - To address this, a comparison step has been added to **check the newly generated code coverage report against the latest posted code coverage comment**. - If the current report is identical to the latest comment, the script will skip posting a new comment. This ensures that the last coverage comment in the PR thread accurately reflects the latest report, preventing unnecessary repetitions. **2. Stats Comment:** - The Stat reports were being generated even when no new changes were made to the PR, causing repetitive APK/AAB report comments and hindering the stale comment checks. - A new step is added to track the presence of new commits. Now, the **stats analysis only triggers if there has been a new commit since the latest APK/AAB report comment**. - This approach reduces redundant analysis, ensuring that builds are only processed when relevant *PR changes are made. ***Limitation:** - These changes aim to help the stale comment checks. However, the trade-off is: merge commits to the `develop` branch will still generate new build reports. Allowing these reports would negate the benefits of stale comment checks, as weekly or bi-weekly merges can cause build variations. - Consequently, the [older method](https://github.com/oppia/oppia-android/pull/5532) of comparing previous and new reports has been removed due to flakiness in the stat.yml. While it is technically possible to use the currently generated report for comparison with the latest comment, it would include variations from merge changes, thus failing to prevent stale comments. Including the comparison step source for reference: ```sh - name: Compare Generated APK & AAB Analysis with the Previous Report if: ${{ steps.track_commits.outputs.new_commits == 'true' }} run: | if [ -f latest_aab_comment_body.log ]; then sed -i -e '$a\' ./develop/brief_build_summary.log sed -i -e '$a\' latest_aab_comment_body.log if diff -B ./develop/brief_build_summary.log latest_aab_comment_body.log > /dev/null; then echo "No significant changes detected; skipping apk aab analysis comment." echo "skip_apk_aab_comment=true" >> $GITHUB_ENV else echo "Changes detected; proceeding with the apk aab analysis comment." diff ./develop/brief_build_summary.log latest_aab_comment_body.log || true echo "skip_apk_aab_comment=false" >> $GITHUB_ENV fi else echo "No previous APK & AAB report posted; Commenting analysed APK & AAB report." echo "skip_apk_aab_comment=false" >> $GITHUB_ENV fi ``` # ### Demonstration >Demonstrated PR: https://github.com/Rd4dev/Oppia-Android-Fork-from-Fork/pull/44 Tested with souce code - [comment_code_coverage.yml](https://github.com/Rd4dev/Oppia-Android-Fork-from-Fork/blob/4492ab36dc1efbcbec9cf0b7c164d24f9a5d4511/.github/workflows/comment_coverage_report.yml#L3) and [stats.yml](https://github.com/Rd4dev/Oppia-Android-Fork-from-Fork/blob/4492ab36dc1efbcbec9cf0b7c164d24f9a5d4511/.github/workflows/stats.yml#L3) - Initial Code Coverage Comment | [Comment](https://github.com/Rd4dev/Oppia-Android-Fork-from-Fork/pull/44#issuecomment-2491752057) | [Stack Trace](https://github.com/Rd4dev/Oppia-Android-Fork-from-Fork/actions/runs/11957616687/job/33335730714#step:5:20) - Initial APK & AAB Analysis Comment | [Comment](https://github.com/Rd4dev/Oppia-Android-Fork-from-Fork/pull/44#issuecomment-2491954464) | [Stack Trace](https://github.com/Rd4dev/Oppia-Android-Fork-from-Fork/actions/runs/11957621776/job/33337727450#step:20:348) - Redundant Code Coverage Comment Skipped | [Stack Trace](https://github.com/Rd4dev/Oppia-Android-Fork-from-Fork/actions/runs/11958563394/job/33338783923?pr=44#step:5:20) - Varying Code Coverage Comment Posted | [Comment](https://github.com/Rd4dev/Oppia-Android-Fork-from-Fork/pull/44#issuecomment-2491997257) | [Stack Trace](https://github.com/Rd4dev/Oppia-Android-Fork-from-Fork/actions/runs/11959332332/job/33341699858#step:5:20) - APK & AAB Analysis Posted with follow up commits | [Comment](https://github.com/Rd4dev/Oppia-Android-Fork-from-Fork/pull/44#issuecomment-2491977311) | [Stack Trace](https://github.com/Rd4dev/Oppia-Android-Fork-from-Fork/actions/runs/11959338918/job/33340923675#step:20:348) - APK & AAB Analysis Skipped with no follow up commits | [Stack Trace](https://github.com/Rd4dev/Oppia-Android-Fork-from-Fork/actions/runs/11959461908/job/33341312780#step:3:33) ## 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)). --------- Co-authored-by: Ben Henning --- .github/workflows/comment_coverage_report.yml | 38 ++++++ .github/workflows/stats.yml | 126 ++++++++++-------- 2 files changed, 106 insertions(+), 58 deletions(-) diff --git a/.github/workflows/comment_coverage_report.yml b/.github/workflows/comment_coverage_report.yml index 0cc70da29a2..4a04401e88f 100644 --- a/.github/workflows/comment_coverage_report.yml +++ b/.github/workflows/comment_coverage_report.yml @@ -48,6 +48,24 @@ jobs: if: ${{ !cancelled() }} runs-on: ubuntu-latest steps: + - name: Find the latest Code Coverage Report Comment + uses: actions/github-script@v6 + with: + script: | + const comments = await github.paginate(github.rest.issues.listComments, { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: ${{ github.event.pull_request.number }}, + }); + + for (let i = comments.length - 1; i >= 0; i--) { + if (comments[i].body.includes("## Coverage Report")) { + const latestCodeCoverageComment = comments[i].body; + require('fs').writeFileSync('latest_code_coverage_comment.md', latestCodeCoverageComment, 'utf8'); + return + } + } + - name: Find CI workflow run for PR id: find-workflow-run uses: actions/github-script@v7 @@ -82,8 +100,28 @@ jobs: name: final-coverage-report github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ steps.find-workflow-run.outputs.run-id }} + + - name: Compare Current Coverage Report with the Latest Coverage Report + run: | + if [ -f latest_code_coverage_comment.md ]; then + sed -i -e '$a\' CoverageReport.md + sed -i -e '$a\' latest_code_coverage_comment.md + + if diff -B CoverageReport.md latest_code_coverage_comment.md > /dev/null; then + echo "No changes detected; skipping coverage comment." + echo "skip_coverage_comment=true" >> $GITHUB_ENV + else + echo "Changes detected; proceeding with the coverage comment." + diff CoverageReport.md latest_code_coverage_comment.md || true + echo "skip_coverage_comment=false" >> $GITHUB_ENV + fi + else + echo "No previous coverage comment found to compare; posting evaluated coverage comment." + echo "skip_coverage_comment=false" >> $GITHUB_ENV + fi - name: Upload Coverage Report as PR Comment + if: ${{ env.skip_coverage_comment == 'false' }} uses: peter-evans/create-or-update-comment@v4 with: issue-number: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/stats.yml b/.github/workflows/stats.yml index 74cbbeabbed..bdcb532c03e 100644 --- a/.github/workflows/stats.yml +++ b/.github/workflows/stats.yml @@ -42,13 +42,65 @@ jobs: ENABLE_CACHING: false CACHE_DIRECTORY: ~/.bazel_cache steps: + - name: Find the latest APK & AAB Analysis Comment + uses: actions/github-script@v6 + id: find_latest_apk_aab_comment + with: + script: | + const comments = await github.paginate(github.rest.issues.listComments, { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: ${{ matrix.prInfo.number }}, + }); + + for (let i = comments.length - 1; i >= 0; i--) { + if (comments[i].body.includes("# APK & AAB differences analysis")) { + const latestComment = comments[i]; + const commentBody = latestComment.body; + const commentDate = latestComment.created_at; + + require('fs').writeFileSync('latest_aab_comment_body.log', commentBody, 'utf8'); + core.setOutput("latest_aab_comment_created_at", commentDate); + + return + } + } + + - name: Track Commits following the latest APK & AAB Analysis Comment + uses: actions/github-script@v6 + id: track_commits + with: + script: | + const commits = await github.paginate(github.rest.pulls.listCommits, { + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: ${{ matrix.prInfo.number }}, + }); + + const latestCommentDate = "${{ steps.find_latest_apk_aab_comment.outputs.latest_aab_comment_created_at }}"; + const recentCommits = commits.filter(commit => { + const commitDate = new Date(commit.commit.committer.date); + return commitDate > new Date("${{ steps.find_latest_apk_aab_comment.outputs.latest_aab_comment_created_at }}"); + }); + + const recentCommitsCount = recentCommits.length; + if(recentCommitsCount > 0 || !latestCommentDate) { + core.setOutput("new_commits", "true"); + } else { + console.log("No new commits since the last APK & AAB report; Skipping redundant analysis."); + core.setOutput("new_commits", "false"); + } + - name: Compute PR head owner/repo reference + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} env: PR_HEAD_REPO: ${{ matrix.prInfo.headRepository.name }} PR_HEAD_REPO_OWNER: ${{ matrix.prInfo.headRepositoryOwner.login }} run: | echo "PR_HEAD=$PR_HEAD_REPO_OWNER/$PR_HEAD_REPO" >> "$GITHUB_ENV" + - name: Print PR information for this run + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} env: PR_BASE_REF_NAME: ${{ matrix.prInfo.baseRefName }} PR_HEAD_REF_NAME: ${{ matrix.prInfo.headRefName }} @@ -57,11 +109,13 @@ jobs: echo "PR $PR_NUMBER is merging into $PR_BASE_REF_NAME from https://github.com/$PR_HEAD branch $PR_HEAD_REF_NAME." - name: Set up JDK 11 + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} uses: actions/setup-java@v1 with: java-version: 11 - name: Set up Bazel + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} uses: abhinavsingh/setup-bazel@v3 with: version: 6.5.0 @@ -73,6 +127,7 @@ jobs: # benefit from incremental build performance (assuming that actions/cache aggressively removes # older caches due to the 5GB cache limit size & Bazel's large cache size). - uses: actions/cache@v2 + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} id: cache with: path: ${{ env.CACHE_DIRECTORY }} @@ -87,6 +142,7 @@ jobs: # few slower CI actions around the time cache is detected to be too large, but it should # incrementally improve thereafter. - name: Ensure cache size + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} env: BAZEL_CACHE_DIR: ${{ env.CACHE_DIRECTORY }} run: | @@ -105,6 +161,7 @@ jobs: fi - name: Configure Bazel to use a local cache + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} env: BAZEL_CACHE_DIR: ${{ env.CACHE_DIRECTORY }} run: | @@ -117,19 +174,23 @@ jobs: # run from the latest develop rather than the base branch (which might be different for # chained PRs). - name: Check out develop repository + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} uses: actions/checkout@v4 with: path: develop - name: Set up build environment + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} uses: ./develop/.github/actions/set-up-android-bazel-build-environment - name: Check Bazel environment + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} run: | cd develop bazel info - name: Check out base repository and branch + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} env: PR_BASE_REF_NAME: ${{ matrix.prInfo.baseRefName }} uses: actions/checkout@v4 @@ -139,6 +200,7 @@ jobs: path: base - name: Check out head repository and branch + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} env: PR_HEAD_REF_NAME: ${{ matrix.prInfo.headRefName }} uses: actions/checkout@v4 @@ -152,6 +214,7 @@ jobs: # up being active (due to multiple repositories being used) and this can quickly overwhelm CI # worker resources. - name: Build Oppia dev, alpha, beta, and GA (feature branch) + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} run: | cd head git log -n 1 @@ -163,6 +226,7 @@ jobs: bazel shutdown - name: Build Oppia dev, alpha, beta, and GA (base branch) + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} run: | cd base git log -n 1 @@ -174,6 +238,7 @@ jobs: bazel shutdown - name: Run stats analysis tool (develop branch) + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} run: | cd develop git log -n 1 @@ -184,66 +249,10 @@ jobs: beta $(pwd)/oppia_beta_without_changes.aab $(pwd)/oppia_beta_with_changes.aab \ ga $(pwd)/oppia_ga_without_changes.aab $(pwd)/oppia_ga_with_changes.aab - - name: Find CI workflow run for PR - id: find-workflow-run - uses: actions/github-script@v7 - continue-on-error: true - with: - script: | - const { owner, repo } = context.repo; - const runsResponse = await github.rest.actions.listWorkflowRuns({ - owner, - repo, - workflow_id: 'stats.yml', - }); - - const runs = runsResponse.data.workflow_runs; - runs.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()); - - const run = runs[1]; - if(!run) { - core.setFailed('Could not find a succesful workflow run'); - return; - } - console.log(run.id); - - core.setOutput('run-id', run.id); - - - name: Download previous build summary - uses: actions/download-artifact@v4 - with: - name: brief_build_summary_${{ matrix.prInfo.number }} - path: ./previous_build_logs - github-token: ${{ secrets.GITHUB_TOKEN }} - run-id: ${{ steps.find-workflow-run.outputs.run-id }} - continue-on-error: true # Ignore errors if the file doesn't exist (first run) - - - name: Compare current build summary with the previous one - id: build-comparison - run: | - if [ -f ./develop/brief_build_summary.log ]; then - echo "Comparing current and previous build summaries..." - if diff ./develop/brief_build_summary.log ./previous_build_logs/brief_build_summary.log > /dev/null; then - echo "No changes detected; skipping comment." - echo "skip_comment=true" >> $GITHUB_ENV - else - echo "Changes detected; proceeding with the comment." - echo "skip_comment=false" >> $GITHUB_ENV - fi - else - echo "No previous summary found; proceeding with the comment." - echo "skip_comment=false" >> $GITHUB_ENV - fi - - - name: Upload current build summary for future comparison - uses: actions/upload-artifact@v4 - with: - name: brief_build_summary_${{ matrix.prInfo.number }} - path: ./develop/brief_build_summary.log - # Reference: https://github.com/peter-evans/create-or-update-comment#setting-the-comment-body-from-a-file. # Also, for multi-line env values, see: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings. - name: Extract reports for uploading & commenting + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} env: PR_NUMBER: ${{ matrix.prInfo.number }} id: compute-comment-body @@ -260,7 +269,7 @@ jobs: cp "$GITHUB_WORKSPACE/develop/full_build_summary.log" "$FULL_BUILD_SUMMARY_FILE_PATH" - name: Add build stats summary comment - if: ${{ env.skip_comment == 'false' }} + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} env: PR_NUMBER: ${{ matrix.prInfo.number }} uses: peter-evans/create-or-update-comment@v1 @@ -269,6 +278,7 @@ jobs: body: ${{ steps.compute-comment-body.outputs.comment_body }} - uses: actions/upload-artifact@v4 + if: ${{ steps.track_commits.outputs.new_commits == 'true' }} with: name: ${{ env.FULL_BUILD_SUMMARY_FILE_NAME }} path: ${{ env.FULL_BUILD_SUMMARY_FILE_PATH }} From fc2f93261aee0dde12d31f20ac05250a23383e00 Mon Sep 17 00:00:00 2001 From: Tobiloba Oyelekan Date: Mon, 16 Dec 2024 08:16:35 +0100 Subject: [PATCH 04/16] Fix part of #4865: Use profileId in classroom activity and presenter (#5596) ## Explanation ### Fixes part of #4865 This is a step towards the whole migration, as proposed we should address this by each feature to make PRs smaller and easy to review. - The changes here are only scoped to classroom. - routes to other features maintain `internalProfileId` until the destination parameter is migrated to `profileId` ## 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)). ## Screen record https://github.com/user-attachments/assets/c474a78f-0331-4b0e-918b-abc07df380c4 --- .../oppia/android/app/classroom/ClassroomListActivity.kt | 6 +++--- .../app/classroom/ClassroomListFragmentPresenter.kt | 7 ++----- .../oppia/android/app/classroom/ClassroomListViewModel.kt | 6 +++--- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListActivity.kt b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListActivity.kt index f6160ec4ba7..5eeb5f498d1 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListActivity.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListActivity.kt @@ -47,7 +47,7 @@ class ClassroomListActivity : @Inject lateinit var activityRouter: ActivityRouter - private var internalProfileId: Int = -1 + private lateinit var profileId: ProfileId @Inject @field:EnableOnboardingFlowV2 @@ -67,7 +67,7 @@ class ClassroomListActivity : super.onCreate(savedInstanceState) (activityComponent as ActivityComponentImpl).inject(this) - internalProfileId = intent.extractCurrentUserProfileId().internalId + profileId = intent.extractCurrentUserProfileId() classroomListActivityPresenter.handleOnCreate() title = resourceHandler.getStringInLocale(R.string.classroom_list_activity_title) } @@ -92,7 +92,7 @@ class ClassroomListActivity : val recentlyPlayedActivityParams = RecentlyPlayedActivityParams .newBuilder() - .setProfileId(ProfileId.newBuilder().setInternalId(internalProfileId).build()) + .setProfileId(profileId) .setActivityTitle(recentlyPlayedActivityTitle).build() activityRouter.routeToScreen( diff --git a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt index b0ab600338e..a385a9ff2b9 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListFragmentPresenter.kt @@ -99,7 +99,6 @@ class ClassroomListFragmentPresenter @Inject constructor( private val exitProfileListener = activity as ExitProfileListener private lateinit var binding: ClassroomListFragmentBinding private lateinit var classroomListViewModel: ClassroomListViewModel - private var internalProfileId: Int = -1 private val profileId = activity.intent.extractCurrentUserProfileId() private var onBackPressedCallback: OnBackPressedCallback? = null @@ -111,15 +110,13 @@ class ClassroomListFragmentPresenter @Inject constructor( /* attachToRoot= */ false ) - internalProfileId = profileId.internalId - logHomeActivityEvent() classroomListViewModel = ClassroomListViewModel( activity, fragment, oppiaLogger, - internalProfileId, + profileId, profileManagementController, topicListController, classroomController, @@ -177,7 +174,7 @@ class ClassroomListFragmentPresenter @Inject constructor( /** Routes to the play story view for the first story in the given topic summary. */ fun onTopicSummaryClicked(topicSummary: TopicSummary) { routeToTopicPlayStoryListener.routeToTopicPlayStory( - internalProfileId, + profileId.internalId, topicSummary.classroomId, topicSummary.topicId, topicSummary.firstStoryId diff --git a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListViewModel.kt b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListViewModel.kt index 8211e52529b..985ed3816c9 100644 --- a/app/src/main/java/org/oppia/android/app/classroom/ClassroomListViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/classroom/ClassroomListViewModel.kt @@ -53,7 +53,7 @@ class ClassroomListViewModel( private val activity: AppCompatActivity, private val fragment: Fragment, private val oppiaLogger: OppiaLogger, - private val internalProfileId: Int, + private val profileId: ProfileId, private val profileManagementController: ProfileManagementController, private val topicListController: TopicListController, private val classroomController: ClassroomController, @@ -63,7 +63,7 @@ class ClassroomListViewModel( private val dateTimeUtil: DateTimeUtil, private val translationController: TranslationController ) : ObservableViewModel() { - private val profileId: ProfileId = ProfileId.newBuilder().setInternalId(internalProfileId).build() + private val promotedStoryListLimit = activity.resources.getInteger( R.integer.promoted_story_list_limit ) @@ -226,7 +226,7 @@ class ClassroomListViewModel( .mapIndexed { index, promotedStory -> PromotedStoryViewModel( activity, - internalProfileId, + profileId.internalId, sortedStoryList.size, storyEntityType, promotedStory, From 3e6404d5203b6ba7469df5c81563283f0821732c Mon Sep 17 00:00:00 2001 From: Subhajit Mallick <153619690+subhajitxyz@users.noreply.github.com> Date: Sat, 21 Dec 2024 08:32:13 +0530 Subject: [PATCH 05/16] add content desc and test for arabicDisplayName --- .../app/options/AudioLanguageItemViewModel.kt | 7 ++++++ .../main/res/layout/audio_language_item.xml | 1 + .../app/options/AudioLanguageFragmentTest.kt | 25 +++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt b/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt index 7ebe3fa7931..1fc3afd003f 100644 --- a/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt @@ -29,4 +29,11 @@ class AudioLanguageItemViewModel( val isLanguageSelected: LiveData by lazy { Transformations.map(currentSelectedLanguage) { it == language } } + + fun languageContentDescription(): String { + return when (language) { + AudioLanguage.ARABIC_LANGUAGE -> "Arabic" + else -> languageDisplayName + } + } } diff --git a/app/src/main/res/layout/audio_language_item.xml b/app/src/main/res/layout/audio_language_item.xml index 86bf4c19470..e721298f2ab 100644 --- a/app/src/main/res/layout/audio_language_item.xml +++ b/app/src/main/res/layout/audio_language_item.xml @@ -38,6 +38,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="24dp" android:fontFamily="sans-serif" + android:contentDescription="@{viewModel.languageContentDescription()}" android:text="@{viewModel.languageDisplayName}" android:textColor="@color/component_color_shared_primary_text_color" android:textSize="16sp" /> diff --git a/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt index 703b2c7cf94..0be67274617 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt @@ -17,6 +17,7 @@ import androidx.test.espresso.matcher.RootMatchers.withDecorView import androidx.test.espresso.matcher.ViewMatchers.Visibility import androidx.test.espresso.matcher.ViewMatchers.isChecked import androidx.test.espresso.matcher.ViewMatchers.isRoot +import androidx.test.espresso.matcher.ViewMatchers.withContentDescription import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText @@ -499,6 +500,30 @@ class AudioLanguageFragmentTest { } } + @Test + fun testOpenFragment_withEnglish_verifyContentDescriptionOfArabicLanguage() { + initializeTestApplicationComponent(enableOnboardingFlowV2 = false) + launchActivityWithLanguage(ENGLISH_AUDIO_LANGUAGE).use { + verifyEnglishIsSelected() + + onView( + atPositionOnView( + R.id.audio_language_recycler_view, + 3, + R.id.language_text_view + ) + ).check(matches(withText(R.string.arabic_localized_language_name))) + + onView( + atPositionOnView( + R.id.audio_language_recycler_view, + 3, + R.id.language_text_view + ) + ).check(matches(withContentDescription("Arabic"))) + } + } + private fun launchActivityWithLanguage( audioLanguage: AudioLanguage ): ActivityScenario { From 9312dcf8e17c96dc99a95e1fd45ba52abfa49e47 Mon Sep 17 00:00:00 2001 From: Subhajit Mallick <153619690+subhajitxyz@users.noreply.github.com> Date: Sat, 21 Dec 2024 09:42:08 +0530 Subject: [PATCH 06/16] added kdoc for fun languageContentDescription --- .../oppia/android/app/options/AudioLanguageItemViewModel.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt b/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt index 1fc3afd003f..66f99f78559 100644 --- a/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt @@ -29,7 +29,10 @@ class AudioLanguageItemViewModel( val isLanguageSelected: LiveData by lazy { Transformations.map(currentSelectedLanguage) { it == language } } - + /** + * Returns the content description for the current language. This is used for accessibility + * purposes to provide a readable description of the language in the UI. + */ fun languageContentDescription(): String { return when (language) { AudioLanguage.ARABIC_LANGUAGE -> "Arabic" From b1d0ca1f50cff91f5f9defd3edf614cb6d78304b Mon Sep 17 00:00:00 2001 From: Subhajit Mallick <153619690+subhajitxyz@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:03:29 +0530 Subject: [PATCH 07/16] add string in string.xml and change test name --- app/src/main/res/values/strings.xml | 4 ++++ .../oppia/android/app/options/AudioLanguageFragmentTest.kt | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 48ed440dcf6..15ee1fdbc10 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -686,4 +686,8 @@ In %s, you can listen to lessons! Select the audio language to listen to lessons STEP 5 OF 5 + + + Arabic + diff --git a/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt b/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt index 0be67274617..d0ba429c015 100644 --- a/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt +++ b/app/src/sharedTest/java/org/oppia/android/app/options/AudioLanguageFragmentTest.kt @@ -501,7 +501,7 @@ class AudioLanguageFragmentTest { } @Test - fun testOpenFragment_withEnglish_verifyContentDescriptionOfArabicLanguage() { + fun testFragment_withEnglish_verifyContentDescriptionReadsArabicLanguage() { initializeTestApplicationComponent(enableOnboardingFlowV2 = false) launchActivityWithLanguage(ENGLISH_AUDIO_LANGUAGE).use { verifyEnglishIsSelected() @@ -520,7 +520,9 @@ class AudioLanguageFragmentTest { 3, R.id.language_text_view ) - ).check(matches(withContentDescription("Arabic"))) + ).check( + matches(withContentDescription(R.string.arabic_language_display_name_content_description)) + ) } } From 0e19cdd49e415d79d149484a2f384cf731478c8e Mon Sep 17 00:00:00 2001 From: Subhajit Mallick <153619690+subhajitxyz@users.noreply.github.com> Date: Fri, 3 Jan 2025 10:31:14 +0530 Subject: [PATCH 08/16] Use appLangugeResourceHandler --- .../android/app/options/AudioLanguageItemViewModel.kt | 8 ++++++-- .../app/options/AudioLanguageSelectionViewModel.kt | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt b/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt index 66f99f78559..6d6735a35ce 100644 --- a/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt @@ -2,7 +2,9 @@ package org.oppia.android.app.options import androidx.lifecycle.LiveData import androidx.lifecycle.Transformations +import org.oppia.android.R import org.oppia.android.app.model.AudioLanguage +import org.oppia.android.app.translation.AppLanguageResourceHandler import org.oppia.android.app.viewmodel.ObservableViewModel /** @@ -20,7 +22,8 @@ class AudioLanguageItemViewModel( val language: AudioLanguage, val languageDisplayName: String, private val currentSelectedLanguage: LiveData, - val audioLanguageRadioButtonListener: AudioLanguageRadioButtonListener + val audioLanguageRadioButtonListener: AudioLanguageRadioButtonListener, + private val resourceHandler: AppLanguageResourceHandler ) : ObservableViewModel() { /** * Indicates whether the language corresponding to this view model is _currently_ selected in the @@ -35,7 +38,8 @@ class AudioLanguageItemViewModel( */ fun languageContentDescription(): String { return when (language) { - AudioLanguage.ARABIC_LANGUAGE -> "Arabic" + AudioLanguage.ARABIC_LANGUAGE -> resourceHandler + .getStringInLocale(R.string.arabic_language_display_name_content_description) else -> languageDisplayName } } diff --git a/app/src/main/java/org/oppia/android/app/options/AudioLanguageSelectionViewModel.kt b/app/src/main/java/org/oppia/android/app/options/AudioLanguageSelectionViewModel.kt index 27b40c88b34..79541d62782 100644 --- a/app/src/main/java/org/oppia/android/app/options/AudioLanguageSelectionViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/options/AudioLanguageSelectionViewModel.kt @@ -128,7 +128,8 @@ class AudioLanguageSelectionViewModel @Inject constructor( language, appLanguageResourceHandler.computeLocalizedDisplayName(language), selectedLanguage, - fragment as AudioLanguageRadioButtonListener + fragment as AudioLanguageRadioButtonListener, + appLanguageResourceHandler ) } From e28fc3bd522ee4b0c45fca9c207d73503fd947b2 Mon Sep 17 00:00:00 2001 From: Subhajit Mallick <153619690+subhajitxyz@users.noreply.github.com> Date: Fri, 3 Jan 2025 10:33:44 +0530 Subject: [PATCH 09/16] Correct klint --- .../oppia/android/app/options/AudioLanguageItemViewModel.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt b/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt index 6d6735a35ce..cc255d0a6eb 100644 --- a/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt @@ -38,8 +38,8 @@ class AudioLanguageItemViewModel( */ fun languageContentDescription(): String { return when (language) { - AudioLanguage.ARABIC_LANGUAGE -> resourceHandler - .getStringInLocale(R.string.arabic_language_display_name_content_description) + AudioLanguage.ARABIC_LANGUAGE -> + resourceHandler.getStringInLocale(R.string.arabic_language_display_name_content_description) else -> languageDisplayName } } From e0c38c645ef8d6da55788caa963f8548053ed98a Mon Sep 17 00:00:00 2001 From: Subhajit Mallick <153619690+subhajitxyz@users.noreply.github.com> Date: Fri, 3 Jan 2025 11:14:29 +0530 Subject: [PATCH 10/16] Remove resourcehandler --- .../oppia/android/app/options/AudioLanguageItemViewModel.kt | 6 ++---- .../android/app/options/AudioLanguageSelectionViewModel.kt | 3 +-- app/src/main/res/values/strings.xml | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt b/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt index cc255d0a6eb..03610b0d554 100644 --- a/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt @@ -22,8 +22,7 @@ class AudioLanguageItemViewModel( val language: AudioLanguage, val languageDisplayName: String, private val currentSelectedLanguage: LiveData, - val audioLanguageRadioButtonListener: AudioLanguageRadioButtonListener, - private val resourceHandler: AppLanguageResourceHandler + val audioLanguageRadioButtonListener: AudioLanguageRadioButtonListener ) : ObservableViewModel() { /** * Indicates whether the language corresponding to this view model is _currently_ selected in the @@ -38,8 +37,7 @@ class AudioLanguageItemViewModel( */ fun languageContentDescription(): String { return when (language) { - AudioLanguage.ARABIC_LANGUAGE -> - resourceHandler.getStringInLocale(R.string.arabic_language_display_name_content_description) + AudioLanguage.ARABIC_LANGUAGE -> "Arabic" else -> languageDisplayName } } diff --git a/app/src/main/java/org/oppia/android/app/options/AudioLanguageSelectionViewModel.kt b/app/src/main/java/org/oppia/android/app/options/AudioLanguageSelectionViewModel.kt index 79541d62782..27b40c88b34 100644 --- a/app/src/main/java/org/oppia/android/app/options/AudioLanguageSelectionViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/options/AudioLanguageSelectionViewModel.kt @@ -128,8 +128,7 @@ class AudioLanguageSelectionViewModel @Inject constructor( language, appLanguageResourceHandler.computeLocalizedDisplayName(language), selectedLanguage, - fragment as AudioLanguageRadioButtonListener, - appLanguageResourceHandler + fragment as AudioLanguageRadioButtonListener ) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 15ee1fdbc10..730b8d38720 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -665,7 +665,7 @@ Click in the box above to type your nickname. Edit profile picture Current profile picture - STEP 3 OF 5 + STEP 3 OF 5 Welcome From b9622bea79925f1a51f245c8d891d6fd21cb7e9c Mon Sep 17 00:00:00 2001 From: Subhajit Mallick <153619690+subhajitxyz@users.noreply.github.com> Date: Fri, 3 Jan 2025 11:15:19 +0530 Subject: [PATCH 11/16] Correct klint --- .../org/oppia/android/app/options/AudioLanguageItemViewModel.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt b/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt index 03610b0d554..66f99f78559 100644 --- a/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt @@ -2,9 +2,7 @@ package org.oppia.android.app.options import androidx.lifecycle.LiveData import androidx.lifecycle.Transformations -import org.oppia.android.R import org.oppia.android.app.model.AudioLanguage -import org.oppia.android.app.translation.AppLanguageResourceHandler import org.oppia.android.app.viewmodel.ObservableViewModel /** From d21a6624d8ef025141a680f72f76387cbf0377d3 Mon Sep 17 00:00:00 2001 From: Subhajit Mallick <153619690+subhajitxyz@users.noreply.github.com> Date: Fri, 3 Jan 2025 11:20:02 +0530 Subject: [PATCH 12/16] Correct string.xml --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 730b8d38720..15ee1fdbc10 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -665,7 +665,7 @@ Click in the box above to type your nickname. Edit profile picture Current profile picture - STEP 3 OF 5 + STEP 3 OF 5 Welcome From bb21cd4286de9d5b4d96d525cf7ee5312f8f1cd3 Mon Sep 17 00:00:00 2001 From: Subhajit Mallick <153619690+subhajitxyz@users.noreply.github.com> Date: Mon, 20 Jan 2025 07:33:51 +0530 Subject: [PATCH 13/16] Add AppLanguageResourcehandler --- BUILD.bazel | 4 ++-- .../app/options/AudioLanguageItemViewModel.kt | 9 +++++++-- .../app/options/AudioLanguageSelectionViewModel.kt | 3 ++- build_flavors.bzl | 12 ++++++------ build_vars.bzl | 2 +- version.bzl | 14 +++++++------- 6 files changed, 25 insertions(+), 19 deletions(-) diff --git a/BUILD.bazel b/BUILD.bazel index f0db399e20c..4c6d5a97c2a 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -119,14 +119,14 @@ package_group( "flavor": "oppia", "min_sdk_version": 21, "multidex": "native", - "target_sdk_version": 33, + "target_sdk_version": 34, }, { "flavor": "oppia_kitkat", "main_dex_list": "//:config/kitkat_main_dex_class_list.txt", "min_sdk_version": 21, "multidex": "manual_main_dex", - "target_sdk_version": 33, + "target_sdk_version": 34, }, ] ] diff --git a/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt b/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt index 66f99f78559..ee5679b2498 100644 --- a/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt @@ -2,7 +2,9 @@ package org.oppia.android.app.options import androidx.lifecycle.LiveData import androidx.lifecycle.Transformations +import org.oppia.android.R import org.oppia.android.app.model.AudioLanguage +import org.oppia.android.app.translation.AppLanguageResourceHandler import org.oppia.android.app.viewmodel.ObservableViewModel /** @@ -20,7 +22,8 @@ class AudioLanguageItemViewModel( val language: AudioLanguage, val languageDisplayName: String, private val currentSelectedLanguage: LiveData, - val audioLanguageRadioButtonListener: AudioLanguageRadioButtonListener + val audioLanguageRadioButtonListener: AudioLanguageRadioButtonListener, + private val appLanguageResourceHandler: AppLanguageResourceHandler ) : ObservableViewModel() { /** * Indicates whether the language corresponding to this view model is _currently_ selected in the @@ -35,7 +38,9 @@ class AudioLanguageItemViewModel( */ fun languageContentDescription(): String { return when (language) { - AudioLanguage.ARABIC_LANGUAGE -> "Arabic" + AudioLanguage.ARABIC_LANGUAGE -> appLanguageResourceHandler.getStringInLocaleWithWrapping( + R.string.arabic_language_display_name_content_description + ) else -> languageDisplayName } } diff --git a/app/src/main/java/org/oppia/android/app/options/AudioLanguageSelectionViewModel.kt b/app/src/main/java/org/oppia/android/app/options/AudioLanguageSelectionViewModel.kt index 27b40c88b34..79541d62782 100644 --- a/app/src/main/java/org/oppia/android/app/options/AudioLanguageSelectionViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/options/AudioLanguageSelectionViewModel.kt @@ -128,7 +128,8 @@ class AudioLanguageSelectionViewModel @Inject constructor( language, appLanguageResourceHandler.computeLocalizedDisplayName(language), selectedLanguage, - fragment as AudioLanguageRadioButtonListener + fragment as AudioLanguageRadioButtonListener, + appLanguageResourceHandler ) } diff --git a/build_flavors.bzl b/build_flavors.bzl index d9d6af2bf96..aa5493a391e 100644 --- a/build_flavors.bzl +++ b/build_flavors.bzl @@ -44,7 +44,7 @@ _FLAVOR_METADATA = { "dev": { "manifest": "//app:src/main/AndroidManifest.xml", "min_sdk_version": 21, - "target_sdk_version": 33, + "target_sdk_version": 34, "multidex": "native", "proguard_specs": [], # Developer builds are not optimized. "production_release": False, @@ -58,7 +58,7 @@ _FLAVOR_METADATA = { "dev_kitkat": { "manifest": "//app:src/main/AndroidManifest.xml", "min_sdk_version": 21, - "target_sdk_version": 33, + "target_sdk_version": 34, "multidex": "manual_main_dex", "main_dex_list": _MAIN_DEX_LIST_TARGET_KITKAT, "proguard_specs": [], # Developer builds are not optimized. @@ -73,7 +73,7 @@ _FLAVOR_METADATA = { "alpha": { "manifest": "//app:src/main/AndroidManifest.xml", "min_sdk_version": 21, - "target_sdk_version": 33, + "target_sdk_version": 34, "multidex": "native", "proguard_specs": _PRODUCTION_PROGUARD_SPECS, "production_release": True, @@ -87,7 +87,7 @@ _FLAVOR_METADATA = { "alpha_kitkat": { "manifest": "//app:src/main/AndroidManifest.xml", "min_sdk_version": 21, - "target_sdk_version": 33, + "target_sdk_version": 34, "multidex": "manual_main_dex", "main_dex_list": _MAIN_DEX_LIST_TARGET_KITKAT, "proguard_specs": [], @@ -102,7 +102,7 @@ _FLAVOR_METADATA = { "beta": { "manifest": "//app:src/main/AndroidManifest.xml", "min_sdk_version": 21, - "target_sdk_version": 33, + "target_sdk_version": 34, "multidex": "native", "proguard_specs": _PRODUCTION_PROGUARD_SPECS, "production_release": True, @@ -116,7 +116,7 @@ _FLAVOR_METADATA = { "ga": { "manifest": "//app:src/main/AndroidManifest.xml", "min_sdk_version": 21, - "target_sdk_version": 33, + "target_sdk_version": 34, "multidex": "native", "proguard_specs": _PRODUCTION_PROGUARD_SPECS, "production_release": True, diff --git a/build_vars.bzl b/build_vars.bzl index 6fd23a4f9a5..be9b7e6460b 100644 --- a/build_vars.bzl +++ b/build_vars.bzl @@ -1,2 +1,2 @@ -BUILD_SDK_VERSION = 33 +BUILD_SDK_VERSION = 34 BUILD_TOOLS_VERSION = "32.0.0" diff --git a/version.bzl b/version.bzl index cd5a9094511..e022394e9fd 100644 --- a/version.bzl +++ b/version.bzl @@ -10,11 +10,11 @@ the app (that are potentially not broadly released yet). """ MAJOR_VERSION = 0 -MINOR_VERSION = 13 +MINOR_VERSION = 14 -OPPIA_DEV_VERSION_CODE = 172 -OPPIA_DEV_KITKAT_VERSION_CODE = 171 -OPPIA_ALPHA_VERSION_CODE = 170 -OPPIA_ALPHA_KITKAT_VERSION_CODE = 169 -OPPIA_BETA_VERSION_CODE = 168 -OPPIA_GA_VERSION_CODE = 167 +OPPIA_DEV_VERSION_CODE = 178 +OPPIA_DEV_KITKAT_VERSION_CODE = 177 +OPPIA_ALPHA_VERSION_CODE = 176 +OPPIA_ALPHA_KITKAT_VERSION_CODE = 175 +OPPIA_BETA_VERSION_CODE = 174 +OPPIA_GA_VERSION_CODE = 173 From 1646f9f4252409074cc15c9d4c1d4d103e75677b Mon Sep 17 00:00:00 2001 From: Subhajit Mallick <153619690+subhajitxyz@users.noreply.github.com> Date: Mon, 20 Jan 2025 08:39:15 +0530 Subject: [PATCH 14/16] add string in ar, pt-rBR,sw --- app/src/main/res/values-ar/strings.xml | 1 + app/src/main/res/values-pt-rBR/strings.xml | 1 + app/src/main/res/values-sw/strings.xml | 1 + 3 files changed, 3 insertions(+) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 787723595ba..aea23c0abf9 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -673,4 +673,5 @@ في %s ، يمكنك الاستماع إلى الدروس! اختر لغة المقاطع الصوتية للاستماع إلى الدروس الخطوة 5 من 5 + العربية diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 63042bc8413..44955edf0b7 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -627,4 +627,5 @@ Em %s, você pode ouvir as lições! Selecione a lingua do áudio para ouvir às lições Passo 5 de 5 + Árabe diff --git a/app/src/main/res/values-sw/strings.xml b/app/src/main/res/values-sw/strings.xml index f827cae27ef..34358fa9eaa 100644 --- a/app/src/main/res/values-sw/strings.xml +++ b/app/src/main/res/values-sw/strings.xml @@ -434,4 +434,5 @@ <p>Ikiwa sauti yako haichezi</p><p><br></p><p>Angalia ili kuona kama programu imesasishwa:</p><ul><li> Nenda kwenye Hifadhi ya Michezo na uhakikishe kuwa programu imesasishwa hadi toleo lake jipya zaidi </li></ul><p><br></p><p>Angalia muunganisho wako wa mtandao:</p><ul><li> Iwapo muunganisho wako wa mtandao ni wa polepole, jaribu kuunganisha tena kwenye mtandao wako wa Wi-Fi au unganisha kwenye mtandao tofauti. Mtandao wa polepole unaweza kusababisha sauti kupakia kwa njia isiyo ya kawaida, na kuifanya iwe vigumu kucheza. </li></ul><p><br></p><p>Uliza Msimamizi aangalie kifaa chake na muunganisho wa mtandao:</p><ul><li> Wasiliana na Msimamizi ili asuluhishe kwa kutumia hatua hapo juu</li></ul><p><br></p><p>Tujulishe ikiwa bado una matatizo ya upakiaji:</p><ul><li> Ripoti tatizo kwa kuwasiliana nasi kwa admin@oppia.org. </li></ul> <p>Wasifu unapofutwa:</p><ol><li> Wasifu hauwezi kurejeshwa. </li><li> Taarifa ya wasifu kama vile jina, picha na maendeleo yatafutwa kabisa. </li></ol><p>Ili kufuta wasifu (bila kujumuisha <u>Msimamizi</u>):</p> <ol><li> Kutoka kwa Ukurasa wa Mwanzo wa Msimamizi, gusa kitufe cha menyu kilicho upande wa juu kushoto. </li><li> Gusa <strong>Vidhibiti vya Msimamizi</strong>. </li><li> Gusa <strong>Hariri Wasifu</strong>. </li><li> Gonga Wasifu ambao ungependa kufuta. </li><li> Katika sehemu ya chini ya skrini, gusa <strong>Ufutaji wa Wasifu</strong>. </li><li> Gusa <strong>Futa</strong> ili kuthibitisha kufuta.</li></ol><p><br></p><p>Kumbuka: <u>Msimamizi</u> pekee ndiye anayeweza kudhibiti wasifu.</p> <p>Ikiwa huwezi kupata swali lako au ungependa kuripoti hitilafu, wasiliana nasi kwa admin@oppia.org.</p> + Kiarabu From 7d148bc76c93a37779db73934229982f1e451073 Mon Sep 17 00:00:00 2001 From: Subhajit Mallick <153619690+subhajitxyz@users.noreply.github.com> Date: Mon, 20 Jan 2025 09:48:46 +0530 Subject: [PATCH 15/16] add string in pcm-rNG --- app/src/main/res/values-pcm-rNG/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-pcm-rNG/strings.xml b/app/src/main/res/values-pcm-rNG/strings.xml index 0774dae0c11..d8c66d7d466 100644 --- a/app/src/main/res/values-pcm-rNG/strings.xml +++ b/app/src/main/res/values-pcm-rNG/strings.xml @@ -583,4 +583,5 @@ Lock Icon Download Status html Content + Arabic From 3e7dfb4e801d8dbc0d8250a5814900d1721b286f Mon Sep 17 00:00:00 2001 From: Subhajit Mallick <153619690+subhajitxyz@users.noreply.github.com> Date: Mon, 20 Jan 2025 10:43:37 +0530 Subject: [PATCH 16/16] add path rVIEW_MODELS_WITH_RESOURCE_IMPORTS in build.bazel --- app/BUILD.bazel | 2 +- app/src/main/res/values-ar/strings.xml | 1 - app/src/main/res/values-pcm-rNG/strings.xml | 1 - app/src/main/res/values-pt-rBR/strings.xml | 1 - app/src/main/res/values-sw/strings.xml | 1 - 5 files changed, 1 insertion(+), 5 deletions(-) diff --git a/app/BUILD.bazel b/app/BUILD.bazel index 7405410cf3e..780deaee405 100644 --- a/app/BUILD.bazel +++ b/app/BUILD.bazel @@ -215,6 +215,7 @@ VIEW_MODELS_WITH_RESOURCE_IMPORTS = [ "src/main/java/org/oppia/android/app/onboarding/OnboadingSlideViewModel.kt", "src/main/java/org/oppia/android/app/onboarding/OnboardingViewModel.kt", "src/main/java/org/oppia/android/app/ongoingtopiclist/OngoingTopicItemViewModel.kt", + "src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt", "src/main/java/org/oppia/android/app/options/OptionsReadingTextSizeViewModel.kt", "src/main/java/org/oppia/android/app/options/TextSizeItemViewModel.kt", "src/main/java/org/oppia/android/app/parser/FractionParsingUiError.kt", @@ -310,7 +311,6 @@ VIEW_MODELS = [ "src/main/java/org/oppia/android/app/ongoingtopiclist/OngoingTopicListViewModel.kt", "src/main/java/org/oppia/android/app/options/AppLanguageItemViewModel.kt", "src/main/java/org/oppia/android/app/options/AppLanguageSelectionViewModel.kt", - "src/main/java/org/oppia/android/app/options/AudioLanguageItemViewModel.kt", "src/main/java/org/oppia/android/app/options/AudioLanguageSelectionViewModel.kt", "src/main/java/org/oppia/android/app/options/OptionControlsViewModel.kt", "src/main/java/org/oppia/android/app/options/OptionsAppLanguageViewModel.kt", diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index aea23c0abf9..787723595ba 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -673,5 +673,4 @@ في %s ، يمكنك الاستماع إلى الدروس! اختر لغة المقاطع الصوتية للاستماع إلى الدروس الخطوة 5 من 5 - العربية diff --git a/app/src/main/res/values-pcm-rNG/strings.xml b/app/src/main/res/values-pcm-rNG/strings.xml index d8c66d7d466..0774dae0c11 100644 --- a/app/src/main/res/values-pcm-rNG/strings.xml +++ b/app/src/main/res/values-pcm-rNG/strings.xml @@ -583,5 +583,4 @@ Lock Icon Download Status html Content - Arabic diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 44955edf0b7..63042bc8413 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -627,5 +627,4 @@ Em %s, você pode ouvir as lições! Selecione a lingua do áudio para ouvir às lições Passo 5 de 5 - Árabe diff --git a/app/src/main/res/values-sw/strings.xml b/app/src/main/res/values-sw/strings.xml index 34358fa9eaa..f827cae27ef 100644 --- a/app/src/main/res/values-sw/strings.xml +++ b/app/src/main/res/values-sw/strings.xml @@ -434,5 +434,4 @@ <p>Ikiwa sauti yako haichezi</p><p><br></p><p>Angalia ili kuona kama programu imesasishwa:</p><ul><li> Nenda kwenye Hifadhi ya Michezo na uhakikishe kuwa programu imesasishwa hadi toleo lake jipya zaidi </li></ul><p><br></p><p>Angalia muunganisho wako wa mtandao:</p><ul><li> Iwapo muunganisho wako wa mtandao ni wa polepole, jaribu kuunganisha tena kwenye mtandao wako wa Wi-Fi au unganisha kwenye mtandao tofauti. Mtandao wa polepole unaweza kusababisha sauti kupakia kwa njia isiyo ya kawaida, na kuifanya iwe vigumu kucheza. </li></ul><p><br></p><p>Uliza Msimamizi aangalie kifaa chake na muunganisho wa mtandao:</p><ul><li> Wasiliana na Msimamizi ili asuluhishe kwa kutumia hatua hapo juu</li></ul><p><br></p><p>Tujulishe ikiwa bado una matatizo ya upakiaji:</p><ul><li> Ripoti tatizo kwa kuwasiliana nasi kwa admin@oppia.org. </li></ul> <p>Wasifu unapofutwa:</p><ol><li> Wasifu hauwezi kurejeshwa. </li><li> Taarifa ya wasifu kama vile jina, picha na maendeleo yatafutwa kabisa. </li></ol><p>Ili kufuta wasifu (bila kujumuisha <u>Msimamizi</u>):</p> <ol><li> Kutoka kwa Ukurasa wa Mwanzo wa Msimamizi, gusa kitufe cha menyu kilicho upande wa juu kushoto. </li><li> Gusa <strong>Vidhibiti vya Msimamizi</strong>. </li><li> Gusa <strong>Hariri Wasifu</strong>. </li><li> Gonga Wasifu ambao ungependa kufuta. </li><li> Katika sehemu ya chini ya skrini, gusa <strong>Ufutaji wa Wasifu</strong>. </li><li> Gusa <strong>Futa</strong> ili kuthibitisha kufuta.</li></ol><p><br></p><p>Kumbuka: <u>Msimamizi</u> pekee ndiye anayeweza kudhibiti wasifu.</p> <p>Ikiwa huwezi kupata swali lako au ungependa kuripoti hitilafu, wasiliana nasi kwa admin@oppia.org.</p> - Kiarabu