diff --git a/app/src/main/java/org/oppia/android/app/player/state/StateFragmentPresenter.kt b/app/src/main/java/org/oppia/android/app/player/state/StateFragmentPresenter.kt index 9aabc25f075..c9bb86f6a47 100755 --- a/app/src/main/java/org/oppia/android/app/player/state/StateFragmentPresenter.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/StateFragmentPresenter.kt @@ -33,6 +33,7 @@ import org.oppia.android.app.player.audio.AudioUiManager import org.oppia.android.app.player.state.ConfettiConfig.LARGE_CONFETTI_BURST import org.oppia.android.app.player.state.ConfettiConfig.MEDIUM_CONFETTI_BURST import org.oppia.android.app.player.state.ConfettiConfig.MINI_CONFETTI_BURST +import org.oppia.android.app.player.state.itemviewmodel.StateItemViewModel import org.oppia.android.app.player.state.listener.RouteToHintsAndSolutionListener import org.oppia.android.app.player.stopplaying.StopStatePlayingSessionWithSavedProgressListener import org.oppia.android.app.survey.SurveyWelcomeDialogFragment @@ -258,7 +259,9 @@ class StateFragmentPresenter @Inject constructor( ) .addHintsAndSolutionsSupport() .addAudioVoiceoverSupport( - explorationId, viewModel.currentStateName, viewModel.isAudioBarVisible, + explorationId, + viewModel.currentStateName, + viewModel.isAudioBarVisible, this::getAudioUiManager ) .addConceptCardSupport() @@ -304,6 +307,14 @@ class StateFragmentPresenter @Inject constructor( } } + private fun areListsTheSame(l: List, r: List): Boolean { + if (l.size != r.size) { + return false + } + + return l.zip(r).all { (x, y) -> x.areContentsTheSame(y) } + } + private fun processEphemeralState(ephemeralState: EphemeralState) { explorationCheckpointState = ephemeralState.checkpointState val shouldSplit = splitScreenManager.shouldSplitScreen(ephemeralState.state.interaction.id) @@ -329,10 +340,14 @@ class StateFragmentPresenter @Inject constructor( shouldSplit ) - viewModel.itemList.clear() - viewModel.itemList += dataPair.first - viewModel.rightItemList.clear() - viewModel.rightItemList += dataPair.second + if (!areListsTheSame(viewModel.itemList, dataPair.first)) { + viewModel.itemList.clear() + viewModel.itemList += dataPair.first + } + if (!areListsTheSame(viewModel.rightItemList, dataPair.second)) { + viewModel.rightItemList.clear() + viewModel.rightItemList += dataPair.second + } if (isInNewState) { (binding.stateRecyclerView.layoutManager as LinearLayoutManager).scrollToPositionWithOffset( @@ -400,7 +415,9 @@ class StateFragmentPresenter @Inject constructor( return when (ephemeralStateResult) { is AsyncResult.Failure -> { oppiaLogger.e( - "StateFragment", "Failed to retrieve answer outcome", ephemeralStateResult.error + "StateFragment", + "Failed to retrieve answer outcome", + ephemeralStateResult.error ) AnswerOutcome.getDefaultInstance() } @@ -465,7 +482,6 @@ class StateFragmentPresenter @Inject constructor( } private fun showHintsAndSolutions(helpIndex: HelpIndex, isCurrentStatePendingState: Boolean) { - if (!isCurrentStatePendingState) { // If current state is not the pending top state, hide the hint bulb. setHintOpenedAndUnRevealed(false) @@ -499,7 +515,6 @@ class StateFragmentPresenter @Inject constructor( private fun setHintOpenedAndUnRevealed(isHintUnrevealed: Boolean) { viewModel.setHintOpenedAndUnRevealedVisibility(isHintUnrevealed) if (isHintUnrevealed) { - val hintBulbAnimation = AnimationUtils.loadAnimation( context, R.anim.hint_bulb_animation diff --git a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/ContentViewModel.kt b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/ContentViewModel.kt index 5a581ea586b..b09c294246e 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/ContentViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/ContentViewModel.kt @@ -7,4 +7,15 @@ class ContentViewModel( val hasConversationView: Boolean, val isSplitView: Boolean, val supportsConceptCards: Boolean -) : StateItemViewModel(ViewType.CONTENT) +) : StateItemViewModel(ViewType.CONTENT) { + override fun areContentsTheSame(other: StateItemViewModel): Boolean { + if (this === other) return true + if (other !is ContentViewModel) return false + + return htmlContent == other.htmlContent && + gcsEntityId == other.gcsEntityId && + hasConversationView == other.hasConversationView && + isSplitView == other.isSplitView && + supportsConceptCards == other.supportsConceptCards + } +} diff --git a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/FractionInteractionViewModel.kt b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/FractionInteractionViewModel.kt index 193248effe7..3afed42bc2d 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/FractionInteractionViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/FractionInteractionViewModel.kt @@ -56,6 +56,18 @@ class FractionInteractionViewModel private constructor( ) } + override fun areContentsTheSame(other: StateItemViewModel): Boolean { + if (this === other) return true + if (other !is FractionInteractionViewModel) return false + + return ( + hasConversationView == other.hasConversationView && + isSplitView == other.isSplitView && + pendingAnswerError == other.pendingAnswerError && + hintText == other.hintText + ) + } + override fun getPendingAnswer(): UserAnswer = UserAnswer.newBuilder().apply { if (answerText.isNotEmpty()) { val answerTextString = answerText.toString() diff --git a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/StateItemViewModel.kt b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/StateItemViewModel.kt index 3d93249cf7c..c077cc5b402 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/StateItemViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/StateItemViewModel.kt @@ -61,4 +61,8 @@ abstract class StateItemViewModel(val viewType: ViewType) : ObservableViewModel( timeToStartNoticeAnimationMs: Long? ): StateItemViewModel } + + open fun areContentsTheSame(other: StateItemViewModel): Boolean { + return false + } } diff --git a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/SubmitButtonViewModel.kt b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/SubmitButtonViewModel.kt index 073adea0828..7b191140074 100644 --- a/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/SubmitButtonViewModel.kt +++ b/app/src/main/java/org/oppia/android/app/player/state/itemviewmodel/SubmitButtonViewModel.kt @@ -12,4 +12,16 @@ class SubmitButtonViewModel( val previousNavigationButtonListener: PreviousNavigationButtonListener, val submitNavigationButtonListener: SubmitNavigationButtonListener, val isSplitView: Boolean -) : StateItemViewModel(ViewType.SUBMIT_ANSWER_BUTTON) +) : StateItemViewModel(ViewType.SUBMIT_ANSWER_BUTTON) { + override fun areContentsTheSame(other: StateItemViewModel): Boolean { + if (this === other) return true + if (other !is SubmitButtonViewModel) return false + + return ( + canSubmitAnswer.get() == other.canSubmitAnswer.get() && + hasConversationView == other.hasConversationView && + hasPreviousButton == other.hasPreviousButton && + isSplitView == other.isSplitView + ) + } +}