1
0
Fork 0

For #6313 - On first load, hides engineView until firstContentfulPaint

master
ekager 2020-05-04 23:29:33 -07:00 committed by Emily Kager
parent 495341a945
commit f663129632
9 changed files with 100 additions and 56 deletions

View File

@ -44,12 +44,6 @@ import org.mozilla.fenix.helpers.click
import org.mozilla.fenix.helpers.ext.waitNotNull
class BrowserRobot {
fun verifyBrowserScreen() {
onView(ViewMatchers.withResourceName("browserLayout"))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
}
fun verifyCurrentPrivateSession(context: Context) {
val session = context.components.core.sessionManager.selectedSession
assertTrue("Current session is private", session?.private!!)
@ -84,6 +78,10 @@ class BrowserRobot {
*/
fun verifyPageContent(expectedText: String) {
mDevice.waitNotNull(
Until.findObject(By.res("org.mozilla.fenix.debug:id/engineView")),
waitingTime
)
assertTrue(mDevice.findObject(UiSelector().text(expectedText)).waitForExists(waitingTime))
}
@ -145,7 +143,8 @@ class BrowserRobot {
fun verifyEnhancedTrackingProtectionSwitch() = assertEnhancedTrackingProtectionSwitch()
fun clickEnhancedTrackingProtectionSwitchOffOn() = onView(withResourceName("switch_widget")).click()
fun clickEnhancedTrackingProtectionSwitchOffOn() =
onView(withResourceName("switch_widget")).click()
fun verifyProtectionSettingsButton() = assertProtectionSettingsButton()
@ -191,7 +190,8 @@ class BrowserRobot {
fun clickEnhancedTrackingProtectionPanel() = enhancedTrackingProtectionPanel().click()
fun verifyEnhancedTrackingProtectionPanelNotVisible() = assertEnhancedTrackingProtectionPanelNotVisible()
fun verifyEnhancedTrackingProtectionPanelNotVisible() =
assertEnhancedTrackingProtectionPanelNotVisible()
fun clickContextOpenLinkInNewTab() {
val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@ -423,7 +423,8 @@ fun navURLBar() = onView(withId(R.id.mozac_browser_toolbar_url_view))
private fun assertNavURLBar() = navURLBar()
.check(matches(withEffectiveVisibility(Visibility.VISIBLE)))
fun enhancedTrackingProtectionPanel() = onView(withId(R.id.mozac_browser_toolbar_tracking_protection_indicator))
fun enhancedTrackingProtectionPanel() =
onView(withId(R.id.mozac_browser_toolbar_tracking_protection_indicator))
private fun assertEnhancedTrackingProtectionPanelNotVisible() {
enhancedTrackingProtectionPanel()

View File

@ -43,4 +43,9 @@ object FeatureFlags {
* Enables the new search experience
*/
val newSearchExperience = Config.channel.isDebug
/**
* Enables wait til first contentful paint
*/
val waitUntilPaintToDraw = Config.channel.isDebug
}

View File

@ -144,9 +144,11 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
private val fullScreenFeature = ViewBoundFeatureWrapper<FullScreenFeature>()
private val swipeRefreshFeature = ViewBoundFeatureWrapper<SwipeRefreshFeature>()
private val webchannelIntegration = ViewBoundFeatureWrapper<FxaWebChannelFeature>()
private val sitePermissionWifiIntegration = ViewBoundFeatureWrapper<SitePermissionsWifiIntegration>()
private val sitePermissionWifiIntegration =
ViewBoundFeatureWrapper<SitePermissionsWifiIntegration>()
private val secureWindowFeature = ViewBoundFeatureWrapper<SecureWindowFeature>()
private var fullScreenMediaFeature = ViewBoundFeatureWrapper<MediaFullscreenOrientationFeature>()
private var fullScreenMediaFeature =
ViewBoundFeatureWrapper<MediaFullscreenOrientationFeature>()
private var pipFeature: PictureInPictureFeature? = null
var customTabSessionId: String? = null
@ -202,7 +204,8 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
engineView = WeakReference(engineView),
swipeRefresh = WeakReference(swipeRefresh),
viewLifecycleScope = WeakReference(viewLifecycleOwner.lifecycleScope),
arguments = requireArguments()
arguments = requireArguments(),
firstContentfulHappened = ::didFirstContentfulHappen
).apply {
beginAnimateInIfNecessary()
}
@ -412,8 +415,10 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
}
}
resumeDownloadDialogState(sessionManager.selectedSession?.id,
store, view, context, toolbarHeight)
resumeDownloadDialogState(
sessionManager.selectedSession?.id,
store, view, context, toolbarHeight
)
downloadsFeature.set(
downloadFeature,
@ -506,7 +511,11 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
onNeedToRequestPermissions = { permissions ->
requestPermissions(permissions, REQUEST_CODE_APP_PERMISSIONS)
},
onShouldShowRequestPermissionRationale = { shouldShowRequestPermissionRationale(it) }),
onShouldShowRequestPermissionRationale = {
shouldShowRequestPermissionRationale(
it
)
}),
owner = this,
view = view
)
@ -568,6 +577,21 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
.collect { tab -> pipModeChanged(tab) }
}
if (context.settings().waitToShowPageUntilFirstPaint) {
store.flowScoped(viewLifecycleOwner) { flow ->
flow.mapNotNull { state ->
state.findTabOrCustomTabOrSelectedTab(
customTabSessionId
)
}
.ifChanged { it.content.firstContentfulPaint }
.collect {
engineView?.asView()?.isVisible =
it.content.firstContentfulPaint || it.content.progress == 100
}
}
}
@Suppress("ConstantConditionIf")
if (FeatureFlags.pullToRefreshEnabled) {
val primaryTextColor =
@ -687,7 +711,12 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
val context = requireContext()
val behavior = when (context.settings().toolbarPosition) {
ToolbarPosition.BOTTOM -> EngineViewBottomBehavior(context, null)
ToolbarPosition.TOP -> SwipeRefreshScrollingViewBehavior(context, null, engineView, browserToolbarView)
ToolbarPosition.TOP -> SwipeRefreshScrollingViewBehavior(
context,
null,
engineView,
browserToolbarView
)
}
(swipeRefresh.layoutParams as CoordinatorLayout.LayoutParams).behavior = behavior
@ -751,12 +780,13 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
super.onStop()
initUIJob?.cancel()
requireComponents.core.store.state.findTabOrCustomTabOrSelectedTab(customTabSessionId)?.let { session ->
// If we didn't enter PiP, exit full screen on stop
if (!session.content.pictureInPictureEnabled && fullScreenFeature.onBackPressed()) {
fullScreenChanged(false)
requireComponents.core.store.state.findTabOrCustomTabOrSelectedTab(customTabSessionId)
?.let { session ->
// If we didn't enter PiP, exit full screen on stop
if (!session.content.pictureInPictureEnabled && fullScreenFeature.onBackPressed()) {
fullScreenChanged(false)
}
}
}
}
@CallSuper
@ -950,7 +980,10 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
.setAction(getString(R.string.edit_bookmark_snackbar_action)) {
nav(
R.id.browserFragment,
BrowserFragmentDirections.actionGlobalBookmarkEditFragment(guid, true)
BrowserFragmentDirections.actionGlobalBookmarkEditFragment(
guid,
true
)
)
}
.show()
@ -988,10 +1021,10 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
// Close find in page bar if opened
findInPageIntegration.onBackPressed()
FenixSnackbar.make(
view = requireView().browserLayout,
duration = Snackbar.LENGTH_SHORT,
isDisplayedWithBrowserToolbar = false
)
view = requireView().browserLayout,
duration = Snackbar.LENGTH_SHORT,
isDisplayedWithBrowserToolbar = false
)
.setText(getString(R.string.full_screen_notification))
.show()
activity?.enterToImmersiveMode()
@ -1014,6 +1047,12 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
}
}
private fun didFirstContentfulHappen() =
if (!requireContext().settings().waitToShowPageUntilFirstPaint) true else
context?.components?.core?.store?.state?.findTabOrCustomTabOrSelectedTab(
customTabSessionId
)?.content?.firstContentfulPaint ?: false
/*
* Dereference these views when the fragment view is destroyed to prevent memory leaks
*/

