Skip to content

Commit

Permalink
added audio based content highlighting - to highlight the correct rec…
Browse files Browse the repository at this point in the history
…ycler view item based on the audio track playing.
  • Loading branch information
justdvnsh committed Mar 21, 2021
1 parent 497263c commit 7f74425
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,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.FeedbackViewModel
import org.oppia.android.app.player.state.listener.RouteToHintsAndSolutionListener
import org.oppia.android.app.player.stopplaying.StopStatePlayingSessionListener
import org.oppia.android.app.utility.SplitScreenManager
Expand Down Expand Up @@ -79,6 +80,7 @@ class StateFragmentPresenter @Inject constructor(
private lateinit var currentStateName: String
private lateinit var binding: StateFragmentBinding
private lateinit var recyclerViewAdapter: RecyclerView.Adapter<*>
private var feedbackViewModel: FeedbackViewModel? = null

private val viewModel: StateViewModel by lazy {
getStateViewModel()
Expand Down Expand Up @@ -216,6 +218,10 @@ class StateFragmentPresenter @Inject constructor(
}
}

fun handleContentCardHighlighting(contentId: String, playing: Boolean) {
recyclerViewAssembler.handleContentCardHighlighting(contentId, playing)
}

fun handleAudioClick() = recyclerViewAssembler.toggleAudioPlaybackState()

fun handleKeyboardAction() {
Expand Down Expand Up @@ -287,6 +293,8 @@ class StateFragmentPresenter @Inject constructor(
val audioFragment: AudioFragment = AudioFragment.newInstance(profileId.internalId)
fragment.childFragmentManager.beginTransaction()
.add(R.id.audio_fragment_placeholder, audioFragment, TAG_AUDIO_FRAGMENT).commitNow()

// (getAudioFragment() as AudioFragment).setContentIdListener(fragment as AudioContentIdListener)
}
return getAudioFragment() as? AudioUiManager
}
Expand Down Expand Up @@ -413,7 +421,7 @@ class StateFragmentPresenter @Inject constructor(
} else {
viewModel.setCanSubmitAnswer(canSubmitAnswer = false)
}
recyclerViewAssembler.readOutAnswerFeedback(result.feedback)
// recyclerViewAssembler.readOutAnswerFeedback(result.feedback, fragment)
}
}
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.oppia.android.app.player.state

import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.animation.AccelerateInterpolator
Expand Down Expand Up @@ -172,6 +173,10 @@ class StatePlayerRecyclerViewAssembler private constructor(
delayShowAdditionalHintsFromWrongAnswerMs
)

private lateinit var stateContentId: String
private var contentViewModel: ContentViewModel? = null
private var feedbackViewModel: FeedbackViewModel? = null

/** The most recent content ID read by the audio system. */
private var audioPlaybackContentId: String? = null

