Skip to content

Commit

Permalink
Fix Part of oppia#4938: Introduce Onboarding Audio language screen (o…
Browse files Browse the repository at this point in the history
…ppia#5386)

<!-- READ ME FIRST: Please fill in the explanation section below and
check off every point from the Essential Checklist! -->
## Explanation
Fix Part of oppia#4938: New
screen to allow a user to select an audio language during the onboarding
process.

This PR only adds the layout and navigation functions without
implementing the language selection functionality.
 

||Portrait|Landscape|
|--|--|--|

|Mobile|![Screenshot_1719963278](https://github.com/oppia/oppia-android/assets/59600948/8f6e9f7b-0362-4172-9a46-036661b71598)|![Screenshot_1719963292](https://github.com/oppia/oppia-android/assets/59600948/19c1124c-1c63-4b71-b678-597db2f005d8)|

||![Screenshot_1719963273](https://github.com/oppia/oppia-android/assets/59600948/324726d9-8fdb-466d-82d0-71b7ddc3581a)|![Screenshot_1719963301](https://github.com/oppia/oppia-android/assets/59600948/8d3c1b27-217e-4e1d-b633-20368a057569)|

|Tablet|![Screenshot_1719963641](https://github.com/oppia/oppia-android/assets/59600948/1b53195b-2c17-4a15-8c95-6090fa77470e)|![Screenshot_1719963651](https://github.com/oppia/oppia-android/assets/59600948/49300ebf-bfae-4a42-922d-64b591bbf138)|

||![Screenshot_1719963670](https://github.com/oppia/oppia-android/assets/59600948/cf4e37d3-56f0-47c4-9f0d-b01d75cceb8d)|![Screenshot_1719963660](https://github.com/oppia/oppia-android/assets/59600948/c4b8f6f7-a41e-44a0-af7f-1c8bfca9fa4f)|


## Essential Checklist
<!-- Please tick the relevant boxes by putting an "x" in them. -->
- [x] 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: ...".)
- [x] Any changes to
[scripts/assets](https://github.com/oppia/oppia-android/tree/develop/scripts/assets)
files have their rationale included in the PR explanation.
- [x] The PR follows the [style
guide](https://github.com/oppia/oppia-android/wiki/Coding-style-guide).
- [x] The PR does not contain any unnecessary code changes from Android
Studio
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#undo-unnecessary-changes)).
- [x] The PR is made from a branch that's **not** called "develop" and
is up-to-date with "develop".
- [x] The PR is **assigned** to the appropriate reviewers
([reference](https://github.com/oppia/oppia-android/wiki/Guidance-on-submitting-a-PR#clarification-regarding-assignees-and-reviewers-section)).
  • Loading branch information
adhiamboperes authored Jul 3, 2024
1 parent fcd75ef commit 1c4b17a
Show file tree
Hide file tree
Showing 19 changed files with 813 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.oppia.android.app.onboarding

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.ArrayAdapter
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import com.google.android.material.appbar.AppBarLayout
import org.oppia.android.R
import org.oppia.android.app.options.AudioLanguageSelectionViewModel
import org.oppia.android.app.translation.AppLanguageResourceHandler
import org.oppia.android.databinding.AudioLanguageSelectionFragmentBinding
import javax.inject.Inject

/** The presenter for [AudioLanguageFragment]. */
class AudioLanguageFragmentPresenter @Inject constructor(
private val fragment: Fragment,
private val activity: AppCompatActivity,
private val appLanguageResourceHandler: AppLanguageResourceHandler,
private val audioLanguageSelectionViewModel: AudioLanguageSelectionViewModel
) {
private lateinit var binding: AudioLanguageSelectionFragmentBinding

/**
* Returns a newly inflated view to render the fragment with an evaluated audio language as the
* initial selected language, based on current locale.
*/
fun handleCreateView(
inflater: LayoutInflater,
container: ViewGroup?
): View {

// Hide toolbar as it's not needed in this layout. The toolbar is created by a shared activity
// and is required in OptionsFragment.
activity.findViewById<AppBarLayout>(R.id.reading_list_app_bar_layout).visibility = View.GONE

binding = AudioLanguageSelectionFragmentBinding.inflate(
inflater,
container,
/* attachToRoot= */ false
)
binding.lifecycleOwner = fragment

binding.audioLanguageText.text = appLanguageResourceHandler.getStringInLocaleWithWrapping(
R.string.audio_language_fragment_text,
appLanguageResourceHandler.getStringInLocale(R.string.app_name)
)

binding.onboardingNavigationBack.setOnClickListener {
activity.finish()
}

val adapter = ArrayAdapter(
fragment.requireContext(),
R.layout.onboarding_language_dropdown_item,
R.id.onboarding_language_text_view,
audioLanguageSelectionViewModel.availableAudioLanguages
)

binding.audioLanguageDropdownList.apply {
setAdapter(adapter)
setText(
audioLanguageSelectionViewModel.defaultLanguageSelection,
false
)
setRawInputType(EditorInfo.TYPE_NULL)
}

return binding.root
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import org.oppia.android.R
import org.oppia.android.app.model.AudioLanguage
import org.oppia.android.app.options.AudioLanguageActivity
import org.oppia.android.app.translation.AppLanguageResourceHandler
import org.oppia.android.databinding.LearnerIntroFragmentBinding
import javax.inject.Inject
Expand All @@ -29,6 +31,7 @@ class IntroFragmentPresenter @Inject constructor(
container,
/* attachToRoot= */ false
)

binding.lifecycleOwner = fragment

setLearnerName(profileNickname)
Expand All @@ -43,6 +46,14 @@ class IntroFragmentPresenter @Inject constructor(
appLanguageResourceHandler.getStringInLocale(R.string.app_name)
)

binding.onboardingNavigationContinue.setOnClickListener {
val intent = AudioLanguageActivity.createAudioLanguageActivityIntent(
fragment.requireContext(),
AudioLanguage.ENGLISH_AUDIO_LANGUAGE
)
fragment.startActivity(intent)
}

return binding.root
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,23 @@ import org.oppia.android.app.fragment.InjectableFragment
import org.oppia.android.app.model.AudioLanguage
import org.oppia.android.app.model.AudioLanguageFragmentArguments
import org.oppia.android.app.model.AudioLanguageFragmentStateBundle
import org.oppia.android.app.onboarding.AudioLanguageFragmentPresenter
import org.oppia.android.util.extensions.getProto
import org.oppia.android.util.extensions.putProto
import org.oppia.android.util.platformparameter.EnableOnboardingFlowV2
import org.oppia.android.util.platformparameter.PlatformParameterValue
import javax.inject.Inject

/** The fragment to change the default audio language of the app. */
class AudioLanguageFragment : InjectableFragment(), AudioLanguageRadioButtonListener {
@Inject lateinit var audioLanguageFragmentPresenterV1: AudioLanguageFragmentPresenterV1

@Inject lateinit var audioLanguageFragmentPresenter: AudioLanguageFragmentPresenter

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

override fun onAttach(context: Context) {
super.onAttach(context)
(fragmentComponent as FragmentComponentImpl).inject(this)
Expand All @@ -33,19 +42,27 @@ class AudioLanguageFragment : InjectableFragment(), AudioLanguageRadioButtonList
savedInstanceState?.retrieveLanguageFromSavedState()
?: arguments?.retrieveLanguageFromArguments()
) { "Expected arguments to be passed to AudioLanguageFragment" }
return audioLanguageFragmentPresenter.handleOnCreateView(inflater, container, audioLanguage)
return if (enableOnboardingFlowV2.value) {
audioLanguageFragmentPresenter.handleCreateView(inflater, container)
} else {
audioLanguageFragmentPresenterV1.handleOnCreateView(inflater, container, audioLanguage)
}
}

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
val state = AudioLanguageFragmentStateBundle.newBuilder().apply {
audioLanguage = audioLanguageFragmentPresenter.getLanguageSelected()
}.build()
outState.putProto(FRAGMENT_SAVED_STATE_KEY, state)
if (!enableOnboardingFlowV2.value) {
val state = AudioLanguageFragmentStateBundle.newBuilder().apply {
audioLanguage = audioLanguageFragmentPresenterV1.getLanguageSelected()
}.build()
outState.putProto(FRAGMENT_SAVED_STATE_KEY, state)
}
}

override fun onLanguageSelected(audioLanguage: AudioLanguage) {
audioLanguageFragmentPresenter.onLanguageSelected(audioLanguage)
if (!enableOnboardingFlowV2.value) {
audioLanguageFragmentPresenterV1.onLanguageSelected(audioLanguage)
}
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import org.oppia.android.databinding.AudioLanguageItemBinding
import javax.inject.Inject

/** The presenter for [AudioLanguageFragment]. */
class AudioLanguageFragmentPresenter @Inject constructor(
class AudioLanguageFragmentPresenterV1 @Inject constructor(
private val fragment: Fragment,
private val audioLanguageSelectionViewModel: AudioLanguageSelectionViewModel,
private val singleTypeBuilderFactory: BindableAdapter.SingleTypeBuilder.Factory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ class AudioLanguageSelectionViewModel @Inject constructor(
)
}

// TODO(#4938): Update the pre-selection logic.
/** The pre-selected [AudioLanguage] to be shown in the language selection dropdown. */
val defaultLanguageSelection = getLanguageDisplayName(AudioLanguage.ENGLISH_AUDIO_LANGUAGE)

/** The list of [AudioLanguage]s supported by the app. */
val availableAudioLanguages: List<String> by lazy {
AudioLanguage.values().filter { it !in IGNORED_AUDIO_LANGUAGES }.map(::getLanguageDisplayName)
}

private fun getLanguageDisplayName(audioLanguage: AudioLanguage): String {
return appLanguageResourceHandler.computeLocalizedDisplayName(audioLanguage)
}

private companion object {
private val IGNORED_AUDIO_LANGUAGES =
listOf(
Expand Down
96 changes: 96 additions & 0 deletions app/src/main/res/layout-land/audio_language_selection_fragment.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/apk/res-auto">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/component_color_onboarding_shared_green_color">

<androidx.constraintlayout.widget.Guideline
android:id="@+id/audio_language_background_guide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.55" />

<org.oppia.android.app.customview.OppiaCurveBackgroundView
android:layout_width="match_parent"
android:layout_height="0dp"
app:customBackgroundColor="@{@color/component_color_onboarding_shared_white_color}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/audio_language_background_guide" />

<TextView
android:id="@+id/audio_language_text"
style="@style/AudioLanguageTextStyle"
android:layout_marginTop="@dimen/phone_shared_margin_xl"
android:layout_marginEnd="@dimen/phone_shared_margin_large"
android:text="@string/audio_language_fragment_text"
android:textColor="@color/component_color_onboarding_shared_white_color"
app:layout_constraintBottom_toTopOf="@id/audio_language_subtitle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/audio_language_subtitle"
style="@style/AudioLanguageSubtitleStyle"
android:layout_marginStart="@dimen/phone_shared_margin_xl"
android:layout_marginTop="@dimen/phone_shared_margin_small"
android:layout_marginEnd="@dimen/phone_shared_margin_xl"
android:text="@string/audio_language_fragment_subtitle"
android:textColor="@color/component_color_onboarding_shared_white_color"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/audio_language_text"
app:layout_constraintWidth_percent="0.50" />

<com.google.android.material.card.MaterialCardView
android:id="@+id/audio_language_dropdown_background"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/phone_shared_margin_xl"
android:layout_marginTop="@dimen/phone_shared_margin_large"
android:layout_marginEnd="@dimen/phone_shared_margin_xl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/audio_language_subtitle"
app:layout_constraintWidth_percent="0.50"
card_view:cardCornerRadius="@dimen/onboarding_shared_corner_radius"
card_view:cardElevation="@dimen/onboarding_shared_elevation"
card_view:cardUseCompatPadding="false">

<com.google.android.material.textfield.TextInputLayout style="@style/LanguageDropdownStyle">

<AutoCompleteTextView
android:id="@+id/audio_language_dropdown_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:padding="@dimen/onboarding_shared_padding_small" />
</com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.card.MaterialCardView>

<Button
android:id="@+id/onboarding_navigation_back"
style="@style/OnboardingNavigationSecondaryButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/phone_shared_margin_large"
android:text="@string/onboarding_navigation_back"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />

<Button
android:id="@+id/onboarding_navigation_continue"
style="@style/OnboardingNavigationPrimaryButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/phone_shared_margin_large"
android:text="@string/onboarding_navigation_continue"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,7 @@
card_view:cardUseCompatPadding="false">

<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/component_color_onboarding_shared_text_color"
app:boxBackgroundColor="@color/component_color_onboarding_shared_white_color"
app:boxStrokeWidth="0dp"
app:boxStrokeWidthFocused="0dp"
app:endIconDrawable="@drawable/ic_arrow_drop_down_black_24dp"
app:endIconTint="@color/component_color_shared_black_background_color"
style="@style/LanguageDropdownStyle"
app:startIconDrawable="@drawable/ic_language_icon_black_24dp"
app:startIconTint="@color/component_color_shared_black_background_color">

Expand Down
Loading

0 comments on commit 1c4b17a

Please sign in to comment.