View File

@ -34,7 +34,8 @@ class BrowserAnimator(
private val engineView: WeakReference<EngineView>,
private val swipeRefresh: WeakReference<View>,
private val viewLifecycleScope: WeakReference<LifecycleCoroutineScope>,
private val arguments: Bundle
private val arguments: Bundle,
private val firstContentfulHappened: () -> Boolean
) {
private val unwrappedEngineView: EngineView?
@ -53,22 +54,9 @@ class BrowserAnimator(
}
doOnEnd {
unwrappedEngineView?.asView()?.visibility = View.VISIBLE
unwrappedSwipeRefresh?.background = null
arguments.putBoolean(SHOULD_ANIMATE_FLAG, false)
}
interpolator = DecelerateInterpolator()
duration = ANIMATION_DURATION
}
private val browserFadeInValueAnimator = ValueAnimator.ofFloat(0f, END_ANIMATOR_VALUE).apply {
addUpdateListener {
unwrappedSwipeRefresh?.alpha = it.animatedFraction
}
doOnEnd {
unwrappedEngineView?.asView()?.visibility = View.VISIBLE
if (firstContentfulHappened()) {
unwrappedEngineView?.asView()?.visibility = View.VISIBLE
}
unwrappedSwipeRefresh?.background = null
arguments.putBoolean(SHOULD_ANIMATE_FLAG, false)
}
@ -93,20 +81,10 @@ class BrowserAnimator(
}
} else {
unwrappedSwipeRefresh?.alpha = 1f
unwrappedEngineView?.asView()?.visibility = View.VISIBLE
unwrappedSwipeRefresh?.background = null
}
}
/**
* Triggers the *zoom out* browser animation to run.
*/
fun beginAnimateOut() {
viewLifecycleScope.get()?.launch(Dispatchers.Main) {
captureEngineViewAndDrawStatically {
unwrappedEngineView?.asView()?.visibility = View.GONE
browserZoomInValueAnimator.reverse()
if (firstContentfulHappened()) {
unwrappedEngineView?.asView()?.visibility = View.VISIBLE
}
unwrappedSwipeRefresh?.background = null
}
}

View File

@ -30,5 +30,11 @@ class SecretSettingsFragment : PreferenceFragmentCompat() {
isChecked = context.settings().useNewSearchExperience
onPreferenceChangeListener = SharedPreferenceUpdater()
}
requirePreference<SwitchPreference>(R.string.pref_key_wait_first_paint).apply {
isVisible = FeatureFlags.waitUntilPaintToDraw
isChecked = context.settings().waitToShowPageUntilFirstPaint
onPreferenceChangeListener = SharedPreferenceUpdater()
}
}
}