Expand Down Expand Up @@ -208,7 +213,7 @@ class StatePlayerRecyclerViewAssembler private constructor(
isSplitView: Boolean
): Pair<List<StateItemViewModel>, List<StateItemViewModel>> {
this.isSplitView.set(isSplitView)

stateContentId = ephemeralState.state.content.contentId
val hasPreviousState = ephemeralState.hasPreviousState
previousAnswerViewModels.clear()
val conversationPendingItemList = mutableListOf<StateItemViewModel>()
Expand Down Expand Up @@ -322,13 +327,18 @@ class StatePlayerRecyclerViewAssembler private constructor(
gcsEntityId: String
) {
val contentSubtitledHtml: SubtitledHtml = ephemeralState.state.content
pendingItemList += ContentViewModel(
contentViewModel = ContentViewModel(
contentSubtitledHtml.contentId,
contentSubtitledHtml.html,
gcsEntityId,
hasConversationView,
isSplitView.get()!!,
playerFeatureSet.conceptCardSupport
)
if (isAudioPlaybackEnabled()) {
handleContentCardHighlighting(contentViewModel!!.contentId, true)
}
pendingItemList += contentViewModel!!
}

private fun addPreviousAnswers(
Expand Down Expand Up @@ -397,6 +407,7 @@ class StatePlayerRecyclerViewAssembler private constructor(
}
}
if (playerFeatureSet.feedbackSupport) {
Log.d("MYSELF", "FEEDBACK ENABLED")
createFeedbackItem(answerAndResponse.feedback, gcsEntityId)?.let(
pendingItemList::add
)
Expand Down Expand Up @@ -498,19 +509,38 @@ class StatePlayerRecyclerViewAssembler private constructor(
val audioUiManager = getAudioUiManager()
if (!isAudioPlaybackEnabled()) {
audioUiManager?.enableAudioPlayback(audioPlaybackContentId)
handleContentCardHighlighting(audioPlaybackContentId ?: stateContentId, true)
} else {
audioUiManager?.disableAudioPlayback()
handleContentCardHighlighting(audioPlaybackContentId ?: stateContentId, false)
}
}
}

/*
* Handle the Content Card highlighting -
* */
fun handleContentCardHighlighting(contentId: String, isPlaying: Boolean) {

if (contentViewModel != null && contentViewModel!!.contentId == contentId) {
contentViewModel!!.updateIsAudioPlaying(isPlaying)
}

if (feedbackViewModel != null && feedbackViewModel!!.contentId == contentId) {
contentViewModel!!.updateIsAudioPlaying(false)
feedbackViewModel!!.updateIsAudioPlaying(isPlaying)

}
}

/**
* Possibly reads out the specified feedback, interrupting any existing audio that's playing.
* This should only be called if voiceover support has been enabled.
*/
fun readOutAnswerFeedback(feedback: SubtitledHtml) {
if (playerFeatureSet.supportAudioVoiceovers && isAudioPlaybackEnabled()) {
audioPlaybackContentId = feedback.contentId
handleContentCardHighlighting(feedback.contentId, true)
getAudioUiManager()?.loadFeedbackAudio(feedback.contentId, allowAutoPlay = true)
}
}
Expand Down Expand Up @@ -554,13 +584,20 @@ class StatePlayerRecyclerViewAssembler private constructor(
): FeedbackViewModel? {
// Only show feedback if there's some to show.
if (feedback.html.isNotEmpty()) {
return FeedbackViewModel(
Log.d("MYSELF", "FEEDBACK.HTML NOT NULL")
feedbackViewModel = FeedbackViewModel(
feedback.contentId,
feedback.html,
gcsEntityId,
hasConversationView,
isSplitView.get()!!,
playerFeatureSet.conceptCardSupport
)
feedbackViewModel!!.updateIsAudioPlaying(false)
if (isAudioPlaybackEnabled()) {
readOutAnswerFeedback(feedback)
}
return feedbackViewModel
}
return null
}
Expand Down Expand Up @@ -922,6 +959,7 @@ class StatePlayerRecyclerViewAssembler private constructor(
supportsLinks = true,
supportsConceptCards = contentViewModel.supportsConceptCards
)
binding.viewModel = contentViewModel
}
)
featureSets += PlayerFeatureSet(contentSupport = true)
Expand Down Expand Up @@ -956,6 +994,7 @@ class StatePlayerRecyclerViewAssembler private constructor(
supportsLinks = true,
supportsConceptCards = feedbackViewModel.supportsConceptCards
)
binding.viewModel = feedbackViewModel
}
)
featureSets += PlayerFeatureSet(feedbackSupport = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
package org.oppia.android.app.player.state.itemviewmodel

import androidx.databinding.Observable
import androidx.databinding.ObservableField

/** [StateItemViewModel] for content-card state. */
class ContentViewModel(
val contentId: String,
val htmlContent: CharSequence,
val gcsEntityId: String,
val hasConversationView: Boolean,
val isSplitView: Boolean,
val supportsConceptCards: Boolean
) : StateItemViewModel(ViewType.CONTENT)
) : StateItemViewModel(ViewType.CONTENT) {
val isPlaying = ObservableField<Boolean>(false)

fun updateIsAudioPlaying(playing: Boolean) = isPlaying.set(playing)
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
package org.oppia.android.app.player.state.itemviewmodel

import androidx.databinding.ObservableField
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData

/** [StateItemViewModel] for feedback blurbs. */
class FeedbackViewModel(
val contentId: String,
val htmlContent: CharSequence,
val gcsEntityId: String,
val hasConversationView: Boolean,
val isSplitView: Boolean,
val supportsConceptCards: Boolean
) : StateItemViewModel(ViewType.FEEDBACK)
) : StateItemViewModel(ViewType.FEEDBACK) {
val isPlaying = ObservableField<Boolean>(false)
val isInitialized: MutableLiveData<Boolean> = MutableLiveData(false)

fun updateIsAudioPlaying(playing: Boolean) = isPlaying.set(playing)

fun updateIsInitialized(initialized: Boolean) {
isInitialized.value = initialized
}
}
12 changes: 12 additions & 0 deletions app/src/main/res/drawable/content_yellow_background.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="2dp"
android:color="@color/oppiaContentHighlighting"/>
<corners
android:radius="4dp"/>
<solid
android:color="@color/oppiaSolidBlue"/>
</shape>
2 changes: 1 addition & 1 deletion app/src/main/res/layout/content_item.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@{viewModel.hasConversationView ? @drawable/content_blue_background : @drawable/transparent_background}"
android:background="@{viewModel.isPlaying() ? @drawable/content_yellow_background : @drawable/transparent_background}"
app:explorationSplitViewMarginApplicable="@{viewModel.hasConversationView &amp;&amp; viewModel.isSplitView}"
app:explorationSplitViewMarginBottom="@{@dimen/space_0dp}"
app:explorationSplitViewMarginEnd="@{@dimen/content_item_exploration_split_view_margin_end}"
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/layout/feedback_item.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@{viewModel.hasConversationView ? @drawable/content_blue_background : @drawable/transparent_background}"
android:background="@{viewModel.isPlaying() ? @drawable/content_yellow_background : @drawable/transparent_background}"
app:explorationSplitViewMarginApplicable="@{viewModel.hasConversationView &amp;&amp; viewModel.isSplitView}"
app:explorationSplitViewMarginBottom="@{@dimen/space_0dp}"
app:explorationSplitViewMarginEnd="@{@dimen/feedback_item_exploration_split_view_margin_end}"
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@
<color name="onboarding3StatusBar">#AD8500</color>
<color name="onboarding4StatusBar">#3B5893</color>
<color name="registrationStatusBar">#9CB1BE</color>
<color name="oppiaContentHighlighting">#F2D140</color>
<!-- ICON COLORS -->
<color name="mergeIconEnabled">#FF000000</color>
<color name="mergeIconDisabled">#999999</color>
Expand Down

0 comments on commit 7f74425

Please sign in to comment.