Fix Part of #4938: Create Admin PIN (4/12)#5880
Fix Part of #4938: Create Admin PIN (4/12)#5880adhiamboperes wants to merge 153 commits intodevelopfrom
Conversation
# Conflicts: # app/src/main/res/values/styles.xml
adhiamboperes
left a comment
There was a problem hiding this comment.
Self reviewed.
app/src/sharedTest/java/org/oppia/android/app/onboarding/AdminIntroFragmentTest.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/org/oppia/android/app/profile/CreateAdminPinFragmentPresenter.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/org/oppia/android/app/profile/CreateAdminPinFragmentPresenter.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/org/oppia/android/app/profile/CreateAdminPinFragmentPresenter.kt
Outdated
Show resolved
Hide resolved
|
|
||
| @OptIn(ExperimentalComposeUiApi::class) | ||
| @Composable | ||
| fun PinSetupScreen() { |
There was a problem hiding this comment.
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
onValueChangelogic extracted to named presenter functions. - the
CreateAdminPinScreenComposable 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 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. |
|
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. |
|
@BenHenning, could you PTAL at this PR? It is ready for review with the exception of |
|
@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. |
|
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? |
BenHenning
left a comment
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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.
| delay(100) | ||
| keyboardController?.show() |
There was a problem hiding this comment.
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.
| { | ||
| focusManager.clearFocus() | ||
| onDone?.invoke() | ||
| } |
There was a problem hiding this comment.
Unnecessary extra curly braces?
| else -> PinValidationResult( | ||
| isValid = false, | ||
| errorMessage = resourceHandler.getStringInLocaleWithWrapping( | ||
| R.string.create_admin_pin_activity_mismatch_error |
There was a problem hiding this comment.
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?
| private data class PinValidationResult( | ||
| val isValid: Boolean, | ||
| val errorMessage: String = "" | ||
| ) |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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() { |
| testCoroutineDispatchers.runCurrent() | ||
|
|
||
| composeRule | ||
| .onNodeWithText(context.getString(R.string.create_admin_pin_activity_blank_error)) |
There was a problem hiding this comment.
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.
| // The submit-time error message to display when show_error is true. | ||
| string error_message = 4; |
There was a problem hiding this comment.
Will this cause any problems with the user changing their system language while the activity is open?
| exempted_file_path: "app/src/main/java/org/oppia/android/app/profile/CreateAdminPinActivityPresenter.kt" | ||
| test_file_not_required: true |
|
Unassigning @BenHenning since the review is done. |
|
Hi @adhiamboperes, it looks like some changes were requested on this pull request by @BenHenning. PTAL. Thanks! |
|
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. |
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
For UI-specific PRs only
If your PR includes UI-related changes, then: