Skip to content

Commit

Permalink
Merge branch 'develop' into fix-thumbnails-multiple-classrooms
Browse files Browse the repository at this point in the history
  • Loading branch information
BenHenning authored Jan 21, 2025
2 parents 16acee1 + f3c6dff commit bc8c66a
Show file tree
Hide file tree
Showing 46 changed files with 2,198 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import org.oppia.android.domain.translation.TranslationController
/** Completed story view model for the recycler view in [CompletedStoryListFragment]. */
class CompletedStoryItemViewModel(
private val activity: AppCompatActivity,
private val internalProfileId: Int,
private val profileId: ProfileId,
val completedStory: CompletedStory,
val entityType: String,
private val intentFactoryShim: IntentFactoryShim,
Expand All @@ -33,7 +33,7 @@ class CompletedStoryItemViewModel(
/** Called when user clicks on CompletedStoryItem. */
fun onCompletedStoryItemClicked() {
routeToTopicPlayStory(
ProfileId.newBuilder().setInternalId(internalProfileId).build(),
profileId,
completedStory.classroomId,
completedStory.topicId,
completedStory.storyId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ class CompletedStoryListActivity : InjectableAutoLocalizedAppCompatActivity() {
super.onCreate(savedInstanceState)
(activityComponent as ActivityComponentImpl).inject(this)

val internalProfileId: Int = intent?.extractCurrentUserProfileId()?.internalId ?: -1
completedStoryListActivityPresenter.handleOnCreate(internalProfileId)
val profileId = intent?.extractCurrentUserProfileId() ?: ProfileId.getDefaultInstance()
completedStoryListActivityPresenter.handleOnCreate(profileId)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.oppia.android.app.completedstorylist
import androidx.appcompat.app.AppCompatActivity
import org.oppia.android.R
import org.oppia.android.app.activity.ActivityScope
import org.oppia.android.app.model.ProfileId
import javax.inject.Inject

/** The presenter for [CompletedStoryListActivity]. */
Expand All @@ -12,15 +13,15 @@ class CompletedStoryListActivityPresenter @Inject constructor(
) {

/** Initializes views for [CompletedStoryListActivity] and binds [CompletedStoryListFragment]. */
fun handleOnCreate(internalProfileId: Int) {
fun handleOnCreate(profileId: ProfileId) {
activity.setContentView(R.layout.completed_story_list_activity)
if (getCompletedStoryListFragment() == null) {
activity
.supportFragmentManager
.beginTransaction()
.add(
R.id.completed_story_list_fragment_placeholder,
CompletedStoryListFragment.newInstance(internalProfileId),
CompletedStoryListFragment.newInstance(profileId),
CompletedStoryListFragment.COMPLETED_STORY_LIST_FRAGMENT_TAG
).commitNow()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ class CompletedStoryListFragment : InjectableFragment() {
const val COMPLETED_STORY_LIST_FRAGMENT_TAG = "COMPLETED_STORY_LIST_FRAGMENT_TAG"

/** Returns a new [CompletedStoryListFragment] to display corresponding to the specified profile ID. */
fun newInstance(internalProfileId: Int): CompletedStoryListFragment {
val profileId = ProfileId.newBuilder().setInternalId(internalProfileId).build()
fun newInstance(profileId: ProfileId): CompletedStoryListFragment {
return CompletedStoryListFragment().apply {
arguments = Bundle().apply {
decorateWithUserProfileId(profileId)
Expand All @@ -47,11 +46,10 @@ class CompletedStoryListFragment : InjectableFragment() {
"Expected arguments to be passed to CompletedStoryListFragment"
}
val profileId = arguments.extractCurrentUserProfileId()
val internalProfileId = profileId.internalId
return completedStoryListFragmentPresenter.handleCreateView(
inflater,
container,
internalProfileId
profileId
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import org.oppia.android.R
import org.oppia.android.app.model.ProfileId
import org.oppia.android.app.recyclerview.BindableAdapter
import org.oppia.android.databinding.CompletedStoryItemBinding
import org.oppia.android.databinding.CompletedStoryListFragmentBinding
Expand All @@ -26,9 +27,9 @@ class CompletedStoryListFragmentPresenter @Inject constructor(
fun handleCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
internalProfileId: Int
profileId: ProfileId
): View? {
viewModel.setProfileId(internalProfileId)
viewModel.setProfileId(profileId)

binding = CompletedStoryListFragmentBinding
.inflate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,11 @@ class CompletedStoryListViewModel @Inject constructor(
private val translationController: TranslationController,
@StoryHtmlParserEntityType private val entityType: String
) : ObservableViewModel() {
/** [internalProfileId] needs to be set before any of the live data members can be accessed. */
private var internalProfileId: Int = -1
/** [profileId] needs to be set before any of the live data members can be accessed. */
private var profileId: ProfileId = ProfileId.getDefaultInstance()

private val completedStoryListResultLiveData: LiveData<AsyncResult<CompletedStoryList>> by lazy {
topicController.getCompletedStoryList(
ProfileId.newBuilder().setInternalId(internalProfileId).build()
).toLiveData()
topicController.getCompletedStoryList(profileId).toLiveData()
}

private val completedStoryLiveData: LiveData<CompletedStoryList> by lazy {
Expand All @@ -45,8 +43,8 @@ class CompletedStoryListViewModel @Inject constructor(
}

/** Sets internalProfileId to this ViewModel. */
fun setProfileId(internalProfileId: Int) {
this.internalProfileId = internalProfileId
fun setProfileId(profileId: ProfileId) {
this.profileId = profileId
}

private fun processCompletedStoryListResult(
Expand Down Expand Up @@ -74,7 +72,7 @@ class CompletedStoryListViewModel @Inject constructor(
completedStoryList.completedStoryList.map { completedStory ->
CompletedStoryItemViewModel(
activity,
internalProfileId,
profileId,
completedStory,
entityType,
intentFactoryShim,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ class LicenseTextViewerFragment : InjectableFragment() {

companion object {
/** Argument key for LicenseTextViewerFragment. */
private const val LICENSE_TEXT_VIEWER_FRAGMENT_ARGUMENTS_KEY =
"LicenseTextViewerFragment.arguments"
const val LICENSE_TEXT_VIEWER_FRAGMENT_ARGUMENTS_KEY = "LicenseTextViewerFragment.arguments"

/** Returns an instance of [LicenseTextViewerFragment]. */
fun newInstance(dependencyIndex: Int, licenseIndex: Int): LicenseTextViewerFragment {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface LanguageInterface {
/**
* Returns whether the user is actively seeking a new audio position, that is, dragging the
* knob to a new position in the audio track.
* */
*/
fun getUserIsSeeking(): Boolean

/** Returns the position of the knob on the audio track. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import org.oppia.android.util.extensions.getProto
import org.oppia.android.util.extensions.putProto
import javax.inject.Inject

private const val POLICIES_FRAGMENT_POLICY_PAGE_ARGUMENT_PROTO = "PoliciesFragment.policy_page"
/** Argument key for PoliciesFragment. */
const val POLICIES_FRAGMENT_POLICY_PAGE_ARGUMENT_PROTO = "PoliciesFragment.policy_page"

/** Fragment that contains policies flow of the app. */
class PoliciesFragment : InjectableFragment() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ interface IntentFactoryShim {
/**
* Creates a [TopicActivity] intent for [PromotedStoryViewModel] and passes necessary string
* data.
* */
*/
fun createTopicPlayStoryActivityIntent(
context: Context,
internalProfileId: Int,
Expand All @@ -27,7 +27,7 @@ interface IntentFactoryShim {

/**
* Creates a [TopicActivity] intent which opens info-tab.
* */
*/
fun createTopicActivityIntent(
context: Context,
internalProfileId: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ interface StoryFragmentScroller {
/**
* Scrolls smoothly (with animation) to the specified vertical pixel position in
* [StoryFragment].
* */
*/
fun smoothScrollToPosition(position: Int)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.oppia.android.app.utility
import android.content.Context
import android.content.Context.WINDOW_SERVICE
import android.util.DisplayMetrics
import android.util.TypedValue
import android.view.WindowManager
import org.oppia.android.app.model.ReadingTextSize
import javax.inject.Inject
Expand All @@ -21,16 +22,18 @@ class FontScaleConfigurationUtil @Inject constructor() {
// TODO(#3616): Migrate to the proper SDK 30+ APIs.
@Suppress("DEPRECATION") // The code is correct for targeted versions of Android.
windowManager!!.defaultDisplay.getMetrics(metrics)
// TODO(#5625): Migrate away from scaledDensity.
val scaledDensity = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 1.0f, metrics
) * configuration.fontScale
@Suppress("DEPRECATION")
metrics.scaledDensity = configuration.fontScale * metrics.density
metrics.scaledDensity = scaledDensity
context.createConfigurationContext(configuration)
context.resources.displayMetrics.setTo(metrics)
}

private fun getReadingTextSizeConfigurationUtil(readingTextSize: ReadingTextSize): Float {
return when (readingTextSize) {
ReadingTextSize.SMALL_TEXT_SIZE -> .8f
ReadingTextSize.SMALL_TEXT_SIZE -> 0.8f
ReadingTextSize.MEDIUM_TEXT_SIZE -> 1.0f
ReadingTextSize.LARGE_TEXT_SIZE -> 1.2f
ReadingTextSize.EXTRA_LARGE_TEXT_SIZE -> 1.4f
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import android.view.ViewParent
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.NestedScrollView
import androidx.drawerlayout.widget.DrawerLayout
import androidx.test.core.app.ActivityScenario.launch
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.Espresso.onView
Expand All @@ -23,6 +24,7 @@ import androidx.test.espresso.matcher.ViewMatchers.isClickable
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import androidx.test.espresso.util.HumanReadables
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import dagger.Component
import org.hamcrest.Matcher
import org.hamcrest.Matchers
Expand All @@ -44,6 +46,7 @@ import org.oppia.android.app.application.ApplicationStartupListenerModule
import org.oppia.android.app.application.testing.TestingBuildFlavorModule
import org.oppia.android.app.devoptions.DeveloperOptionsModule
import org.oppia.android.app.devoptions.DeveloperOptionsStarterModule
import org.oppia.android.app.model.AdministratorControlsFragmentArguments
import org.oppia.android.app.player.state.itemviewmodel.SplitScreenInteractionModule
import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.atPositionOnView
import org.oppia.android.app.recyclerview.RecyclerViewMatcher.Companion.scrollToPosition
Expand Down Expand Up @@ -98,6 +101,7 @@ import org.oppia.android.testing.time.FakeOppiaClockModule
import org.oppia.android.util.accessibility.AccessibilityTestModule
import org.oppia.android.util.caching.AssetModule
import org.oppia.android.util.caching.testing.CachingTestModule
import org.oppia.android.util.extensions.getProto
import org.oppia.android.util.gcsresource.GcsResourceModule
import org.oppia.android.util.locale.LocaleProdModule
import org.oppia.android.util.logging.LoggerModule
Expand Down Expand Up @@ -433,6 +437,35 @@ class AdministratorControlsFragmentTest {
}
}

@Test
fun testFragment_argumentsAreCorrect() {
launch<AdministratorControlsFragmentTestActivity>(
createAdministratorControlsFragmentTestActivityIntent(
profileId = internalProfileId
)
).use { scenario ->
testCoroutineDispatchers.runCurrent()
scenario.onActivity { activity ->

val administratorControlsFragment = activity.supportFragmentManager
.findFragmentById(R.id.administrator_controls_fragment_test_activity_fragment_container)
as AdministratorControlsFragment
val isMultipane = activity
.findViewById<DrawerLayout>(R.id.administrator_controls_activity_drawer_layout) != null

val arguments = checkNotNull(administratorControlsFragment.arguments) {
"Expected arguments to be passed to AdministratorControlsFragment"
}.getProto(
ADMINISTRATOR_CONTROLS_FRAGMENT_ARGUMENTS_KEY,
AdministratorControlsFragmentArguments.getDefaultInstance()
)
val receivedIsMultipane = arguments.isMultipane

assertThat(receivedIsMultipane).isEqualTo(isMultipane)
}
}
}

private fun clickAutoUpdateTopicContainer() {
onView(
atPositionOnView(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ import org.oppia.android.util.networking.NetworkConnectionDebugUtilModule
import org.oppia.android.util.networking.NetworkConnectionUtilDebugModule
import org.oppia.android.util.parser.html.HtmlParserEntityTypeModule
import org.oppia.android.util.parser.image.ImageParsingModule
import org.oppia.android.util.profile.CurrentUserProfileIdIntentDecorator.extractCurrentUserProfileId
import org.robolectric.annotation.Config
import org.robolectric.annotation.LooperMode
import javax.inject.Inject
Expand Down Expand Up @@ -1649,6 +1650,31 @@ class RecentlyPlayedFragmentTest {
}
}

@Test
fun testFragment_argumentsAreCorrect() {
ActivityScenario.launch<RecentlyPlayedActivity>(
createRecentlyPlayedActivityIntent(
internalProfileId = internalProfileId,
RecentlyPlayedActivityTitle.STORIES_FOR_YOU
)
).use { scenario ->
testCoroutineDispatchers.runCurrent()
scenario.onActivity { activity ->

val recentlyPlayedFragment = activity.supportFragmentManager
.findFragmentById(R.id.recently_played_fragment_placeholder) as RecentlyPlayedFragment

val arguments = checkNotNull(recentlyPlayedFragment.arguments) {
"Expected arguments to be passed to RecentlyPlayedFragment"
}
val profileId = arguments.extractCurrentUserProfileId()
val receivedInternalProfileId = profileId.internalId

assertThat(receivedInternalProfileId).isEqualTo(internalProfileId)
}
}
}

private fun setUpTestFragment(activity: RecentlyPlayedActivity) {
activity.supportFragmentManager
.beginTransaction()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.oppia.android.app.options
import android.app.Application
import android.content.Context
import android.content.Intent
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.drawerlayout.widget.DrawerLayout
import androidx.test.core.app.ActivityScenario
Expand All @@ -21,6 +22,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withContentDescription
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import dagger.Component
import org.hamcrest.Matchers.allOf
import org.junit.After
Expand All @@ -44,6 +46,7 @@ import org.oppia.android.app.model.AppLanguageActivityParams
import org.oppia.android.app.model.AudioLanguage
import org.oppia.android.app.model.AudioLanguageActivityParams
import org.oppia.android.app.model.OppiaLanguage
import org.oppia.android.app.model.OptionsFragmentArguments
import org.oppia.android.app.model.ProfileId
import org.oppia.android.app.model.ReadingTextSize
import org.oppia.android.app.model.ReadingTextSizeActivityParams
Expand Down Expand Up @@ -99,6 +102,7 @@ import org.oppia.android.testing.time.FakeOppiaClockModule
import org.oppia.android.util.accessibility.AccessibilityTestModule
import org.oppia.android.util.caching.AssetModule
import org.oppia.android.util.caching.testing.CachingTestModule
import org.oppia.android.util.extensions.getProto
import org.oppia.android.util.gcsresource.GcsResourceModule
import org.oppia.android.util.locale.LocaleProdModule
import org.oppia.android.util.logging.LoggerModule
Expand Down Expand Up @@ -559,6 +563,39 @@ class OptionsFragmentTest {
}
}

@Test
fun testFragment_argumentsAreCorrect() {
launch<OptionsActivity>(
createOptionActivityIntent(
internalProfileId = 0,
isFromNavigationDrawer = true
)
).use { scenario ->
testCoroutineDispatchers.runCurrent()
scenario.onActivity { activity ->

val optionsFragment = activity.supportFragmentManager
.findFragmentById(R.id.options_fragment_placeholder) as OptionsFragment

val args = optionsFragment.arguments?.getProto(
OPTIONS_FRAGMENT_ARGUMENTS_KEY,
OptionsFragmentArguments.getDefaultInstance()
)

val isMultipane =
activity.findViewById<FrameLayout>(R.id.multipane_options_container) != null

val receivedIsMultipane = args?.isMultipane
val receivedIsFirstOpen = args?.isFirstOpen
val receivedSelectedFragment = checkNotNull(args?.selectedFragment)

assertThat(receivedIsMultipane).isEqualTo(isMultipane)
assertThat(receivedIsFirstOpen).isEqualTo(true)
assertThat(receivedSelectedFragment).isEqualTo(READING_TEXT_SIZE_FRAGMENT)
}
}
}

private fun rotateToLandscape() {
onView(isRoot()).perform(orientationLandscape())
testCoroutineDispatchers.runCurrent()
Expand Down
Loading

0 comments on commit bc8c66a

Please sign in to comment.