Fixes #25545: wait to draw Pocket until after first frame

pull/543/head
MatthewTighe 2 years ago committed by mergify[bot]
parent dcc1c43260
commit d6952cb2aa

@ -87,7 +87,7 @@ object FeatureFlags {
/**
* Enables the Task Continuity enhancements.
*/
val taskContinuityFeature = Config.channel.isDebug
val taskContinuityFeature = Config.channel.isNightlyOrDebug
/**
* Enables the Unified Search feature.

@ -27,6 +27,11 @@ import org.mozilla.fenix.gleanplumb.MessagingState
*/
sealed class AppAction : Action {
data class UpdateInactiveExpanded(val expanded: Boolean) : AppAction()
/**
* Updates whether the first frame of the homescreen has been [drawn].
*/
data class UpdateFirstFrameDrawn(val drawn: Boolean) : AppAction()
data class AddNonFatalCrash(val crash: NativeCodeCrash) : AppAction()
data class RemoveNonFatalCrash(val crash: NativeCodeCrash) : AppAction()
object RemoveAllNonFatalCrashes : AppAction()

@ -28,6 +28,7 @@ import org.mozilla.fenix.gleanplumb.MessagingState
*
* @property inactiveTabsExpanded A flag to know if the Inactive Tabs section of the Tabs Tray
* should be expanded when the tray is opened.
* @property firstFrameDrawn Flag indicating whether the first frame of the homescreen has been drawn.
* @property nonFatalCrashes List of non-fatal crashes that allow the app to continue being used.
* @property collections The list of [TabCollection] to display in the [HomeFragment].
* @property expandedCollections A set containing the ids of the [TabCollection] that are expanded
@ -50,6 +51,7 @@ import org.mozilla.fenix.gleanplumb.MessagingState
*/
data class AppState(
val inactiveTabsExpanded: Boolean = false,
val firstFrameDrawn: Boolean = false,
val nonFatalCrashes: List<NativeCodeCrash> = emptyList(),
val collections: List<TabCollection> = emptyList(),
val expandedCollections: Set<Long> = emptySet(),

@ -26,6 +26,9 @@ internal object AppStoreReducer {
fun reduce(state: AppState, action: AppAction): AppState = when (action) {
is AppAction.UpdateInactiveExpanded ->
state.copy(inactiveTabsExpanded = action.expanded)
is AppAction.UpdateFirstFrameDrawn -> {
state.copy(firstFrameDrawn = action.drawn)
}
is AppAction.AddNonFatalCrash ->
state.copy(nonFatalCrashes = state.nonFatalCrashes + action.crash)
is AppAction.RemoveNonFatalCrash ->

@ -28,6 +28,7 @@ import androidx.constraintlayout.widget.ConstraintSet.TOP
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.core.view.doOnPreDraw
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
@ -385,11 +386,13 @@ class HomeFragment : Fragment() {
displayWallpaperIfEnabled()
binding.root.doOnPreDraw {
requireComponents.appStore.dispatch(AppAction.UpdateFirstFrameDrawn(drawn = true))
}
// DO NOT MOVE ANYTHING BELOW THIS addMarker CALL!
requireComponents.core.engine.profiler?.addMarker(
MarkersFragmentLifecycleCallbacks.MARKER_NAME, profilerStartTime, "HomeFragment.onCreateView",
)
return binding.root
}

@ -49,11 +49,16 @@ class PocketCategoriesViewHolder(
composeView.resources.getDimensionPixelSize(R.dimen.home_item_horizontal_margin)
composeView.setPadding(horizontalPadding, 0, horizontalPadding, 0)
val homeScreenReady = components.appStore
.observeAsComposableState { state -> state.firstFrameDrawn }.value ?: false
val categories = components.appStore
.observeAsComposableState { state -> state.pocketStoriesCategories }.value
val categoriesSelections = components.appStore
.observeAsComposableState { state -> state.pocketStoriesCategoriesSelections }.value
// See the detailed comment in PocketStoriesViewHolder for reasoning behind this change.
if (!homeScreenReady) return
Column {
Spacer(Modifier.height(24.dp))

@ -52,9 +52,22 @@ class PocketStoriesViewHolder(
override fun Content() {
val horizontalPadding = dimensionResource(R.dimen.home_item_horizontal_margin)
val homeScreenReady = components.appStore
.observeAsComposableState { state -> state.firstFrameDrawn }.value ?: false
val stories = components.appStore
.observeAsComposableState { state -> state.pocketStories }.value
/* This was originally done to address this perf issue:
* https://github.com/mozilla-mobile/fenix/issues/25545 for details.
* It was determined that Pocket content was becoming available before the first frame was
* rendered more regularly. Including Pocket in the first render pass significantly
* increases time-to-render in lower-end devices. By waiting until the first frame has
* rendered, the perceived performance should increase since the app becomes active more
* quickly. This was intended as a workaround until the Compose upgrade was completed and a
* more robust solution could be investigated.
*/
if (!homeScreenReady) return
LaunchedEffect(stories) {
// We should report back when a certain story is actually being displayed.
// Cannot do it reliably so for now we'll just mass report everything as being displayed.

@ -2,6 +2,10 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!-- RecyclerViews will focus the first element that is focusable. This prevents views below
the top from being scrolled to unintentionally. -->
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="0dp"/>
android:layout_height="0dp"
android:focusable="true" />

Loading…
Cancel
Save