Skip to content

Commit

Permalink
Merge branch 'develop' into feat/ratio-ui-empty-answer-support
Browse files Browse the repository at this point in the history
  • Loading branch information
theMr17 authored Jan 11, 2024
2 parents be6f136 + 9ad24ef commit 3b11ba7
Show file tree
Hide file tree
Showing 49 changed files with 895 additions and 643 deletions.
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@
<activity android:name=".app.testing.DrawableBindingAdaptersTestActivity" />
<activity android:name=".app.testing.ExplorationInjectionActivity" />
<activity android:name=".app.testing.ExplorationTestActivity" />
<activity android:name=".app.testing.FractionInputInteractionViewTestActivity" />
<activity
android:name=".app.testing.TestFontScaleConfigurationUtilActivity"
android:theme="@style/OppiaThemeWithoutActionBar" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import org.oppia.android.app.testing.DragDropTestActivity
import org.oppia.android.app.testing.DrawableBindingAdaptersTestActivity
import org.oppia.android.app.testing.ExplorationInjectionActivity
import org.oppia.android.app.testing.ExplorationTestActivity
import org.oppia.android.app.testing.FractionInputInteractionViewTestActivity
import org.oppia.android.app.testing.HomeFragmentTestActivity
import org.oppia.android.app.testing.HomeTestActivity
import org.oppia.android.app.testing.HtmlParserTestActivity
Expand Down Expand Up @@ -140,6 +141,7 @@ interface ActivityComponentImpl :
fun inject(faqSingleActivity: FAQSingleActivity)
fun inject(forceNetworkTypeActivity: ForceNetworkTypeActivity)
fun inject(forceNetworkTypeTestActivity: ForceNetworkTypeTestActivity)
fun inject(fractionInputInteractionViewTestActivity: FractionInputInteractionViewTestActivity)
fun inject(helpActivity: HelpActivity)
fun inject(homeActivity: HomeActivity)
fun inject(homeFragmentTestActivity: HomeFragmentTestActivity)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import org.oppia.android.util.data.AsyncResult
import org.oppia.android.util.data.DataProvider
import org.oppia.android.util.data.DataProviders.Companion.combineWith
import org.oppia.android.util.data.DataProviders.Companion.toLiveData
import org.oppia.android.util.platformparameter.EnableLanguageSelectionUi
import org.oppia.android.util.platformparameter.PlatformParameterValue
import javax.inject.Inject

