Skip to content

Commit

Permalink
Merge branch 'new-onboarding-ui' into onboarding-profile-configuration
Browse files Browse the repository at this point in the history
# Conflicts:
#	domain/src/main/java/org/oppia/android/domain/platformparameter/PlatformParameterAlphaKenyaModule.kt
#	domain/src/main/java/org/oppia/android/domain/platformparameter/PlatformParameterAlphaModule.kt
#	domain/src/main/java/org/oppia/android/domain/platformparameter/PlatformParameterModule.kt
#	testing/src/main/java/org/oppia/android/testing/platformparameter/TestPlatformParameterModule.kt
  • Loading branch information
adhiamboperes committed Jan 31, 2024
2 parents 6237fbb + 296c4d1 commit ea08ccb
Show file tree
Hide file tree
Showing 46 changed files with 1,282 additions and 176 deletions.
21 changes: 15 additions & 6 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<!-- TODO(#56): Reenable landscape support. -->
<application
android:name=".app.application.dev.DeveloperOppiaApplication"
Expand All @@ -16,14 +15,19 @@
android:supportsRtl="true"
android:theme="@style/OppiaTheme">
<!-- NOTE TO DEVELOPER: You can enable debug logs for fast upload & better inspection in Firebase console using https://support.google.com/analytics/answer/7201382. -->
<meta-data android:name="firebase_analytics_collection_deactivated" android:value="true" />
<meta-data android:name="firebase_crashlytics_collection_enabled" android:value="false" />
<meta-data
android:name="firebase_analytics_collection_deactivated"
android:value="true" />
<meta-data
android:name="firebase_crashlytics_collection_enabled"
android:value="false" />
<meta-data
android:name="automatic_app_expiration_enabled"
android:value="false" />
<meta-data
android:name="expiration_date"
android:value="2020-09-01" />

<activity
android:name=".app.administratorcontrols.AdministratorControlsActivity"
android:label="@string/administrator_controls_title"
Expand All @@ -43,7 +47,7 @@
<activity
android:name=".app.administratorcontrols.learneranalytics.ProfileAndDeviceIdActivity"
android:label="@string/profile_and_device_id_activity_title"
android:theme="@style/OppiaThemeWithoutActionBar"/>
android:theme="@style/OppiaThemeWithoutActionBar" />
<activity
android:name=".app.completedstorylist.CompletedStoryListActivity"
android:label="@string/completed_story_list_activity_title"
Expand Down Expand Up @@ -187,9 +191,9 @@
android:theme="@style/OppiaThemeWithoutActionBar" />
<activity
android:name=".app.splash.SplashActivity"
android:exported="true"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:exported="true"
android:theme="@style/SplashScreenTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand Down Expand Up @@ -308,7 +312,8 @@
<activity
android:name=".app.devoptions.forcenetworktype.testing.ForceNetworkTypeTestActivity"
android:theme="@style/OppiaThemeWithoutActionBar" />
<activity android:name=".app.policies.PoliciesActivity"
<activity
android:name=".app.policies.PoliciesActivity"
android:label="@string/policy_activity_title"
android:theme="@style/OppiaThemeWithoutActionBar" />
<activity
Expand All @@ -327,6 +332,10 @@
android:label="@string/survey_activity_title"
android:theme="@style/OppiaThemeWithoutActionBar"
android:windowSoftInputMode="adjustNothing" />
<activity
android:name=".app.onboarding.onboardingv2.OnboardingProfileTypeActivity"
android:label="@string/onboarding_profile_type_activity_title"
android:theme="@style/OppiaThemeWithoutActionBar" />

<provider
android:name="androidx.work.impl.WorkManagerInitializer"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ 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.OnboardingActivity
import org.oppia.android.app.onboarding.onboardingv2.OnboardingProfileTypeActivity
import org.oppia.android.app.ongoingtopiclist.OngoingTopicListActivity
import org.oppia.android.app.options.AppLanguageActivity
import org.oppia.android.app.options.AudioLanguageActivity
Expand Down Expand Up @@ -212,4 +213,5 @@ interface ActivityComponentImpl :
fun inject(viewEventLogsTestActivity: ViewEventLogsTestActivity)
fun inject(walkthroughActivity: WalkthroughActivity)
fun inject(surveyActivity: SurveyActivity)
fun inject(onboardingProfileTypeActivity: OnboardingProfileTypeActivity)
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package org.oppia.android.app.customview

import android.content.Context
import android.content.res.TypedArray
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.util.AttributeSet
import android.view.View
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
Expand All @@ -18,33 +18,35 @@ import org.oppia.android.app.view.ViewComponentImpl
import javax.inject.Inject

/**
* CustomView to add a background to [SurveyWelcomeDialogFragment] and [SurveyOutroDialogFragment].
* Without chaptersFinished and totalChapters values this custom-view cannot be created.
* CustomView to add a background to views that require a bezier curve background.
*
* Reference: // https://proandroiddev.com/how-i-drew-custom-shapes-in-bottom-bar-c4539d86afd7 and
* // https://ciechanow.ski/drawing-bezier-curves/
*/
class SurveyOnboardingBackgroundView : View {
class OppiaCurveBackgroundView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
@Inject
lateinit var resourceHandler: AppLanguageResourceHandler

private val isRtl by lazy {
resourceHandler.getLayoutDirection() == ViewCompat.LAYOUT_DIRECTION_RTL
}

private var customBackgroundColor = Color.WHITE // Default color

private lateinit var paint: Paint
private lateinit var path: Path
private var strokeWidth = 2f

constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)

init {
val typedArray: TypedArray =
context.obtainStyledAttributes(attrs, R.styleable.OppiaCurveBackgroundView)
customBackgroundColor =
typedArray.getColor(R.styleable.OppiaCurveBackgroundView_customBackgroundColor, Color.WHITE)
typedArray.recycle()
setupCurvePaint()
}

Expand All @@ -61,13 +63,13 @@ class SurveyOnboardingBackgroundView : View {
val width = this.width.toFloat()
val height = this.height.toFloat()

val controlPoint1X = width * 0.5f
val controlPoint1X = width * 0.4f
val controlPoint1Y = 0f

val controlPoint2X = width * 0.5f
val controlPoint2Y = height * 0.2f
val controlPoint2Y = height * 0.15f

val controlPoint3X = width * 1f
val controlPoint3X = width * 1.2f
val controlPoint3Y = height * 0.1f

path.reset()
Expand All @@ -91,11 +93,8 @@ class SurveyOnboardingBackgroundView : View {
paint = Paint(Paint.ANTI_ALIAS_FLAG)
paint.apply {
style = Paint.Style.FILL_AND_STROKE
strokeWidth = this@SurveyOnboardingBackgroundView.strokeWidth
color = ContextCompat.getColor(
context,
R.color.component_color_survey_popup_background_color
)
strokeWidth = this@OppiaCurveBackgroundView.strokeWidth
color = customBackgroundColor
}
setBackgroundColor(Color.TRANSPARENT)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import org.oppia.android.app.notice.GeneralAvailabilityUpgradeNoticeDialogFragme
import org.oppia.android.app.notice.OptionalAppDeprecationNoticeDialogFragment
import org.oppia.android.app.notice.OsDeprecationNoticeDialogFragment
import org.oppia.android.app.onboarding.OnboardingFragment
import org.oppia.android.app.onboarding.onboardingv2.OnboardingProfileTypeFragment
import org.oppia.android.app.ongoingtopiclist.OngoingTopicListFragment
import org.oppia.android.app.options.AppLanguageFragment
import org.oppia.android.app.options.AudioLanguageFragment
Expand Down Expand Up @@ -194,4 +195,5 @@ interface FragmentComponentImpl : FragmentComponent, ViewComponentBuilderInjecto
fun inject(exitSurveyConfirmationDialogFragment: ExitSurveyConfirmationDialogFragment)
fun inject(surveyWelcomeDialogFragment: SurveyWelcomeDialogFragment)
fun inject(surveyOutroDialogFragment: SurveyOutroDialogFragment)
fun inject(onboardingProfileTypeFragment: OnboardingProfileTypeFragment)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,23 @@ 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.util.platformparameter.EnableOnboardingFlowV2
import org.oppia.android.util.platformparameter.PlatformParameterValue
import javax.inject.Inject
import org.oppia.android.app.onboarding.onboardingv2.OnboardingFragmentPresenter as OnboardingFragmentPresenterV2

/** Fragment that contains an onboarding flow of the app. */
class OnboardingFragment : InjectableFragment() {
@Inject
lateinit var onboardingFragmentPresenter: OnboardingFragmentPresenter

@Inject
lateinit var onboardingFragmentPresenterV2: OnboardingFragmentPresenterV2

@Inject
@field:EnableOnboardingFlowV2
lateinit var enableOnboardingFlowV2: PlatformParameterValue<Boolean>

override fun onAttach(context: Context) {
super.onAttach(context)
(fragmentComponent as FragmentComponentImpl).inject(this)
Expand All @@ -24,6 +34,10 @@ class OnboardingFragment : InjectableFragment() {
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return onboardingFragmentPresenter.handleCreateView(inflater, container)
return if (enableOnboardingFlowV2.value) {
onboardingFragmentPresenterV2.handleCreateView(inflater, container)
} else {
onboardingFragmentPresenter.handleCreateView(inflater, container)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class OnboardingFragmentPresenter @Inject constructor(
}
setUpViewPager()
addDots()

return binding.root
}

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

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import org.oppia.android.R
import org.oppia.android.app.fragment.FragmentScope
import org.oppia.android.app.onboarding.OnboardingViewModel
import org.oppia.android.app.viewmodel.ViewModelProvider
import org.oppia.android.databinding.OnboardingAppLanguageSelectionFragmentBinding
import javax.inject.Inject

/** The presenter for [OnboardingFragment] V2. */
@FragmentScope
class OnboardingFragmentPresenter @Inject constructor(
private val activity: AppCompatActivity,
private val fragment: Fragment,
private val viewModelProvider: ViewModelProvider<OnboardingViewModel>
) {
private lateinit var binding: OnboardingAppLanguageSelectionFragmentBinding

fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View {
binding = OnboardingAppLanguageSelectionFragmentBinding.inflate(
inflater,
container,
/* attachToRoot= */ false
)
// NB: Both the view model and lifecycle owner must be set in order to correctly bind LiveData elements to
// data-bound view models.
binding.let {
it.lifecycleOwner = fragment
}

binding.onboardingLanguageDropdown.adapter = ArrayAdapter(
fragment.requireContext(),
R.layout.onboarding_language_dropdown_item,
R.id.onboarding_language_text_view,
arrayOf("English")
)

binding.onboardingLanguageLetsGoButton.setOnClickListener {
val intent = OnboardingProfileTypeActivity.createOnboardingProfileTypeActivityIntent(activity)
fragment.startActivity(intent)
}

return binding.root
}

private fun getOnboardingViewModel(): OnboardingViewModel {
return viewModelProvider.getForFragment(fragment, OnboardingViewModel::class.java)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.oppia.android.app.onboarding.onboardingv2

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.ScreenName
import org.oppia.android.util.logging.CurrentAppScreenNameIntentDecorator.decorateWithScreenName
import javax.inject.Inject

/** The activity for showing the profile type selection screen. */
class OnboardingProfileTypeActivity : InjectableAutoLocalizedAppCompatActivity() {
@Inject
lateinit var onboardingProfileTypeActivityPresenter: OnboardingProfileTypeActivityPresenter

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
(activityComponent as ActivityComponentImpl).inject(this)

onboardingProfileTypeActivityPresenter.handleOnCreate()
}

companion object {
/** Returns a new [Intent] open a [OnboardingProfileTypeActivity] with the specified params. */
fun createOnboardingProfileTypeActivityIntent(context: Context): Intent {
return Intent(context, OnboardingProfileTypeActivity::class.java).apply {
decorateWithScreenName(ScreenName.ONBOARDING_PROFILE_TYPE_ACTIVITY)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.oppia.android.app.onboarding.onboardingv2

import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import org.oppia.android.R
import org.oppia.android.app.activity.ActivityScope
import org.oppia.android.databinding.OnboardingProfileTypeActivityBinding
import javax.inject.Inject

private const val TAG_PROFILE_TYPE_FRAGMENT = "TAG_PROFILE_TYPE_FRAGMENT"

/** The Presenter for [OnboardingProfileTypeActivity]. */
@ActivityScope
class OnboardingProfileTypeActivityPresenter @Inject constructor(
private val activity: AppCompatActivity
) {
private lateinit var binding: OnboardingProfileTypeActivityBinding

/** Handle creation and binding of the OnboardingProfileTypeActivity layout. */
fun handleOnCreate() {
binding = DataBindingUtil.setContentView(activity, R.layout.onboarding_profile_type_activity)
binding.apply {
lifecycleOwner = activity
}

if (getOnboardingProfileTypeFragment() == null) {
val onboardingProfileTypeFragment = OnboardingProfileTypeFragment()
activity.supportFragmentManager.beginTransaction().add(
R.id.profile_type_fragment_placeholder,
onboardingProfileTypeFragment,
TAG_PROFILE_TYPE_FRAGMENT
)
.commitNow()
}
}

private fun getOnboardingProfileTypeFragment(): OnboardingProfileTypeFragment? {
return activity.supportFragmentManager.findFragmentByTag(
TAG_PROFILE_TYPE_FRAGMENT
) as? OnboardingProfileTypeFragment
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.oppia.android.app.onboarding.onboardingv2

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 javax.inject.Inject

/** Fragment that contains an onboarding flow of the app. */
class OnboardingProfileTypeFragment : InjectableFragment() {
@Inject
lateinit var onboardingProfileTypeFragmentPresenter: OnboardingProfileTypeFragmentPresenter

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

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return onboardingProfileTypeFragmentPresenter.handleCreateView(inflater, container)
}
}
Loading

0 comments on commit ea08ccb

Please sign in to comment.