View File

@ -103,6 +103,12 @@ class Settings(private val appContext: Context) : PreferencesHolder {
featureFlag = FeatureFlags.newSearchExperience
)
var waitToShowPageUntilFirstPaint by featureFlagPreference(
appContext.getPreferenceKey(R.string.pref_key_wait_first_paint),
default = false,
featureFlag = FeatureFlags.waitUntilPaintToDraw
)
var forceEnableZoom by booleanPreference(
appContext.getPreferenceKey(R.string.pref_key_accessibility_force_enable_zoom),
default = false

View File

@ -175,6 +175,8 @@
<string name="pref_key_use_new_search_experience" translatable="false">pref_key_use_new_search_experience</string>
<string name="pref_key_wait_first_paint" translatable="false">pref_key_wait_first_paint</string>
<string name="pref_key_debug_settings" translatable="false">pref_key_debug_settings</string>
<string name="pref_key_open_tabs_count" translatable="false">pref_key_open_tabs_count</string>

View File

@ -34,6 +34,8 @@
<string name="preferences_debug_settings">Secret Settings</string>
<!-- Label for the new search experience preference -->
<string name="preferences_debug_settings_use_new_search_experience">Use New Search Experience</string>
<!-- Label for the wait until first paint preference -->
<string name="preferences_debug_settings_wait_first_paint">Wait Until First Paint To Show Page Content</string>
<!-- Content description (not visible, for screen readers etc.) used to announce [LinkTextView]. -->
<string name="link_text_view_type_announcement" translatable="false">link</string>

View File

@ -9,4 +9,9 @@
android:key="@string/pref_key_use_new_search_experience"
android:title="@string/preferences_debug_settings_use_new_search_experience"
app:iconSpaceReserved="false" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/pref_key_wait_first_paint"
android:title="@string/preferences_debug_settings_wait_first_paint"
app:iconSpaceReserved="false" />
</PreferenceScreen>