/** [ViewModel] for [OptionsFragment]. */
Expand All @@ -32,7 +30,6 @@ class OptionControlsViewModel @Inject constructor(
activity: AppCompatActivity,
private val profileManagementController: ProfileManagementController,
private val oppiaLogger: OppiaLogger,
@EnableLanguageSelectionUi private val enableLanguageSelectionUi: PlatformParameterValue<Boolean>,
private val resourceHandler: AppLanguageResourceHandler,
private val translationController: TranslationController
) : OptionsItemViewModel() {
Expand Down Expand Up @@ -112,13 +109,12 @@ class OptionControlsViewModel @Inject constructor(
}

private fun createAppLanguageViewModel(language: OppiaLanguage): OptionsAppLanguageViewModel? {
return if (enableLanguageSelectionUi.value) {
OptionsAppLanguageViewModel(
routeToAppLanguageListListener,
loadAppLanguageListListener, language,
resourceHandler.computeLocalizedDisplayName(language)
)
} else null
return OptionsAppLanguageViewModel(
routeToAppLanguageListListener,
loadAppLanguageListListener,
language,
resourceHandler.computeLocalizedDisplayName(language)
)
}

private fun createAudioLanguageViewModel(profile: Profile): OptionsAudioLanguageViewModel {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ enum class FractionParsingUiError(@StringRes private var error: Int?) {
DIVISION_BY_ZERO(error = R.string.fraction_error_divide_by_zero),

/** Corresponds to [FractionParsingError.NUMBER_TOO_LONG]. */
NUMBER_TOO_LONG(error = R.string.fraction_error_larger_than_seven_digits);
NUMBER_TOO_LONG(error = R.string.fraction_error_larger_than_seven_digits),

/** Corresponds to [FractionParsingError.EMPTY_INPUT]. */
EMPTY_INPUT(error = R.string.fraction_error_empty_input);

/**
* Returns the string corresponding to this error's string resources, or null if there is none.
Expand All @@ -39,6 +42,7 @@ enum class FractionParsingUiError(@StringRes private var error: Int?) {
FractionParsingError.INVALID_FORMAT -> INVALID_FORMAT
FractionParsingError.DIVISION_BY_ZERO -> DIVISION_BY_ZERO
FractionParsingError.NUMBER_TOO_LONG -> NUMBER_TOO_LONG
FractionParsingError.EMPTY_INPUT -> EMPTY_INPUT
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,17 @@ class FractionInteractionViewModel private constructor(
override fun onPropertyChanged(sender: Observable, propertyId: Int) {
errorOrAvailabilityCheckReceiver.onPendingAnswerErrorOrAvailabilityCheck(
pendingAnswerError,
answerText.isNotEmpty()
true // Allow submit on empty answer.
)
}
}
errorMessage.addOnPropertyChangedCallback(callback)
isAnswerAvailable.addOnPropertyChangedCallback(callback)
// Force-update the UI to reflect the state of the errorMessage and isAnswerAvailable property:
errorOrAvailabilityCheckReceiver.onPendingAnswerErrorOrAvailabilityCheck(
/* pendingAnswerError= */null,
/* inputAnswerAvailable= */true
)
}

override fun getPendingAnswer(): UserAnswer = UserAnswer.newBuilder().apply {
Expand All @@ -64,23 +69,25 @@ class FractionInteractionViewModel private constructor(

/** It checks the pending error for the current fraction input, and correspondingly updates the error string based on the specified error category. */
override fun checkPendingAnswerError(category: AnswerErrorCategory): String? {
if (answerText.isNotEmpty()) {
when (category) {
AnswerErrorCategory.REAL_TIME -> {
when (category) {
AnswerErrorCategory.REAL_TIME -> {
if (answerText.isNotEmpty()) {
pendingAnswerError =
FractionParsingUiError.createFromParsingError(
fractionParser.getRealTimeAnswerError(answerText.toString())
).getErrorMessageFromStringRes(resourceHandler)
} else {
pendingAnswerError = null
}
AnswerErrorCategory.SUBMIT_TIME -> {
pendingAnswerError =
FractionParsingUiError.createFromParsingError(
fractionParser.getSubmitTimeError(answerText.toString())
).getErrorMessageFromStringRes(resourceHandler)
}
}
errorMessage.set(pendingAnswerError)
AnswerErrorCategory.SUBMIT_TIME -> {
pendingAnswerError =
FractionParsingUiError.createFromParsingError(
fractionParser.getSubmitTimeError(answerText.toString())
).getErrorMessageFromStringRes(resourceHandler)
}
}
errorMessage.set(pendingAnswerError)
return pendingAnswerError
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ class MathExpressionInteractionsViewModel private constructor(
* bound to the corresponding edit text.
*/
var answerText: CharSequence = ""
// The value of ths field is set from the Binding and from the TextWatcher. Any
// programmatic modification needs to be done here, so that the Binding and the TextWatcher
// do not step on each other.
set(value) {
field = value.toString().trim()
}

/**
* Defines whether an answer is currently available to parse. This is expected to be directly
Expand Down Expand Up @@ -166,7 +172,7 @@ class MathExpressionInteractionsViewModel private constructor(
}

override fun onTextChanged(answer: CharSequence, start: Int, before: Int, count: Int) {
answerText = answer.toString().trim()
answerText = answer
val isAnswerTextAvailable = answerText.isNotEmpty()
if (isAnswerTextAvailable != isAnswerAvailable.get()) {
isAnswerAvailable.set(isAnswerTextAvailable)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package org.oppia.android.app.testing

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.View
import androidx.databinding.DataBindingUtil
import org.oppia.android.R
import org.oppia.android.app.activity.ActivityComponentImpl
import org.oppia.android.app.activity.InjectableAutoLocalizedAppCompatActivity
import org.oppia.android.app.customview.interaction.FractionInputInteractionView
import org.oppia.android.app.model.InputInteractionViewTestActivityParams
import org.oppia.android.app.model.Interaction
import org.oppia.android.app.model.UserAnswer
import org.oppia.android.app.model.WrittenTranslationContext
import org.oppia.android.app.player.state.answerhandling.AnswerErrorCategory
import org.oppia.android.app.player.state.answerhandling.InteractionAnswerErrorOrAvailabilityCheckReceiver
import org.oppia.android.app.player.state.answerhandling.InteractionAnswerReceiver
import org.oppia.android.app.player.state.itemviewmodel.FractionInteractionViewModel
import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel
import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel.InteractionItemFactory
import org.oppia.android.app.player.state.listener.StateKeyboardButtonListener
import org.oppia.android.databinding.ActivityFractionInputInteractionViewTestBinding
import org.oppia.android.util.extensions.getProtoExtra
import org.oppia.android.util.extensions.putProtoExtra
import javax.inject.Inject

/**
* This is a dummy activity to test [FractionInputInteractionView].
*/
class FractionInputInteractionViewTestActivity :
InjectableAutoLocalizedAppCompatActivity(),
StateKeyboardButtonListener,
InteractionAnswerErrorOrAvailabilityCheckReceiver,
InteractionAnswerReceiver {
private lateinit var binding: ActivityFractionInputInteractionViewTestBinding

@Inject
lateinit var fractionInteractionViewModelFactory: FractionInteractionViewModel.FactoryImpl

/** Gives access to the [FractionInteractionViewModel]. */
val fractionInteractionViewModel by lazy {
fractionInteractionViewModelFactory.create<FractionInteractionViewModel>()
}

/** Gives access to the translation context. */
lateinit var writtenTranslationContext: WrittenTranslationContext

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
(activityComponent as ActivityComponentImpl).inject(this)
binding = DataBindingUtil.setContentView<ActivityFractionInputInteractionViewTestBinding>(
this, R.layout.activity_fraction_input_interaction_view_test
)

val params =
intent.getProtoExtra(
TEST_ACTIVITY_PARAMS_ARGUMENT_KEY,
InputInteractionViewTestActivityParams.getDefaultInstance()
)
writtenTranslationContext = params.writtenTranslationContext
binding.fractionInteractionViewModel = fractionInteractionViewModel
}

/** Checks submit-time errors. */
fun getPendingAnswerErrorOnSubmitClick(v: View) {
fractionInteractionViewModel.checkPendingAnswerError(AnswerErrorCategory.SUBMIT_TIME)
}

override fun onPendingAnswerErrorOrAvailabilityCheck(
pendingAnswerError: String?,
inputAnswerAvailable: Boolean
) {
}

override fun onAnswerReadyForSubmission(answer: UserAnswer) {
}

override fun onEditorAction(actionCode: Int) {
}

private inline fun <reified T : StateItemViewModel> InteractionItemFactory.create(
interaction: Interaction = Interaction.getDefaultInstance()
): T {
return create(
entityId = "fake_entity_id",
hasConversationView = false,
interaction = interaction,
interactionAnswerReceiver = this@FractionInputInteractionViewTestActivity,
answerErrorReceiver = this@FractionInputInteractionViewTestActivity,
hasPreviousButton = false,
isSplitView = false,
writtenTranslationContext,
timeToStartNoticeAnimationMs = null
) as T
}

companion object {
private const val TEST_ACTIVITY_PARAMS_ARGUMENT_KEY =
"FractionInputInteractionViewTestActivity.params"

/** Creates an intent to open this activity. */
fun createIntent(
context: Context,
extras: InputInteractionViewTestActivityParams
): Intent {
return Intent(context, FractionInputInteractionViewTestActivity::class.java).also {
it.putProtoExtra(TEST_ACTIVITY_PARAMS_ARGUMENT_KEY, extras)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import androidx.databinding.DataBindingUtil
import org.oppia.android.R
import org.oppia.android.app.activity.ActivityComponentImpl
import org.oppia.android.app.activity.InjectableAutoLocalizedAppCompatActivity
import org.oppia.android.app.customview.interaction.FractionInputInteractionView
import org.oppia.android.app.customview.interaction.NumericInputInteractionView
import org.oppia.android.app.customview.interaction.TextInputInteractionView
import org.oppia.android.app.model.InputInteractionViewTestActivityParams
Expand All @@ -23,7 +22,6 @@ import org.oppia.android.app.model.WrittenTranslationContext
import org.oppia.android.app.player.state.answerhandling.AnswerErrorCategory
import org.oppia.android.app.player.state.answerhandling.InteractionAnswerErrorOrAvailabilityCheckReceiver
import org.oppia.android.app.player.state.answerhandling.InteractionAnswerReceiver
import org.oppia.android.app.player.state.itemviewmodel.FractionInteractionViewModel
import org.oppia.android.app.player.state.itemviewmodel.MathExpressionInteractionsViewModel
import org.oppia.android.app.player.state.itemviewmodel.NumericInputViewModel
import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel
Expand All @@ -38,7 +36,7 @@ import org.oppia.android.app.player.state.itemviewmodel.MathExpressionInteractio

/**
* This is a dummy activity to test input interaction views.
* It contains [FractionInputInteractionView], [NumericInputInteractionView],and [TextInputInteractionView].
* It contains [NumericInputInteractionView],and [TextInputInteractionView].
*/
class InputInteractionViewTestActivity :
InjectableAutoLocalizedAppCompatActivity(),
Expand All @@ -53,20 +51,13 @@ class InputInteractionViewTestActivity :
@Inject
lateinit var textInputViewModelFactory: TextInputViewModel.FactoryImpl

@Inject
lateinit var fractionInteractionViewModelFactory: FractionInteractionViewModel.FactoryImpl

@Inject
lateinit var mathExpViewModelFactoryFactory: MathExpViewModelFactoryFactoryImpl

val numericInputViewModel by lazy { numericInputViewModelFactory.create<NumericInputViewModel>() }

val textInputViewModel by lazy { textInputViewModelFactory.create<TextInputViewModel>() }

val fractionInteractionViewModel by lazy {
fractionInteractionViewModelFactory.create<FractionInteractionViewModel>()
}

lateinit var mathExpressionViewModel: MathExpressionInteractionsViewModel
lateinit var writtenTranslationContext: WrittenTranslationContext

Expand Down Expand Up @@ -113,12 +104,10 @@ class InputInteractionViewTestActivity :

binding.numericInputViewModel = numericInputViewModel
binding.textInputViewModel = textInputViewModel
binding.fractionInteractionViewModel = fractionInteractionViewModel
binding.mathExpressionInteractionsViewModel = mathExpressionViewModel
}

fun getPendingAnswerErrorOnSubmitClick(v: View) {
fractionInteractionViewModel.checkPendingAnswerError(AnswerErrorCategory.SUBMIT_TIME)
numericInputViewModel.checkPendingAnswerError(AnswerErrorCategory.SUBMIT_TIME)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
android:fontFamily="sans-serif"
android:text="@{viewModel.storyPercentage != 100? @string/status_in_progress : @string/status_completed}"
android:textColor="@color/component_color_shared_primary_text_color"
android:textSize="10sp"
android:textSize="12sp"
android:visibility="@{viewModel.storyPercentage != 0 ? View.VISIBLE : View.GONE}" />
</LinearLayout>

Expand Down
6 changes: 2 additions & 4 deletions app/src/main/res/layout-sw600dp/revision_card_fragment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,13 @@

<com.google.android.material.card.MaterialCardView
android:id="@+id/previous_navigation_card"
android:layout_width="wrap_content"
android:layout_width="144dp"
android:layout_height="wrap_content"
android:layout_marginStart="28dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="28dp"
android:layout_marginBottom="@dimen/topic_revision_summary_view_container_margin_bottom"
android:clipToPadding="true"
android:maxWidth="144dp"
android:onClick="@{() -> viewModel.onPreviousCardClicked()}"
android:visibility="@{viewModel.subtopicId == 1 ? View.GONE : View.VISIBLE}"
app:cardBackgroundColor="@color/component_color_shared_revision_card_background_color"
Expand Down Expand Up @@ -120,14 +119,13 @@

<com.google.android.material.card.MaterialCardView
android:id="@+id/next_navigation_card"
android:layout_width="wrap_content"
android:layout_width="144dp"
android:layout_height="wrap_content"
android:layout_marginStart="28dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="28dp"
android:layout_marginBottom="@dimen/topic_revision_summary_view_container_margin_bottom"
android:clipToPadding="true"
android:maxWidth="144dp"
android:onClick="@{() -> viewModel.onNextCardClicked()}"
android:visibility="@{viewModel.subtopicId &lt; viewModel.subtopicListSize ? View.VISIBLE : View.GONE}"
app:cardBackgroundColor="@color/component_color_shared_revision_card_background_color"
Expand Down
Loading

0 comments on commit 3b11ba7

Please sign in to comment.