Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
f3e8961
New layout for auth
adhiamboperes Mar 18, 2025
471e1a6
Merge remote-tracking branch 'upstream/develop' into redesign-pin-input
adhiamboperes Apr 26, 2025
14296af
Add compose livedata dependency
adhiamboperes May 2, 2025
cb7936f
Create color and string resources
adhiamboperes May 2, 2025
b10ae81
Create xml layouts
adhiamboperes May 2, 2025
5a366f1
Create ProfileLoginActivity
adhiamboperes May 2, 2025
83f3762
Create ProfileLoginFragment
adhiamboperes May 2, 2025
c384747
Refactor login intent to new ProfileLoginActivity
adhiamboperes May 2, 2025
a691304
Add todos to track cleanup
adhiamboperes May 2, 2025
eec9434
Cleanup unused items
adhiamboperes May 2, 2025
99e1a19
Add admin reset pin flow
adhiamboperes May 4, 2025
a93542a
Add route to non-admin reset pin flow
adhiamboperes May 4, 2025
1ea182a
Add non-admin pin reset flow
adhiamboperes May 4, 2025
69973d1
wip commit
adhiamboperes May 5, 2025
b393870
Merge branch 'develop' of github.com:oppia/oppia-android into redesig…
adhiamboperes May 5, 2025
f00119d
Create AdminIntroActivity
adhiamboperes May 5, 2025
8d6139a
Create AdminIntroFragment
adhiamboperes May 5, 2025
2796aa4
Correct ktlint errors
adhiamboperes May 5, 2025
3cff4d1
Add navigation to the screen
adhiamboperes May 5, 2025
9145b20
Create the screen components
adhiamboperes May 5, 2025
44d77bf
Add navigation to the next screen
adhiamboperes May 5, 2025
9ef0501
Add activity tests
adhiamboperes May 15, 2025
734c9ab
Add fragment tests
adhiamboperes May 21, 2025
d894646
Break down large composables
adhiamboperes May 22, 2025
a0ca9de
Add tests for login flow
adhiamboperes May 22, 2025
0524005
Move dialogs to own files
adhiamboperes May 22, 2025
3c7e3ff
Add tests for dialog flows: wip for non-admin
adhiamboperes May 22, 2025
a83c10b
Add todo to ensure an admin profile is created when all profile data …
adhiamboperes May 22, 2025
09bfe8c
Fix lint issues
adhiamboperes May 22, 2025
a4e9208
Fix static analysis checks failures
adhiamboperes May 23, 2025
e0a697e
Fix ProfileChooserFragmentTest failures
adhiamboperes May 23, 2025
6680a9c
Finish dialog tests
adhiamboperes May 23, 2025
7523db0
Merge branch 'develop' of github.com:oppia/oppia-android into redesig…
adhiamboperes May 23, 2025
828e042
Format dagger modules
adhiamboperes May 23, 2025
c1f6619
Fix missing dagger module
adhiamboperes May 23, 2025
139723f
Merge remote-tracking branch 'upstream/redesign-pin-input' into creat…
adhiamboperes May 23, 2025
1f58671
Ensure navigation is correct
adhiamboperes May 24, 2025
bfb32f3
Cleanup navigation and add tests for all changes
adhiamboperes May 26, 2025
d75fdb5
Fix UI and failing tests
adhiamboperes May 27, 2025
432f3d7
fix trim spannable bug
adhiamboperes May 27, 2025
4e4315f
Merge branch 'develop' of github.com:oppia/oppia-android into develop
adhiamboperes Jun 6, 2025
bff3c08
Merge branch 'develop' into redesign-pin-input
adhiamboperes Jun 6, 2025
fc3c28c
Merge branch 'redesign-pin-input' into create-admin-intro
adhiamboperes Jun 6, 2025
7d781b4
Merge branch 'develop' into redesign-pin-input
adhiamboperes Jun 30, 2025
98372c9
Generate a new maven_install due to conflicts in the old one.
adhiamboperes Jun 30, 2025
d6cc784
regenerate maven_install.json
adhiamboperes Jun 30, 2025
8dbe1ec
address reviewer comment.
adhiamboperes Jul 1, 2025
92efbaf
Revert unrelated changed
adhiamboperes Jul 1, 2025
99eeafb
fix tests
adhiamboperes Jul 1, 2025
7971ea4
Merge branch 'develop' into redesign-pin-input
adhiamboperes Jul 1, 2025
39efe71
Merge branch 'redesign-pin-input' into create-admin-intro
adhiamboperes Jul 1, 2025
54304b3
Merge branch 'develop' into redesign-pin-input
adhiamboperes Jul 1, 2025
f14fdbf
fix conflicts
adhiamboperes Jul 1, 2025
f6c3ce4
Repin dependencies
adhiamboperes Jul 1, 2025
d3be083
Merge branch 'redesign-pin-input' of github.com:oppia/oppia-android i…
adhiamboperes Jul 1, 2025
9d00c2f
Merge branch 'redesign-pin-input' into create-admin-intro
adhiamboperes Jul 1, 2025
299376c
Fix ktlint issue
adhiamboperes Jul 1, 2025
db6e2aa
Fix file formatting
adhiamboperes Jul 2, 2025
ef109b7
Merge branch 'develop' into redesign-pin-input
adhiamboperes Jul 3, 2025
4b42e64
Exempt files from coverage.
adhiamboperes Jul 3, 2025
da39e88
Address reviewer comments
adhiamboperes Jul 3, 2025
d9cd074
Fix coverage failures
adhiamboperes Jul 3, 2025
f51dda6
Merge branch 'redesign-pin-input' into create-admin-intro
adhiamboperes Jul 4, 2025
fd1740c
Minor cleanup
adhiamboperes Jul 4, 2025
c452f8d
Fix Kdoc validity check
adhiamboperes Jul 4, 2025
fd9e76f
Fix navigation bug
adhiamboperes Jul 4, 2025
d69d67f
Fix wavy background
adhiamboperes Jul 4, 2025
19320b9
Fix lint checks
adhiamboperes Jul 4, 2025
a0e3293
Merge branch 'develop' into redesign-pin-input
adhiamboperes Jul 8, 2025
e672fe2
Merge branch 'redesign-pin-input' into create-admin-intro
adhiamboperes Jul 8, 2025
b745269
Merge branch 'develop' into redesign-pin-input
adhiamboperes Jul 15, 2025
b5ef741
Merge branch 'redesign-pin-input' into create-admin-intro
adhiamboperes Jul 15, 2025
696089e
Merge branch 'develop' of github.com:oppia/oppia-android into redesig…
adhiamboperes Aug 16, 2025
cf03541
Merge branch 'develop' into redesign-pin-input
adhiamboperes Aug 22, 2025
7a2928a
Use use {} block for scenario
adhiamboperes Aug 25, 2025
cc2b32f
Remove test tags
adhiamboperes Aug 25, 2025
8b2e18b
Merge branch 'develop' of github.com:oppia/oppia-android into redesig…
adhiamboperes Aug 25, 2025
82e0ba2
Merge branch 'redesign-pin-input' of github.com:oppia/oppia-android i…
adhiamboperes Aug 25, 2025
3ff1286
Add lint exemption
adhiamboperes Aug 25, 2025
4589f9e
Merge branch 'develop' of github.com:oppia/oppia-android into redesig…
adhiamboperes Sep 1, 2025
50f62cd
Add comments explaining test tag usage
adhiamboperes Sep 1, 2025
f8670b9
fix kdoc formatting
adhiamboperes Sep 1, 2025
99ef626
add comment
adhiamboperes Sep 7, 2025
252a05b
resolve merge conflicts from develop
adhiamboperes Sep 7, 2025
1373660
Remove duplicate tests
adhiamboperes Sep 8, 2025
1a03d92
Merge remote-tracking branch 'upstream/develop' into redesign-pin-input
adhiamboperes Sep 8, 2025
8963a2a
Merge branch 'redesign-pin-input' into create-admin-intro
adhiamboperes Sep 8, 2025
e9601f1
Fix indentation issue
adhiamboperes Sep 8, 2025
a306113
General cleanup.
adhiamboperes Sep 8, 2025
eb930d3
Refactor some intents.
adhiamboperes Sep 8, 2025
761a0b3
Ensure the newly created admin name is picked up by the profile chooser.
adhiamboperes Sep 9, 2025
9c172ce
Refactor complete onboarding logic and update tests
adhiamboperes Sep 9, 2025
3841366
Update AdminIntroFragmentTest tests
adhiamboperes Sep 9, 2025
e0659f0
Update CreateProfileFragmentTest tests
adhiamboperes Sep 9, 2025
3e20653
fix failing tests
adhiamboperes Sep 15, 2025
ad84072
address reviewer comments
adhiamboperes Sep 15, 2025
ed7e0e6
Update admin profile creation and profile choose launch
adhiamboperes Sep 15, 2025
184a956
Fix failing admin intro test and lint errors
adhiamboperes Sep 15, 2025
054ad99
Fix failing OnboardingProfileTypeFragmentTest tests
adhiamboperes Sep 15, 2025
e639c2d
Merge branch 'develop' into create-admin-intro
adhiamboperes Sep 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,10 @@
android:name=".app.profile.ProfileLoginActivity"
android:label="@string/profile_login_activity_title"
android:theme="@style/OppiaThemeWithoutActionBar" />
<activity
android:name=".app.onboarding.AdminIntroActivity"
android:label="@string/admin_intro_activity_title"
android:theme="@style/OppiaThemeWithoutActionBar" />
<activity
android:name=".app.testing.TextInputLayoutBindingAdaptersTestActivity"
android:theme="@style/OppiaThemeWithoutActionBar" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import org.oppia.android.app.help.thirdparty.ThirdPartyDependencyListActivity
import org.oppia.android.app.home.HomeActivity
import org.oppia.android.app.home.recentlyplayed.RecentlyPlayedActivity
import org.oppia.android.app.mydownloads.MyDownloadsActivity
import org.oppia.android.app.onboarding.AdminIntroActivity
import org.oppia.android.app.onboarding.CreateProfileActivity
import org.oppia.android.app.onboarding.IntroActivity
import org.oppia.android.app.onboarding.OnboardingActivity
Expand Down Expand Up @@ -232,4 +233,5 @@ interface ActivityComponentImpl :
fun inject(createProfileActivity: CreateProfileActivity)
fun inject(introActivity: IntroActivity)
fun inject(profileLoginActivity: ProfileLoginActivity)
fun inject(adminIntroActivity: AdminIntroActivity)
}
Original file line number Diff line number Diff line change
Expand Up @@ -275,13 +275,27 @@ class ClassroomListFragmentPresenter @Inject constructor(
val profile = result.value
val profileType = profile.profileType

if (enableOnboardingFlowV2.value && !profile.completedProfileOnboarding) {
// These asynchronous API calls do not block or wait for their results. They execute in
// the background and have minimal chances of interfering with the synchronous
// `handleBackPress` call below.
profileManagementController.markProfileOnboardingEnded(profileId)
if (profileType == ProfileType.SOLE_LEARNER || profileType == ProfileType.SUPERVISOR) {
appStartupStateController.markOnboardingFlowCompleted(profileId)
if (enableOnboardingFlowV2.value) {
when {
profileType == ProfileType.SUPERVISOR && profile.numberOfLogins == 1 -> {
// Supervisors end profile onboarding on the profiles list screen, but they do
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Supervisors end profile onboarding on the profiles list screen, but they do
// Supervisors end profile onboarding on the profiles list screen, but they do

Small nit.

// complete app onboarding here.
appStartupStateController.markOnboardingFlowCompleted(profileId)
}
profileType == ProfileType.SOLE_LEARNER && !profile.completedProfileOnboarding -> {
// Sole learners both end profile onboarding and complete app onboarding here.
// These asynchronous API calls do not block or wait for their results. They execute
// in the background and have minimal chances of interfering with the synchronous
// `handleBackPress` call below.
profileManagementController.markProfileOnboardingEnded(profileId)
appStartupStateController.markOnboardingFlowCompleted(profileId)
}
profileType == ProfileType.ADDITIONAL_LEARNER &&
!profile.completedProfileOnboarding -> {
// Additional learners only end profile onboarding, since they will never be the first
// profile in the app.
profileManagementController.markProfileOnboardingEnded(profileId)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import org.oppia.android.app.notice.ForcedAppDeprecationNoticeDialogFragment
import org.oppia.android.app.notice.GeneralAvailabilityUpgradeNoticeDialogFragment
import org.oppia.android.app.notice.OptionalAppDeprecationNoticeDialogFragment
import org.oppia.android.app.notice.OsDeprecationNoticeDialogFragment
import org.oppia.android.app.onboarding.AdminIntroFragment
import org.oppia.android.app.onboarding.CreateProfileFragment
import org.oppia.android.app.onboarding.IntroFragment
import org.oppia.android.app.onboarding.OnboardingFragment
Expand Down Expand Up @@ -218,4 +219,5 @@ interface FragmentComponentImpl : FragmentComponent, ViewComponentBuilderInjecto
fun inject(createProfileFragment: CreateProfileFragment)
fun inject(introFragment: IntroFragment)
fun inject(profileLoginFragment: ProfileLoginFragment)
fun inject(adminIntroFragment: AdminIntroFragment)
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,27 @@ class HomeFragmentPresenter @Inject constructor(
val profile = result.value
val profileType = profile.profileType

if (enableOnboardingFlowV2.value && !profile.completedProfileOnboarding) {
// These asynchronous API calls do not block or wait for their results. They execute in
// the background and have minimal chances of interfering with the synchronous
// `handleBackPress` call below.
profileManagementController.markProfileOnboardingEnded(profileId)
if (profileType == ProfileType.SOLE_LEARNER || profileType == ProfileType.SUPERVISOR) {
appStartupStateController.markOnboardingFlowCompleted(profileId)
if (enableOnboardingFlowV2.value) {
when {
profileType == ProfileType.SUPERVISOR && profile.numberOfLogins == 1 -> {
// Supervisors end profile onboarding on the profiles list screen, but they do
// complete app onboarding here.
appStartupStateController.markOnboardingFlowCompleted(profileId)
}
profileType == ProfileType.SOLE_LEARNER && !profile.completedProfileOnboarding -> {
// Sole learners both end profile onboarding and complete app onboarding here.
// These asynchronous API calls do not block or wait for their results. They execute
// in the background and have minimal chances of interfering with the synchronous
// `handleBackPress` call below.
profileManagementController.markProfileOnboardingEnded(profileId)
appStartupStateController.markOnboardingFlowCompleted(profileId)
}
profileType == ProfileType.ADDITIONAL_LEARNER &&
!profile.completedProfileOnboarding -> {
// Additional learners only end profile onboarding, since they will never be the first
// profile in the app.
profileManagementController.markProfileOnboardingEnded(profileId)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.oppia.android.app.onboarding

import android.content.Context
import android.content.Intent
import android.os.Bundle
import org.oppia.android.app.activity.ActivityComponentImpl
import org.oppia.android.app.activity.InjectableAutoLocalizedAppCompatActivity
import org.oppia.android.app.model.AdminIntroActivityParams
import org.oppia.android.app.model.ProfileId
import org.oppia.android.app.model.ProfileType
import org.oppia.android.app.model.ScreenName.ADMIN_INTRO_ACTIVITY
import org.oppia.android.util.extensions.getProtoExtra
import org.oppia.android.util.extensions.putProtoExtra
import org.oppia.android.util.logging.CurrentAppScreenNameIntentDecorator.decorateWithScreenName
import org.oppia.android.util.profile.CurrentUserProfileIdIntentDecorator.decorateWithUserProfileId
import org.oppia.android.util.profile.CurrentUserProfileIdIntentDecorator.extractCurrentUserProfileId
import javax.inject.Inject

/** Argument key for [AdminIntroActivity] intent parameters. */
const val ADMIN_INTRO_PARAMS_KEY = "AdminIntroActivityParams.params"

/** Activity for displaying the admin onboarding screen. */
class AdminIntroActivity : InjectableAutoLocalizedAppCompatActivity() {

@Inject
lateinit var adminIntroActivityPresenter: AdminIntroActivityPresenter

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

(activityComponent as ActivityComponentImpl).inject(this)

val profileId = intent.extractCurrentUserProfileId()
val adminIntroActivityParams = intent.getProtoExtra(
ADMIN_INTRO_PARAMS_KEY, AdminIntroActivityParams.getDefaultInstance()
)
val profileType = adminIntroActivityParams.profileType
val profileNickname = adminIntroActivityParams.profileNickname

adminIntroActivityPresenter.handleOnCreate(profileId, profileType, profileNickname)
}

companion object {
/** Returns a new [Intent] to open an [AdminIntroActivity] with the specified params. */
fun createAdminIntroActivityIntent(
context: Context,
profileId: ProfileId,
profileType: ProfileType,
profileNickname: String
): Intent {
val introActivityParams = AdminIntroActivityParams.newBuilder()
.setProfileType(profileType)
.setProfileNickname(profileNickname)
.build()

return Intent(context, AdminIntroActivity::class.java).apply {
decorateWithScreenName(ADMIN_INTRO_ACTIVITY)
putProtoExtra(ADMIN_INTRO_PARAMS_KEY, introActivityParams)
decorateWithUserProfileId(profileId)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.oppia.android.app.onboarding

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import org.oppia.android.app.activity.ActivityScope
import org.oppia.android.app.model.AdminIntroFragmentArguments
import org.oppia.android.app.model.ProfileId
import org.oppia.android.app.model.ProfileType
import org.oppia.android.app.ui.R
import org.oppia.android.util.extensions.putProto
import org.oppia.android.util.profile.CurrentUserProfileIdIntentDecorator.decorateWithUserProfileId
import javax.inject.Inject

/** Argument key for [AdminIntroFragment] arguments. */
const val ADMIN_INTRO_FRAGMENT_ARGS = "AdminIntroFragment.args"

private const val TAG_ADMIN_INTRO_FRAGMENT = "TAG_ADMIN_INTRO_FRAGMENT"

/** The presenter for [AdminIntroActivity]. */
@ActivityScope
class AdminIntroActivityPresenter @Inject constructor(
private val activity: AppCompatActivity
) {

/** Creates the view for [AdminIntroActivity]. */
fun handleOnCreate(profileId: ProfileId, profileType: ProfileType, profileNickname: String) {
activity.setContentView(R.layout.admin_intro_activity)

if (getAdminIntroFragment() == null) {
val adminIntroFragment = AdminIntroFragment()

val args = Bundle().apply {
val fragmentArgs =
AdminIntroFragmentArguments.newBuilder()
.setProfileType(profileType)
.setProfileNickname(profileNickname)
.build()
putProto(ADMIN_INTRO_FRAGMENT_ARGS, fragmentArgs)
decorateWithUserProfileId(profileId)
}

adminIntroFragment.arguments = args

activity.supportFragmentManager.beginTransaction()
.add(
R.id.admin_intro_fragment_placeholder,
adminIntroFragment,
TAG_ADMIN_INTRO_FRAGMENT
)
.commitNow()
}
}

private fun getAdminIntroFragment(): AdminIntroFragment? {
return activity.supportFragmentManager.findFragmentByTag(
TAG_ADMIN_INTRO_FRAGMENT
) as? AdminIntroFragment
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.oppia.android.app.onboarding

import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import org.oppia.android.app.fragment.FragmentComponentImpl
import org.oppia.android.app.fragment.InjectableFragment
import org.oppia.android.app.model.AdminIntroFragmentArguments
import org.oppia.android.util.extensions.getProto
import org.oppia.android.util.profile.CurrentUserProfileIdIntentDecorator.extractCurrentUserProfileId
import javax.inject.Inject

/** Fragment that contains the admin intro screen. */
class AdminIntroFragment : InjectableFragment() {

@Inject
lateinit var adminIntroFragmentPresenter: AdminIntroFragmentPresenter

override fun onAttach(context: Context) {
super.onAttach(context)
(fragmentComponent as FragmentComponentImpl).inject(this)
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val profileId = checkNotNull(arguments?.extractCurrentUserProfileId()) {
"Expected profileId to be included in the arguments for AdminIntroFragment."
}

val adminIntroFragmentArguments = arguments?.getProto(
ADMIN_INTRO_FRAGMENT_ARGS, AdminIntroFragmentArguments.getDefaultInstance()
)

val profileType = checkNotNull(adminIntroFragmentArguments?.profileType) {
"Expected AdminIntroFragment to have a profileType argument."
}

val profileNickName = checkNotNull(adminIntroFragmentArguments?.profileNickname) {
"Expected AdminIntroFragment to have a profileNickName argument."
}

return adminIntroFragmentPresenter
.handleCreateView(inflater, container, profileId, profileType, profileNickName)
}
}
Loading
Loading