diff --git a/app/BUILD.bazel b/app/BUILD.bazel index 1e4620c4821..cfa6c0b3c47 100644 --- a/app/BUILD.bazel +++ b/app/BUILD.bazel @@ -408,9 +408,9 @@ VIEWS_WITH_RESOURCE_IMPORTS = [ "src/main/java/org/oppia/android/app/customview/ChapterNotStartedContainerConstraintLayout.kt", "src/main/java/org/oppia/android/app/customview/ContinueButtonView.kt", "src/main/java/org/oppia/android/app/customview/LessonThumbnailImageView.kt", + "src/main/java/org/oppia/android/app/customview/OppiaCurveBackgroundView.kt", "src/main/java/org/oppia/android/app/customview/PromotedStoryCardView.kt", "src/main/java/org/oppia/android/app/customview/SegmentedCircularProgressView.kt", - "src/main/java/org/oppia/android/app/customview/SurveyOnboardingBackgroundView.kt", "src/main/java/org/oppia/android/app/customview/VerticalDashedLineView.kt", "src/main/java/org/oppia/android/app/survey/SurveyMultipleChoiceOptionView.kt", "src/main/java/org/oppia/android/app/survey/SurveyNpsItemOptionView.kt", @@ -485,6 +485,7 @@ BINDING_ADAPTERS_WITH_RESOURCE_IMPORTS = [ BINDING_ADAPTERS = [ "src/main/java/org/oppia/android/app/databinding/AppCompatCheckBoxBindingAdapters.java", "src/main/java/org/oppia/android/app/databinding/CircularProgressIndicatorAdapters.java", + "src/main/java/org/oppia/android/app/databinding/ColorBindingAdapters.java", "src/main/java/org/oppia/android/app/databinding/ConstraintLayoutAdapters.java", "src/main/java/org/oppia/android/app/databinding/EditTextBindingAdapters.java", "src/main/java/org/oppia/android/app/databinding/GuidelineBindingAdapters.java", diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 41d1ce55918..b85115c35a1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -329,6 +329,9 @@ android:label="@string/survey_activity_title" android:theme="@style/OppiaThemeWithoutActionBar" android:windowSoftInputMode="adjustNothing" /> + + override fun onAttach(context: Context) { super.onAttach(context) (fragmentComponent as FragmentComponentImpl).inject(this) @@ -24,6 +33,10 @@ class OnboardingFragment : InjectableFragment() { container: ViewGroup?, savedInstanceState: Bundle? ): View? { - return onboardingFragmentPresenter.handleCreateView(inflater, container) + return if (enableOnboardingFlowV2.value) { + onboardingFragmentPresenter.handleCreateView(inflater, container) + } else { + onboardingFragmentPresenterV1.handleCreateView(inflater, container) + } } } diff --git a/app/src/main/java/org/oppia/android/app/onboarding/OnboardingFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/onboarding/OnboardingFragmentPresenter.kt index c9a37d9b391..22536eead2b 100644 --- a/app/src/main/java/org/oppia/android/app/onboarding/OnboardingFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/onboarding/OnboardingFragmentPresenter.kt @@ -3,235 +3,38 @@ package org.oppia.android.app.onboarding import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.ImageView -import android.widget.LinearLayout -import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment -import androidx.viewpager2.widget.ViewPager2 import org.oppia.android.R import org.oppia.android.app.fragment.FragmentScope -import org.oppia.android.app.model.PolicyPage -import org.oppia.android.app.policies.RouteToPoliciesListener -import org.oppia.android.app.recyclerview.BindableAdapter import org.oppia.android.app.translation.AppLanguageResourceHandler -import org.oppia.android.databinding.OnboardingFragmentBinding -import org.oppia.android.databinding.OnboardingSlideBinding -import org.oppia.android.databinding.OnboardingSlideFinalBinding -import org.oppia.android.util.parser.html.HtmlParser -import org.oppia.android.util.parser.html.PolicyType -import org.oppia.android.util.statusbar.StatusBarColor +import org.oppia.android.databinding.OnboardingAppLanguageSelectionFragmentBinding import javax.inject.Inject /** The presenter for [OnboardingFragment]. */ @FragmentScope class OnboardingFragmentPresenter @Inject constructor( - private val activity: AppCompatActivity, private val fragment: Fragment, - private val onboardingViewModel: OnboardingViewModel, - private val onboardingSlideFinalViewModel: OnboardingSlideFinalViewModel, - private val resourceHandler: AppLanguageResourceHandler, - private val htmlParserFactory: HtmlParser.Factory, - private val multiTypeBuilderFactory: BindableAdapter.MultiTypeBuilder.Factory -) : OnboardingNavigationListener, HtmlParser.PolicyOppiaTagActionListener { - private val dotsList = ArrayList() - private lateinit var binding: OnboardingFragmentBinding + private val appLanguageResourceHandler: AppLanguageResourceHandler +) { + private lateinit var binding: OnboardingAppLanguageSelectionFragmentBinding + /** Handle creation and binding of the [OnboardingFragment] layout. */ fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View { - binding = OnboardingFragmentBinding.inflate( + 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 - it.presenter = this - it.viewModel = onboardingViewModel - } - setUpViewPager() - addDots() - return binding.root - } - - private fun setUpViewPager() { - val onboardingViewPagerBindableAdapter = createViewPagerAdapter() - onboardingViewPagerBindableAdapter.setData( - listOf( - OnboardingSlideViewModel( - context = activity, viewPagerSlide = ViewPagerSlide.SLIDE_0, resourceHandler - ), - OnboardingSlideViewModel( - context = activity, viewPagerSlide = ViewPagerSlide.SLIDE_1, resourceHandler - ), - OnboardingSlideViewModel( - context = activity, viewPagerSlide = ViewPagerSlide.SLIDE_2, resourceHandler - ), - onboardingSlideFinalViewModel - ) - ) - binding.onboardingSlideViewPager.adapter = onboardingViewPagerBindableAdapter - binding.onboardingSlideViewPager.registerOnPageChangeCallback( - object : ViewPager2.OnPageChangeCallback() { - override fun onPageScrollStateChanged(state: Int) { - } - override fun onPageScrolled( - position: Int, - positionOffset: Float, - positionOffsetPixels: Int - ) { - } + binding.apply { + lifecycleOwner = fragment - override fun onPageSelected(position: Int) { - if (position == TOTAL_NUMBER_OF_SLIDES - 1) { - binding.onboardingSlideViewPager.currentItem = TOTAL_NUMBER_OF_SLIDES - 1 - onboardingViewModel.slideChanged(TOTAL_NUMBER_OF_SLIDES - 1) - } else { - onboardingViewModel.slideChanged(ViewPagerSlide.getSlideForPosition(position).ordinal) - } - selectDot(position) - onboardingStatusBarColorUpdate(position) - } - }) - } - - private fun createViewPagerAdapter(): BindableAdapter { - return multiTypeBuilderFactory.create { viewModel -> - when (viewModel) { - is OnboardingSlideViewModel -> ViewType.ONBOARDING_MIDDLE_SLIDE - is OnboardingSlideFinalViewModel -> ViewType.ONBOARDING_FINAL_SLIDE - else -> throw IllegalArgumentException("Encountered unexpected view model: $viewModel") - } - } - .registerViewDataBinder( - viewType = ViewType.ONBOARDING_MIDDLE_SLIDE, - inflateDataBinding = OnboardingSlideBinding::inflate, - setViewModel = OnboardingSlideBinding::setViewModel, - transformViewModel = { it as OnboardingSlideViewModel } + onboardingLanguageTitle.text = appLanguageResourceHandler.getStringInLocaleWithWrapping( + R.string.onboarding_language_activity_title, + appLanguageResourceHandler.getStringInLocale(R.string.app_name) ) - .registerViewDataBinder( - viewType = ViewType.ONBOARDING_FINAL_SLIDE, - inflateDataBinding = OnboardingSlideFinalBinding::inflate, - setViewModel = this::bindOnboardingSlideFinal, - transformViewModel = { it as OnboardingSlideFinalViewModel } - ) - .build() - } - - private fun bindOnboardingSlideFinal( - binding: OnboardingSlideFinalBinding, - model: OnboardingSlideFinalViewModel - ) { - binding.viewModel = model - - val completeString: String = - resourceHandler.getStringInLocaleWithWrapping( - R.string.agree_to_terms, - resourceHandler.getStringInLocale(R.string.app_name) - ) - binding.slideTermsOfServiceAndPrivacyPolicyLinksTextView.text = htmlParserFactory.create( - policyOppiaTagActionListener = this, - displayLocale = resourceHandler.getDisplayLocale() - ).parseOppiaHtml( - completeString, - binding.slideTermsOfServiceAndPrivacyPolicyLinksTextView, - supportsLinks = true, - supportsConceptCards = false - ) - } - - override fun onPolicyPageLinkClicked(policyType: PolicyType) { - when (policyType) { - PolicyType.PRIVACY_POLICY -> - (activity as RouteToPoliciesListener).onRouteToPolicies(PolicyPage.PRIVACY_POLICY) - PolicyType.TERMS_OF_SERVICE -> - (activity as RouteToPoliciesListener).onRouteToPolicies(PolicyPage.TERMS_OF_SERVICE) } - } - private enum class ViewType { - ONBOARDING_MIDDLE_SLIDE, - ONBOARDING_FINAL_SLIDE - } - - private fun onboardingStatusBarColorUpdate(position: Int) { - when (position) { - 0 -> StatusBarColor.statusBarColorUpdate( - R.color.component_color_onboarding_1_status_bar_color, - activity, - false - ) - 1 -> StatusBarColor.statusBarColorUpdate( - R.color.component_color_onboarding_2_status_bar_color, - activity, - false - ) - 2 -> StatusBarColor.statusBarColorUpdate( - R.color.component_color_onboarding_3_status_bar_color, - activity, - false - ) - 3 -> StatusBarColor.statusBarColorUpdate( - R.color.component_color_onboarding_4_status_bar_color, - activity, - false - ) - else -> StatusBarColor.statusBarColorUpdate( - R.color.component_color_shared_activity_status_bar_color, - activity, - false - ) - } - } - - override fun clickOnSkip() { - binding.onboardingSlideViewPager.currentItem = TOTAL_NUMBER_OF_SLIDES - 1 - } - - override fun clickOnNext() { - val position: Int = binding.onboardingSlideViewPager.currentItem + 1 - binding.onboardingSlideViewPager.currentItem = position - if (position != TOTAL_NUMBER_OF_SLIDES - 1) { - onboardingViewModel.slideChanged(ViewPagerSlide.getSlideForPosition(position).ordinal) - } else { - onboardingViewModel.slideChanged(TOTAL_NUMBER_OF_SLIDES - 1) - } - selectDot(position) - } - - private fun addDots() { - val dotsLayout = binding.slideDotsContainer - val dotIdList = ArrayList() - dotIdList.add(R.id.onboarding_dot_0) - dotIdList.add(R.id.onboarding_dot_1) - dotIdList.add(R.id.onboarding_dot_2) - dotIdList.add(R.id.onboarding_dot_3) - for (index in 0 until TOTAL_NUMBER_OF_SLIDES) { - val dotView = ImageView(activity) - dotView.id = dotIdList[index] - dotView.setImageResource(R.drawable.onboarding_dot_active) - - val params = LinearLayout.LayoutParams( - activity.resources.getDimensionPixelSize(R.dimen.dot_width_height), - activity.resources.getDimensionPixelSize(R.dimen.dot_width_height) - ) - params.setMargins( - activity.resources.getDimensionPixelSize(R.dimen.dot_gap), - 0, - 0, - 0 - ) - dotsLayout.addView(dotView, params) - dotsList.add(dotView) - } - selectDot(0) - } - - private fun selectDot(position: Int) { - for (index in 0 until TOTAL_NUMBER_OF_SLIDES) { - val alphaValue = if (index == position) 1.0F else 0.3F - dotsList[index].alpha = alphaValue - } + return binding.root } } diff --git a/app/src/main/java/org/oppia/android/app/onboarding/OnboardingFragmentPresenterV1.kt b/app/src/main/java/org/oppia/android/app/onboarding/OnboardingFragmentPresenterV1.kt new file mode 100644 index 00000000000..a10847e8c79 --- /dev/null +++ b/app/src/main/java/org/oppia/android/app/onboarding/OnboardingFragmentPresenterV1.kt @@ -0,0 +1,237 @@ +package org.oppia.android.app.onboarding + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.LinearLayout +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment +import androidx.viewpager2.widget.ViewPager2 +import org.oppia.android.R +import org.oppia.android.app.fragment.FragmentScope +import org.oppia.android.app.model.PolicyPage +import org.oppia.android.app.policies.RouteToPoliciesListener +import org.oppia.android.app.recyclerview.BindableAdapter +import org.oppia.android.app.translation.AppLanguageResourceHandler +import org.oppia.android.databinding.OnboardingFragmentBinding +import org.oppia.android.databinding.OnboardingSlideBinding +import org.oppia.android.databinding.OnboardingSlideFinalBinding +import org.oppia.android.util.parser.html.HtmlParser +import org.oppia.android.util.parser.html.PolicyType +import org.oppia.android.util.statusbar.StatusBarColor +import javax.inject.Inject + +/** The presenter for [OnboardingFragment]. */ +@FragmentScope +class OnboardingFragmentPresenterV1 @Inject constructor( + private val activity: AppCompatActivity, + private val fragment: Fragment, + private val onboardingViewModel: OnboardingViewModel, + private val onboardingSlideFinalViewModel: OnboardingSlideFinalViewModel, + private val resourceHandler: AppLanguageResourceHandler, + private val htmlParserFactory: HtmlParser.Factory, + private val multiTypeBuilderFactory: BindableAdapter.MultiTypeBuilder.Factory +) : OnboardingNavigationListener, HtmlParser.PolicyOppiaTagActionListener { + private val dotsList = ArrayList() + private lateinit var binding: OnboardingFragmentBinding + + fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View { + binding = OnboardingFragmentBinding.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 + it.presenter = this + it.viewModel = onboardingViewModel + } + setUpViewPager() + addDots() + return binding.root + } + + private fun setUpViewPager() { + val onboardingViewPagerBindableAdapter = createViewPagerAdapter() + onboardingViewPagerBindableAdapter.setData( + listOf( + OnboardingSlideViewModel( + context = activity, viewPagerSlide = ViewPagerSlide.SLIDE_0, resourceHandler + ), + OnboardingSlideViewModel( + context = activity, viewPagerSlide = ViewPagerSlide.SLIDE_1, resourceHandler + ), + OnboardingSlideViewModel( + context = activity, viewPagerSlide = ViewPagerSlide.SLIDE_2, resourceHandler + ), + onboardingSlideFinalViewModel + ) + ) + binding.onboardingSlideViewPager.adapter = onboardingViewPagerBindableAdapter + binding.onboardingSlideViewPager.registerOnPageChangeCallback( + object : ViewPager2.OnPageChangeCallback() { + override fun onPageScrollStateChanged(state: Int) { + } + + override fun onPageScrolled( + position: Int, + positionOffset: Float, + positionOffsetPixels: Int + ) { + } + + override fun onPageSelected(position: Int) { + if (position == TOTAL_NUMBER_OF_SLIDES - 1) { + binding.onboardingSlideViewPager.currentItem = TOTAL_NUMBER_OF_SLIDES - 1 + onboardingViewModel.slideChanged(TOTAL_NUMBER_OF_SLIDES - 1) + } else { + onboardingViewModel.slideChanged(ViewPagerSlide.getSlideForPosition(position).ordinal) + } + selectDot(position) + onboardingStatusBarColorUpdate(position) + } + }) + } + + private fun createViewPagerAdapter(): BindableAdapter { + return multiTypeBuilderFactory.create { viewModel -> + when (viewModel) { + is OnboardingSlideViewModel -> ViewType.ONBOARDING_MIDDLE_SLIDE + is OnboardingSlideFinalViewModel -> ViewType.ONBOARDING_FINAL_SLIDE + else -> throw IllegalArgumentException("Encountered unexpected view model: $viewModel") + } + } + .registerViewDataBinder( + viewType = ViewType.ONBOARDING_MIDDLE_SLIDE, + inflateDataBinding = OnboardingSlideBinding::inflate, + setViewModel = OnboardingSlideBinding::setViewModel, + transformViewModel = { it as OnboardingSlideViewModel } + ) + .registerViewDataBinder( + viewType = ViewType.ONBOARDING_FINAL_SLIDE, + inflateDataBinding = OnboardingSlideFinalBinding::inflate, + setViewModel = this::bindOnboardingSlideFinal, + transformViewModel = { it as OnboardingSlideFinalViewModel } + ) + .build() + } + + private fun bindOnboardingSlideFinal( + binding: OnboardingSlideFinalBinding, + model: OnboardingSlideFinalViewModel + ) { + binding.viewModel = model + + val completeString: String = + resourceHandler.getStringInLocaleWithWrapping( + R.string.agree_to_terms, + resourceHandler.getStringInLocale(R.string.app_name) + ) + binding.slideTermsOfServiceAndPrivacyPolicyLinksTextView.text = htmlParserFactory.create( + policyOppiaTagActionListener = this, + displayLocale = resourceHandler.getDisplayLocale() + ).parseOppiaHtml( + completeString, + binding.slideTermsOfServiceAndPrivacyPolicyLinksTextView, + supportsLinks = true, + supportsConceptCards = false + ) + } + + override fun onPolicyPageLinkClicked(policyType: PolicyType) { + when (policyType) { + PolicyType.PRIVACY_POLICY -> + (activity as RouteToPoliciesListener).onRouteToPolicies(PolicyPage.PRIVACY_POLICY) + PolicyType.TERMS_OF_SERVICE -> + (activity as RouteToPoliciesListener).onRouteToPolicies(PolicyPage.TERMS_OF_SERVICE) + } + } + + private enum class ViewType { + ONBOARDING_MIDDLE_SLIDE, + ONBOARDING_FINAL_SLIDE + } + + private fun onboardingStatusBarColorUpdate(position: Int) { + when (position) { + 0 -> StatusBarColor.statusBarColorUpdate( + R.color.component_color_onboarding_1_status_bar_color, + activity, + false + ) + 1 -> StatusBarColor.statusBarColorUpdate( + R.color.component_color_onboarding_2_status_bar_color, + activity, + false + ) + 2 -> StatusBarColor.statusBarColorUpdate( + R.color.component_color_onboarding_3_status_bar_color, + activity, + false + ) + 3 -> StatusBarColor.statusBarColorUpdate( + R.color.component_color_onboarding_4_status_bar_color, + activity, + false + ) + else -> StatusBarColor.statusBarColorUpdate( + R.color.component_color_shared_activity_status_bar_color, + activity, + false + ) + } + } + + override fun clickOnSkip() { + binding.onboardingSlideViewPager.currentItem = TOTAL_NUMBER_OF_SLIDES - 1 + } + + override fun clickOnNext() { + val position: Int = binding.onboardingSlideViewPager.currentItem + 1 + binding.onboardingSlideViewPager.currentItem = position + if (position != TOTAL_NUMBER_OF_SLIDES - 1) { + onboardingViewModel.slideChanged(ViewPagerSlide.getSlideForPosition(position).ordinal) + } else { + onboardingViewModel.slideChanged(TOTAL_NUMBER_OF_SLIDES - 1) + } + selectDot(position) + } + + private fun addDots() { + val dotsLayout = binding.slideDotsContainer + val dotIdList = ArrayList() + dotIdList.add(R.id.onboarding_dot_0) + dotIdList.add(R.id.onboarding_dot_1) + dotIdList.add(R.id.onboarding_dot_2) + dotIdList.add(R.id.onboarding_dot_3) + for (index in 0 until TOTAL_NUMBER_OF_SLIDES) { + val dotView = ImageView(activity) + dotView.id = dotIdList[index] + dotView.setImageResource(R.drawable.onboarding_dot_active) + + val params = LinearLayout.LayoutParams( + activity.resources.getDimensionPixelSize(R.dimen.dot_width_height), + activity.resources.getDimensionPixelSize(R.dimen.dot_width_height) + ) + params.setMargins( + activity.resources.getDimensionPixelSize(R.dimen.dot_gap), + 0, + 0, + 0 + ) + dotsLayout.addView(dotView, params) + dotsList.add(dotView) + } + selectDot(0) + } + + private fun selectDot(position: Int) { + for (index in 0 until TOTAL_NUMBER_OF_SLIDES) { + val alphaValue = if (index == position) 1.0F else 0.3F + dotsList[index].alpha = alphaValue + } + } +} diff --git a/app/src/main/java/org/oppia/android/app/testing/ColorBindingAdaptersTestActivity.kt b/app/src/main/java/org/oppia/android/app/testing/ColorBindingAdaptersTestActivity.kt new file mode 100644 index 00000000000..9d8878c520f --- /dev/null +++ b/app/src/main/java/org/oppia/android/app/testing/ColorBindingAdaptersTestActivity.kt @@ -0,0 +1,26 @@ +package org.oppia.android.app.testing + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import org.oppia.android.R +import org.oppia.android.app.activity.InjectableAutoLocalizedAppCompatActivity + +/** Test activity for ViewBindingAdapters. */ +class ColorBindingAdaptersTestActivity : InjectableAutoLocalizedAppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_color_binding_adapters_test) + + supportFragmentManager.beginTransaction().add( + R.id.background, + ColorBindingAdaptersTestFragment() + ).commitNow() + } + + companion object { + /** Intent to open this activity. */ + fun createIntent(context: Context): Intent = + Intent(context, ColorBindingAdaptersTestActivity::class.java) + } +} diff --git a/app/src/main/java/org/oppia/android/app/testing/ColorBindingAdaptersTestFragment.kt b/app/src/main/java/org/oppia/android/app/testing/ColorBindingAdaptersTestFragment.kt new file mode 100644 index 00000000000..5c05770960c --- /dev/null +++ b/app/src/main/java/org/oppia/android/app/testing/ColorBindingAdaptersTestFragment.kt @@ -0,0 +1,24 @@ +package org.oppia.android.app.testing + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import org.oppia.android.R +import org.oppia.android.app.fragment.InjectableFragment + +/** Test-only fragment for verifying behaviors of [ColorBindingAdapters]. */ +class ColorBindingAdaptersTestFragment : InjectableFragment() { + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + return inflater.inflate( + R.layout.color_binding_adapters_test_fragment, + container, + /* attachToRoot= */ false + ) + } +} diff --git a/app/src/main/java/org/oppia/android/app/view/ViewComponentImpl.kt b/app/src/main/java/org/oppia/android/app/view/ViewComponentImpl.kt index 08726cc7f49..dc71fc0e90a 100644 --- a/app/src/main/java/org/oppia/android/app/view/ViewComponentImpl.kt +++ b/app/src/main/java/org/oppia/android/app/view/ViewComponentImpl.kt @@ -6,9 +6,9 @@ import dagger.Subcomponent import org.oppia.android.app.customview.ChapterNotStartedContainerConstraintLayout import org.oppia.android.app.customview.ContinueButtonView import org.oppia.android.app.customview.LessonThumbnailImageView +import org.oppia.android.app.customview.OppiaCurveBackgroundView import org.oppia.android.app.customview.PromotedStoryCardView import org.oppia.android.app.customview.SegmentedCircularProgressView -import org.oppia.android.app.customview.SurveyOnboardingBackgroundView import org.oppia.android.app.home.promotedlist.ComingSoonTopicsListView import org.oppia.android.app.home.promotedlist.PromotedStoryListView import org.oppia.android.app.player.state.DragDropSortInteractionView @@ -42,7 +42,7 @@ interface ViewComponentImpl : ViewComponent { fun inject(promotedStoryCardView: PromotedStoryCardView) fun inject(promotedStoryListView: PromotedStoryListView) fun inject(segmentedCircularProgressView: SegmentedCircularProgressView) - fun inject(surveyOnboardingBackgroundView: SurveyOnboardingBackgroundView) + fun inject(oppiaCurveBackgroundView: OppiaCurveBackgroundView) fun inject(surveyMultipleChoiceOptionView: SurveyMultipleChoiceOptionView) fun inject(surveyNpsItemOptionView: SurveyNpsItemOptionView) } diff --git a/app/src/main/res/drawable/dropdown_background.xml b/app/src/main/res/drawable/dropdown_background.xml new file mode 100644 index 00000000000..c6cca728b36 --- /dev/null +++ b/app/src/main/res/drawable/dropdown_background.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_language_icon_black_24dp.xml b/app/src/main/res/drawable/ic_language_icon_black_24dp.xml new file mode 100644 index 00000000000..e89dd7a2a58 --- /dev/null +++ b/app/src/main/res/drawable/ic_language_icon_black_24dp.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/otter.xml b/app/src/main/res/drawable/otter.xml new file mode 100644 index 00000000000..bc0891510c1 --- /dev/null +++ b/app/src/main/res/drawable/otter.xml @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout-land/onboarding_app_language_selection_fragment.xml b/app/src/main/res/layout-land/onboarding_app_language_selection_fragment.xml new file mode 100644 index 00000000000..45941fad82e --- /dev/null +++ b/app/src/main/res/layout-land/onboarding_app_language_selection_fragment.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +