Skip to content

Fix Part of #4938: Create Admin PIN (4/12)#5880

Open
adhiamboperes wants to merge 153 commits intodevelopfrom
create-pin-setup
Open

Fix Part of #4938: Create Admin PIN (4/12)#5880
adhiamboperes wants to merge 153 commits intodevelopfrom
create-pin-setup

Conversation

@adhiamboperes
Copy link
Copy Markdown
Contributor

@adhiamboperes adhiamboperes commented Jul 4, 2025

Explanation

Fixes part of #4938

Introduces a new screen for creating an admin PIN during admin onboarding. This is the last step of admin onboarding.

The PR ensures there are validations to enforce correct PINs that are 5 digits long and that the user inputs and appropriate error messages are retained even on configuration changes.

There are additional changes that clean up the onboarding flow placeholders, and tests have been added where necessary.

Essential Checklist

  • 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 files have their rationale included in the PR explanation.
  • The PR follows the style guide.
  • The PR does not contain any unnecessary code changes from Android Studio (reference).
  • The PR is made from a branch that's not called "develop" and is up-to-date with "develop".
  • The PR is assigned to the appropriate reviewers (reference).

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)
  • Add a video showing the full UX flow with a screen reader enabled (see accessibility 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

Copy link
Copy Markdown
Contributor Author

@adhiamboperes adhiamboperes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Self reviewed.


@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun PinSetupScreen() {
Copy link
Copy Markdown
Contributor Author

@adhiamboperes adhiamboperes Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I refactored the entire class:

  • used protos for the UI data objects, but the actual error messages are derived on read. I however would like an opinion on where to store the proto. It currently lives in screens.proto.
  • all onValueChange logic extracted to named presenter functions.
  • the CreateAdminPinScreen Composable takes state + callbacks and owns nothing

The composables below CreateAdminPinScreen have no internal state. However, CreateAdminPinScreen itself still owns state via rememberSaveable, which means state hoisting hasn't been applied at the top level.

@adhiamboperes adhiamboperes marked this pull request as ready for review March 19, 2026 12:52
@github-actions
Copy link
Copy Markdown

@adhiamboperes this PR is being marked as draft because the PR description must contain 'Fixes #' or 'Fixes part of #' for each issue the PR is changing, and each one on its own line with no other text.

@oppiabot
Copy link
Copy Markdown

oppiabot bot commented Mar 26, 2026

Hi @adhiamboperes, I'm going to mark this PR as stale because it hasn't had any updates for 7 days. If no further activity occurs within 7 days, it will be automatically closed so that others can take up the issue.
If you are still working on this PR, please make a follow-up commit within 3 days (and submit it for review, if applicable). Please also let us know if you are stuck so we can help you! If you're unsure how to reassign this PR to a reviewer, please make sure to review the wiki page that details the Guidance on submitting PRs.

@oppiabot oppiabot bot added the stale Corresponds to items that haven't seen a recent update and may be automatically closed. label Mar 26, 2026
@oppiabot oppiabot bot closed this Mar 26, 2026
@adhiamboperes adhiamboperes reopened this Mar 31, 2026
@oppiabot oppiabot bot removed the stale Corresponds to items that haven't seen a recent update and may be automatically closed. label Mar 31, 2026
@adhiamboperes adhiamboperes marked this pull request as ready for review April 1, 2026 22:39
@adhiamboperes
Copy link
Copy Markdown
Contributor Author

@BenHenning, could you PTAL at this PR?

It is ready for review with the exception of app/src/sharedTest/java/org/oppia/android/app/profile/CreateAdminPinActivityTest.kt which fails with sigterm. So far, I have been unable to debug and fix it due to being unable to run tests locally.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

@adhiamboperes this PR is being marked as draft because the PR description must contain 'Fixes #' or 'Fixes part of #' for each issue the PR is changing, and each one on its own line with no other text.

@github-actions github-actions bot marked this pull request as draft April 1, 2026 22:43
@adhiamboperes
Copy link
Copy Markdown
Contributor Author

Also the issue assignment workflow is still failing despite this branch being up to date with develop.

@adhiamboperes adhiamboperes marked this pull request as ready for review April 1, 2026 22:54
@BenHenning
Copy link
Copy Markdown
Member

Also the issue assignment workflow is still failing despite this branch being up to date with develop.

@adhiamboperes it seems the regex check is case sensitive. Perhaps it will pass now?

Copy link
Copy Markdown
Member

@BenHenning BenHenning left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @adhiamboperes! Took a full pass, PTAL. I'll also respond to my earlier long comment (but can't as part of this review due to a GitHub bug).


@Test
fun testFragment_onLaunch_allTextViewsHaveCorrectContent() {
launch(CreateAdminPinActivity::class.java).use {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: it's ideal to test fragments in the context of a different activity. If it's easy I suggest using TestActivity for this purpose.

That might potentially help with figuring out the timeout, too, since it looks like (per CI) both the fragment and activity classes are hanging.

Comment on lines +137 to +138
delay(100)
keyboardController?.show()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the delay and explicit show actually necessary? Gemini seems to suggest that the delay is likely what's causing the deadlock with our coroutine dispatcher testing barrier which would cause the hanging. It seems to assume that these lines may be unnecessary because focusing the text view ought to be sufficient to open the keyboard automatically.

However, if this is called too soon it may need to be wrapped in a onGloballyPositioned so that focus happens after layout.

Comment on lines +259 to +262
{
focusManager.clearFocus()
onDone?.invoke()
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary extra curly braces?

else -> PinValidationResult(
isValid = false,
errorMessage = resourceHandler.getStringInLocaleWithWrapping(
R.string.create_admin_pin_activity_mismatch_error
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some repeat references to these strings. Is it possible to cleanly refactor to avoid repeating these such that each string is only referenced once?

Comment on lines +486 to +489
private data class PinValidationResult(
val isValid: Boolean,
val errorMessage: String = ""
)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional, but you could refine this a bit by leveraging a sealed class and also using a StringRes so that the string lookup only needs to happen in one place for the error:

private sealed class PinValidationResult {
  object Valid: PinValidationResult()
  data class Invalid(@StringRes val errorMessageId: Int): PinValidationResult()
}

private val resourceHandler: AppLanguageResourceHandler,
private val profileManagementController: ProfileManagementController
) {
private lateinit var binding: CreateAdminPinFragmentBinding
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually need to use databinding? It seems unnecessary looking at the layout file (and probably better to avoid it since I'm not exactly sure how well Compose and databinding will interoperate...).

}
}

fun testFragment_supervisorOnboardingFlow_stepCountThreeText_isDisplayed() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing @Test.

testCoroutineDispatchers.runCurrent()

composeRule
.onNodeWithText(context.getString(R.string.create_admin_pin_activity_blank_error))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm looking at these tests, I acknowledge they are quite clean however one issue I see is that there's a bit of a risk here. I think it's theoretically possible to show every related string to the new screen at one time and all of the tests will pass (or most will, there are a few assert not visible).

This is actually why I think it's important to validate specific views but I know Compose makes that tricky. I think we do need a solution for this but I'm not precisely sure what it is.

Comment on lines +207 to +208
// The submit-time error message to display when show_error is true.
string error_message = 4;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this cause any problems with the user changing their system language while the activity is open?

Comment on lines +2032 to +2033
exempted_file_path: "app/src/main/java/org/oppia/android/app/profile/CreateAdminPinActivityPresenter.kt"
test_file_not_required: true
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: missing spacing.

@oppiabot
Copy link
Copy Markdown

oppiabot bot commented Apr 3, 2026

Unassigning @BenHenning since the review is done.

@oppiabot
Copy link
Copy Markdown

oppiabot bot commented Apr 3, 2026

Hi @adhiamboperes, it looks like some changes were requested on this pull request by @BenHenning. PTAL. Thanks!

@oppiabot
Copy link
Copy Markdown

oppiabot bot commented Apr 10, 2026

Hi @adhiamboperes, I'm going to mark this PR as stale because it hasn't had any updates for 7 days. If no further activity occurs within 7 days, it will be automatically closed so that others can take up the issue.
If you are still working on this PR, please make a follow-up commit within 3 days (and submit it for review, if applicable). Please also let us know if you are stuck so we can help you! If you're unsure how to reassign this PR to a reviewer, please make sure to review the wiki page that details the Guidance on submitting PRs.

@oppiabot oppiabot bot added the stale Corresponds to items that haven't seen a recent update and may be automatically closed. label Apr 10, 2026
@adhiamboperes adhiamboperes removed the stale Corresponds to items that haven't seen a recent update and may be automatically closed. label Apr 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants