Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix part #376: Fraction input interaction view validation #419

Merged
merged 107 commits into from
Jan 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
acf2610
nit
nikitamarysolomanpvt Nov 11, 2019
b760c44
UI hi-fi for text,number,and fraction input views
nikitamarysolomanpvt Nov 11, 2019
deaa102
UI hi-fi for text,number,and fraction input views
nikitamarysolomanpvt Nov 11, 2019
5f30564
UI hi-fi for text,number,and fraction input views nit
nikitamarysolomanpvt Nov 12, 2019
8484f34
nit
nikitamarysolomanpvt Nov 12, 2019
33e1232
nit
nikitamarysolomanpvt Nov 12, 2019
d108ff0
test cases update
nikitamarysolomanpvt Nov 13, 2019
fc2355f
accent color
nikitamarysolomanpvt Nov 13, 2019
adc0fbf
input type in fraction input type
nikitamarysolomanpvt Nov 13, 2019
e0a7c5a
input type in fraction input type
nikitamarysolomanpvt Nov 13, 2019
47b7aad
Merge branches 'develop' and 'hi-fi-input-interaction-views' of https…
nikitamarysolomanpvt Nov 13, 2019
1e3ed3a
Merge branches 'develop' and 'hi-fi-input-interaction-views' of https…
nikitamarysolomanpvt Nov 13, 2019
fe0f1d8
text color in input type views
nikitamarysolomanpvt Nov 13, 2019
8a489a0
changed inputtype in edit text
nikitamarysolomanpvt Nov 13, 2019
0eff2ef
margin updated in input views
nikitamarysolomanpvt Nov 14, 2019
9d8f704
margin updated in input views
nikitamarysolomanpvt Nov 14, 2019
b429ec8
nit
nikitamarysolomanpvt Nov 18, 2019
9981d81
keyboardhelper to handle softinoutkeyboard
nikitamarysolomanpvt Nov 18, 2019
321facd
Merge branch 'develop' of https://github.com/oppia/oppia-android into…
nikitamarysolomanpvt Nov 18, 2019
ef864b2
Edit text focus removed.
nikitamarysolomanpvt Nov 18, 2019
70d4c73
as per review suggestion added binding.stateRecyclerView.smoothScroll…
nikitamarysolomanpvt Nov 18, 2019
6d01b40
nit
nikitamarysolomanpvt Nov 18, 2019
8289c5e
Fix-406
Nov 18, 2019
900d248
nit changes and keybord helper class renamed.
nikitamarysolomanpvt Nov 18, 2019
4c6a0db
Merge branches 'fix-406' and 'hi-fi-input-interaction-views' of https…
nikitamarysolomanpvt Nov 18, 2019
1c94120
nit
nikitamarysolomanpvt Nov 19, 2019
8e88592
merged with develop, inputviews test cases fix
nikitamarysolomanpvt Nov 19, 2019
f9f5149
kdoc for keyboardhelper.nit changes
nikitamarysolomanpvt Nov 19, 2019
7922ce3
kdoc for keyboardhelper
nikitamarysolomanpvt Nov 19, 2019
c288193
nit
nikitamarysolomanpvt Nov 19, 2019
16ed76d
nit
nikitamarysolomanpvt Nov 19, 2019
03ddc53
Merge branches 'develop' and 'hi-fi-input-interaction-views' of https…
nikitamarysolomanpvt Nov 19, 2019
9984a6d
nit
nikitamarysolomanpvt Nov 19, 2019
fbfb1c0
nit
nikitamarysolomanpvt Nov 19, 2019
9b69e00
nit
nikitamarysolomanpvt Nov 19, 2019
5c9ed90
validation in fraction input
nikitamarysolomanpvt Nov 19, 2019
1adc337
merged with develop
nikitamarysolomanpvt Nov 19, 2019
196a780
nit
nikitamarysolomanpvt Nov 19, 2019
4616518
nit
nikitamarysolomanpvt Nov 19, 2019
d065f43
nit
nikitamarysolomanpvt Nov 20, 2019
e0659c3
errorcode enum
nikitamarysolomanpvt Nov 22, 2019
b2118f3
errorcode enum
nikitamarysolomanpvt Nov 22, 2019
82a9331
nit
nikitamarysolomanpvt Nov 22, 2019
db757c3
nit
nikitamarysolomanpvt Nov 22, 2019
787d5e7
nit
nikitamarysolomanpvt Nov 25, 2019
46200b8
nit
nikitamarysolomanpvt Nov 25, 2019
11451ff
error text on Fraction input
nikitamarysolomanpvt Nov 26, 2019
0e2ec7a
error text on Fraction input
nikitamarysolomanpvt Nov 26, 2019
374b4de
nit
nikitamarysolomanpvt Nov 26, 2019
d36e0ad
nit
nikitamarysolomanpvt Nov 26, 2019
f0b4a2f
updated FractionParsingErrors Enum with string resources, added getPe…
nikitamarysolomanpvt Nov 27, 2019
9af5ce4
nit
nikitamarysolomanpvt Nov 27, 2019
4e04196
nit
nikitamarysolomanpvt Nov 27, 2019
812fb69
nit
nikitamarysolomanpvt Nov 27, 2019
bb81937
Merge branches 'develop' and 'hi-fi-input-interaction-views-validatio…
nikitamarysolomanpvt Nov 28, 2019
2ab1b45
Merge conflict issue fix
nikitamarysolomanpvt Nov 28, 2019
056ea73
Merge branch 'develop' of https://github.com/oppia/oppia-android into…
nikitamarysolomanpvt Nov 28, 2019
dd4d929
Merge branch 'develop' of https://github.com/oppia/oppia-android into…
nikitamarysolomanpvt Nov 28, 2019
f7ad0d0
not showing error on fiest - symbol in fraction input, new method for…
nikitamarysolomanpvt Nov 28, 2019
c3a9b0b
not showing error on fiest - symbol in fraction input, new method for…
nikitamarysolomanpvt Nov 28, 2019
a5cf2ba
nit
nikitamarysolomanpvt Nov 28, 2019
388ec6d
partial answer removed error message display by regex for partial values
nikitamarysolomanpvt Nov 28, 2019
c617d13
nit import optimisation changes reverted
nikitamarysolomanpvt Nov 28, 2019
289135c
nit import optimisation changes reverted
nikitamarysolomanpvt Nov 28, 2019
da5701c
nit import optimisation changes reverted
nikitamarysolomanpvt Nov 28, 2019
5429720
carsh fix in EditTextBindingAdapters
nikitamarysolomanpvt Nov 28, 2019
2b9924a
on submit button displays error for partial input and divided by 0
nikitamarysolomanpvt Nov 29, 2019
afe06ad
instance check
nikitamarysolomanpvt Nov 29, 2019
a209c6f
moved FractionParsingError to StringToFractionParser,
nikitamarysolomanpvt Nov 29, 2019
7309044
color names updated casing
nikitamarysolomanpvt Nov 29, 2019
fa42522
Introduced disparity between the patterns used to validate vs the one…
nikitamarysolomanpvt Dec 2, 2019
8460bf1
test cases for error messages.
nikitamarysolomanpvt Dec 2, 2019
31f9cef
nit
nikitamarysolomanpvt Dec 2, 2019
642c835
partial mixed fraction issue fix
nikitamarysolomanpvt Dec 3, 2019
889813a
nit
nikitamarysolomanpvt Dec 3, 2019
0386236
Merge branch 'develop' of https://github.com/oppia/oppia-android into…
nikitamarysolomanpvt Dec 5, 2019
93e9474
nit
nikitamarysolomanpvt Dec 5, 2019
60fa159
nit
nikitamarysolomanpvt Dec 5, 2019
b5aaa75
added few testcases
nikitamarysolomanpvt Dec 6, 2019
0dd3fcb
nit changes.
nikitamarysolomanpvt Dec 7, 2019
5fc4124
parseFunction introduced and the helper is used for both for parsing …
nikitamarysolomanpvt Dec 9, 2019
a6eab84
getter and setter for PendingAnswerError in FractionInteractionViewMo…
nikitamarysolomanpvt Dec 11, 2019
9aba111
removed digit filter in test activity nit
nikitamarysolomanpvt Dec 12, 2019
5e5e490
removed digit filter in test activity nit
nikitamarysolomanpvt Dec 12, 2019
0c7845b
added new method onAnswerRealTimeError in InteractionAnswerHandler
nikitamarysolomanpvt Dec 13, 2019
a1b38c9
added new method onAnswerRealTimeError in InteractionAnswerHandler
nikitamarysolomanpvt Dec 13, 2019
8d710c0
state fragment is added as parameter to FractionInteractionViewModel
nikitamarysolomanpvt Dec 16, 2019
c398c4c
submit button active/inactive on realtime error implementation on Sta…
nikitamarysolomanpvt Dec 16, 2019
66d88a1
nit changes
nikitamarysolomanpvt Dec 17, 2019
e98b6a3
nit changes, InputInteractionViewTestActivity updated with new realti…
nikitamarysolomanpvt Dec 18, 2019
18ea562
merged with develop
nikitamarysolomanpvt Dec 18, 2019
1771758
submit button issue fix.
nikitamarysolomanpvt Dec 18, 2019
173ded5
interactionVieewModelModule code fix for on continue button click for…
nikitamarysolomanpvt Dec 19, 2019
d72d58c
nit
nikitamarysolomanpvt Dec 19, 2019
df38130
setting error on submit is moved to stateFragmentPresenter
nikitamarysolomanpvt Dec 23, 2019
68c9c2a
nit
nikitamarysolomanpvt Jan 9, 2020
f672062
InteractionAnswerErrorReceiver
nikitamarysolomanpvt Jan 10, 2020
8bfe532
3rd approach
nikitamarysolomanpvt Jan 13, 2020
28b3fbd
fraction input validation final approach
nikitamarysolomanpvt Jan 13, 2020
9d8e23f
nit
nikitamarysolomanpvt Jan 14, 2020
b3a9c1d
nit
nikitamarysolomanpvt Jan 14, 2020
8268e97
Merge branches 'develop' and 'hi-fi-input-interaction-views-validatio…
nikitamarysolomanpvt Jan 14, 2020
586b1cf
nit
nikitamarysolomanpvt Jan 14, 2020
9e8c1bc
nit
nikitamarysolomanpvt Jan 14, 2020
d0a309b
New fraction submit time error "None of the numbers of the fraction s…
nikitamarysolomanpvt Jan 17, 2020
ba97d7d
test-case to check long number, nit changes ,kDoc
nikitamarysolomanpvt Jan 21, 2020
db99432
nit
nikitamarysolomanpvt Jan 22, 2020
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
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ class FractionInputInteractionView @JvmOverloads constructor(
attrs: AttributeSet? = null,
defStyle: Int = android.R.attr.editTextStyle
) : EditText(context, attrs, defStyle), View.OnFocusChangeListener {
private val hintText: String
private val hintText: CharSequence
private val stateKeyboardButtonListener: StateKeyboardButtonListener

init {
onFocusChangeListener = this
hintText = (hint ?: "").toString()
hintText = (hint ?: "")
stateKeyboardButtonListener = context as StateKeyboardButtonListener
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,20 @@ class NumericInputInteractionView @JvmOverloads constructor(
defStyle: Int = android.R.attr.editTextStyle
) : EditText(context, attrs, defStyle), View.OnFocusChangeListener {
private val stateKeyboardButtonListener: StateKeyboardButtonListener
private val hintText: CharSequence

init {
onFocusChangeListener = this
hintText = (hint ?: "")
stateKeyboardButtonListener = context as StateKeyboardButtonListener
}

override fun onFocusChange(v: View, hasFocus: Boolean) = if (hasFocus) {
hint = ""
typeface = Typeface.DEFAULT
showSoftKeyboard(v, context)
} else {
hint = hintText
if (text.isEmpty()) setTypeface(typeface, Typeface.ITALIC)
hideSoftKeyboard(v, context)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ class TextInputInteractionView @JvmOverloads constructor(
attrs: AttributeSet? = null,
defStyle: Int = android.R.attr.editTextStyle
) : EditText(context, attrs, defStyle), View.OnFocusChangeListener {
private val hintText: String
private val hintText: CharSequence
private val stateKeyboardButtonListener: StateKeyboardButtonListener

init {
onFocusChangeListener = this
hintText = (hint ?: "").toString()
hintText = (hint ?: "")
stateKeyboardButtonListener = context as StateKeyboardButtonListener
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.oppia.app.databinding

import android.text.TextWatcher
import android.widget.EditText
import androidx.databinding.BindingAdapter

/** Binding adapter for setting a [TextWatcher] as a change listener for an [EditText]. */
@BindingAdapter("app:textChangedListener")
fun bindTextWatcher(editText: EditText, textWatcher: TextWatcher) {
editText.addTextChangedListener(textWatcher)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package org.oppia.app.parser

import android.content.Context
import androidx.annotation.StringRes
import org.oppia.app.R
import org.oppia.app.customview.interaction.FractionInputInteractionView
import org.oppia.app.model.Fraction
import org.oppia.domain.util.normalizeWhitespace

Expand All @@ -8,14 +12,59 @@ class StringToFractionParser {
private val wholeNumberOnlyRegex = """^-? ?(\d+)$""".toRegex()
private val fractionOnlyRegex = """^-? ?(\d+) ?/ ?(\d+)$""".toRegex()
private val mixedNumberRegex = """^-? ?(\d+) (\d+) ?/ ?(\d+)$""".toRegex()
private val invalidCharsRegex = """^[\d\s/-]+$""".toRegex()
private val invalidCharsLengthRegex = "\\d{8,}".toRegex()

fun getFractionFromString(text: String): Fraction {
/**
* Returns a [FractionParsingError] for the specified text input if it's an invalid fraction, or
* [FractionParsingError.VALID] if no issues are found. Note that a valid fraction returned by this method is guaranteed
* to be parsed correctly by [parseRegularFraction].
*
* This method should only be used when a user tries submitting an answer. Real-time error detection should be done
* using [getRealTimeAnswerError], instead.
*/
rt4914 marked this conversation as resolved.
Show resolved Hide resolved
fun getSubmitTimeError(text: String): FractionParsingError {
if (invalidCharsLengthRegex.find(text) != null)
return FractionParsingError.NUMBER_TOO_LONG
val fraction = parseFraction(text)
return when {
fraction == null -> FractionParsingError.INVALID_FORMAT
fraction.denominator == 0 -> FractionParsingError.DIVISION_BY_ZERO
else -> FractionParsingError.VALID
}
}

/**
* Returns a [FractionParsingError] for obvious incorrect fraction formatting issues for the specified raw text, or
* [FractionParsingError.VALID] if not such issues are found.
*
* Note that this method returning a valid result does not guarantee the text is a valid fraction--
* [getSubmitTimeError] should be used for that, instead. This method is meant to be used as a quick sanity check for
* general validity, not for definite correctness.
*/
rt4914 marked this conversation as resolved.
Show resolved Hide resolved
fun getRealTimeAnswerError(text: String): FractionParsingError {
val normalized = text.normalizeWhitespace()
return when {
!normalized.matches(invalidCharsRegex) -> FractionParsingError.INVALID_CHARS
normalized.startsWith("/") -> FractionParsingError.INVALID_FORMAT
normalized.count { it == '/' } > 1 -> FractionParsingError.INVALID_FORMAT
normalized.lastIndexOf('-') > 0 -> FractionParsingError.INVALID_FORMAT
else -> FractionParsingError.VALID
}
}

/** Returns a [Fraction] parse from the specified raw text string. */
fun parseFraction(text: String): Fraction? {
// Normalize whitespace to ensure that answer follows a simpler subset of possible patterns.
val inputText: String = text.normalizeWhitespace()
return parseMixedNumber(inputText)
?: parseFraction(inputText)
?: parseRegularFraction(inputText)
?: parseWholeNumber(inputText)
?: throw IllegalArgumentException("Incorrectly formatted fraction: $text")
}

/** Returns a [Fraction] parse from the specified raw text string. */
fun parseFractionFromString(text: String): Fraction {
return parseFraction(text) ?: throw IllegalArgumentException("Incorrectly formatted fraction: $text")
}

private fun parseMixedNumber(inputText: String): Fraction? {
Expand All @@ -29,7 +78,7 @@ class StringToFractionParser {
.build()
}

private fun parseFraction(inputText: String): Fraction? {
private fun parseRegularFraction(inputText: String): Fraction? {
val fractionOnlyMatch = fractionOnlyRegex.matchEntire(inputText) ?: return null
val (_, numeratorText, denominatorText) = fractionOnlyMatch.groupValues
// Fraction-only numbers imply no whole number.
Expand All @@ -53,4 +102,18 @@ class StringToFractionParser {
}

private fun isInputNegative(inputText: String): Boolean = inputText.startsWith("-")

/** Enum to store the errors of [FractionInputInteractionView]. */
nikitamarysolomanpvt marked this conversation as resolved.
Show resolved Hide resolved
enum class FractionParsingError(@StringRes private var error: Int?) {
VALID(error = null),
INVALID_CHARS(error = R.string.fraction_error_invalid_chars),
INVALID_FORMAT(error = R.string.fraction_error_invalid_format),
DIVISION_BY_ZERO(error = R.string.fraction_error_divide_by_zero),
NUMBER_TOO_LONG(error = R.string.fraction_error_larger_than_seven_digits);

/** Returns the string corresponding to this error's string resources, or null if there is none. */
fun getErrorMessageFromStringRes(context: Context): String? {
return error?.let(context::getString)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import android.view.View
import android.view.ViewGroup
import org.oppia.app.fragment.InjectableFragment
import org.oppia.app.model.UserAnswer
import org.oppia.app.player.state.answerhandling.InteractionAnswerErrorReceiver
import org.oppia.app.player.state.answerhandling.InteractionAnswerHandler
import org.oppia.app.player.state.answerhandling.InteractionAnswerReceiver
import javax.inject.Inject

/** Fragment that represents the current state of an exploration. */
class StateFragment : InjectableFragment(), InteractionAnswerReceiver {
class StateFragment : InjectableFragment(), InteractionAnswerReceiver, InteractionAnswerHandler,
InteractionAnswerErrorReceiver {
companion object {
/**
* Creates a new instance of a StateFragment.
Expand Down Expand Up @@ -46,6 +49,10 @@ class StateFragment : InjectableFragment(), InteractionAnswerReceiver {

fun handleKeyboardAction() = stateFragmentPresenter.handleKeyboardAction()

override fun onPendingAnswerError(pendingAnswerError: String?) {
stateFragmentPresenter.updateSubmitButton(pendingAnswerError)
}

fun setAudioBarVisibility(visibility: Boolean) = stateFragmentPresenter.setAudioBarVisibility(visibility)

fun scrollToTop() = stateFragmentPresenter.scrollToTop()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ import org.oppia.app.model.EphemeralState
import org.oppia.app.model.Interaction
import org.oppia.app.model.State
import org.oppia.app.model.SubtitledHtml
import org.oppia.app.player.audio.AudioButtonListener
import org.oppia.app.model.UserAnswer
import org.oppia.app.player.audio.AudioButtonListener
import org.oppia.app.player.audio.AudioFragment
import org.oppia.app.player.audio.AudioUiManager
import org.oppia.app.player.state.answerhandling.InteractionAnswerErrorReceiver
import org.oppia.app.player.state.answerhandling.InteractionAnswerReceiver
import org.oppia.app.player.state.itemviewmodel.ContentViewModel
import org.oppia.app.player.state.itemviewmodel.ContinueInteractionViewModel
Expand Down Expand Up @@ -100,7 +101,7 @@ class StateFragmentPresenter @Inject constructor(
/**
* A list of view models corresponding to past view models that are hidden by default. These are intentionally not
* retained upon configuration changes since the user can just re-expand the list. Note that the first element of this
* list (when initialized), will always be the previous answers header to help locate the items in the recycler view
* list (when initialized), will always be the previous answer's header to help locate the items in the recycler view
* (when present).
*/
private val previousAnswerViewModels: MutableList<StateItemViewModel> = mutableListOf()
Expand All @@ -109,6 +110,7 @@ class StateFragmentPresenter @Inject constructor(
* configuration changes since the user can just re-expand the list.
*/
private var hasPreviousResponsesExpanded: Boolean = false
private lateinit var stateNavigationButtonViewModel: StateNavigationButtonViewModel

fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View? {
explorationId = fragment.arguments!!.getString(STATE_FRAGMENT_EXPLORATION_ID_ARGUMENT_KEY)!!
Expand Down Expand Up @@ -399,7 +401,7 @@ class StateFragmentPresenter @Inject constructor(
Handler().postDelayed({
binding.congratulationTextview.clearAnimation()
binding.congratulationTextview.visibility = View.INVISIBLE
},2000)
}, 2000)
}

/** Helper for subscribeToAnswerOutcome. */
Expand Down Expand Up @@ -440,7 +442,8 @@ class StateFragmentPresenter @Inject constructor(

fun handleKeyboardAction() {
hideKeyboard()
handleSubmitAnswer(viewModel.getPendingAnswer())
if (stateNavigationButtonViewModel.isInteractionButtonActive.get()!!)
handleSubmitAnswer(viewModel.getPendingAnswer())
}

override fun onContinueButtonClicked() {
Expand Down Expand Up @@ -473,7 +476,7 @@ class StateFragmentPresenter @Inject constructor(
) {
val interactionViewModelFactory = interactionViewModelFactoryMap.getValue(interaction.id)
pendingItemList += interactionViewModelFactory(
explorationId, interaction, fragment as InteractionAnswerReceiver
explorationId, interaction, fragment as InteractionAnswerReceiver, fragment as InteractionAnswerErrorReceiver
)
}

Expand Down Expand Up @@ -559,7 +562,7 @@ class StateFragmentPresenter @Inject constructor(
hasGeneralContinueButton: Boolean,
stateIsTerminal: Boolean
) {
val stateNavigationButtonViewModel =
stateNavigationButtonViewModel =
StateNavigationButtonViewModel(context, this as StateNavigationButtonListener)
stateNavigationButtonViewModel.updatePreviousButton(isEnabled = hasPreviousState)

Expand Down Expand Up @@ -611,4 +614,13 @@ class StateFragmentPresenter @Inject constructor(
}

private fun isAudioShowing(): Boolean = viewModel.isAudioBarVisible.get()!!

/** Updates submit button UI as active if pendingAnswerError null else inactive. */
fun updateSubmitButton(pendingAnswerError: String?) {
nikitamarysolomanpvt marked this conversation as resolved.
Show resolved Hide resolved
if (pendingAnswerError != null) {
stateNavigationButtonViewModel.isInteractionButtonActive.set(false)
} else {
stateNavigationButtonViewModel.isInteractionButtonActive.set(true)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.databinding.ObservableList
import androidx.lifecycle.ViewModel
import org.oppia.app.fragment.FragmentScope
import org.oppia.app.model.UserAnswer
import org.oppia.app.player.state.answerhandling.AnswerErrorCategory
import org.oppia.app.player.state.answerhandling.InteractionAnswerHandler
import org.oppia.app.player.state.itemviewmodel.StateItemViewModel
import org.oppia.app.viewmodel.ObservableArrayList
Expand Down Expand Up @@ -34,7 +35,10 @@ class StateViewModel @Inject constructor() : ObservableViewModel() {

// TODO(#164): Add a hasPendingAnswer() that binds to the enabled state of the Submit button.
fun getPendingAnswer(): UserAnswer {
nikitamarysolomanpvt marked this conversation as resolved.
Show resolved Hide resolved
return getPendingAnswerHandler(itemList)?.getPendingAnswer() ?: UserAnswer.getDefaultInstance()
return if (getPendingAnswerHandler(itemList)?.checkPendingAnswerError(AnswerErrorCategory.SUBMIT_TIME) != null) {
UserAnswer.getDefaultInstance()
} else
getPendingAnswerHandler(itemList)?.getPendingAnswer() ?: UserAnswer.getDefaultInstance()
}

private fun getPendingAnswerHandler(itemList: List<StateItemViewModel>): InteractionAnswerHandler? {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.oppia.app.player.state.answerhandling

/**
* A handler for interaction answer's error receiving to update submit button.
* Handlers can either require an additional user action before the submit button UI can be updated.
*/
interface InteractionAnswerErrorReceiver {

/**
* Called when an error was detected upon answer submission. Implementations are recommended to prevent further answer
* submission until the pending answer itself changes. The interaction is responsible for displaying the error provided
* here, not the implementation.
*/
fun onPendingAnswerError(pendingAnswerError: String?) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,15 @@ interface InteractionAnswerHandler {
*/
fun isExplicitAnswerSubmissionRequired(): Boolean = true

/** Return the current answer's error messages if not valid else return null. */
nikitamarysolomanpvt marked this conversation as resolved.
Show resolved Hide resolved
fun checkPendingAnswerError(category: AnswerErrorCategory): String? {
return null
}

/** Return the current answer that is ready for handling. */
fun getPendingAnswer(): UserAnswer
fun getPendingAnswer(): UserAnswer? {
return null
}
}

/**
Expand All @@ -25,3 +32,11 @@ interface InteractionAnswerHandler {
interface InteractionAnswerReceiver {
fun onAnswerReadyForSubmission(answer: UserAnswer)
}

/** Categories of errors that can be inferred from a pending answer. */
enum class AnswerErrorCategory {
/** Corresponds to errors that may be found while the user is trying to input an answer. */
REAL_TIME,
/** Corresponds to errors that may be found only when a user tries to submit an answer. */
SUBMIT_TIME
}
Loading