2
0
mirror of https://github.com/fork-maintainers/iceraven-browser synced 2024-11-19 09:25:34 +00:00

[fenix] For https://github.com/mozilla-mobile/fenix/issues/17917 - Migrate browser from Kotlin synthetics to View Binding.

This commit is contained in:
Mugurell 2021-08-17 10:44:37 +03:00 committed by mergify[bot]
parent c0d03b3d1e
commit b38f717c4b
8 changed files with 81 additions and 84 deletions

View File

@ -30,8 +30,6 @@ import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.fragment_browser.*
import kotlinx.android.synthetic.main.fragment_browser.view.*
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -134,6 +132,7 @@ import mozilla.components.support.ktx.android.view.enterToImmersiveMode
import mozilla.components.support.ktx.kotlin.getOrigin
import org.mozilla.fenix.components.toolbar.interactor.BrowserToolbarInteractor
import org.mozilla.fenix.components.toolbar.interactor.DefaultBrowserToolbarInteractor
import org.mozilla.fenix.databinding.FragmentBrowserBinding
import org.mozilla.fenix.ext.secure
import org.mozilla.fenix.settings.biometric.BiometricPromptFeature
import mozilla.components.feature.session.behavior.ToolbarPosition as MozacToolbarPosition
@ -152,6 +151,9 @@ abstract class BaseBrowserFragment :
OnBackLongPressedListener,
AccessibilityManager.AccessibilityStateChangeListener {
private var _binding: FragmentBrowserBinding? = null
protected val binding get() = _binding!!
private lateinit var browserFragmentStore: BrowserFragmentStore
private lateinit var browserAnimator: BrowserAnimator
@ -221,7 +223,7 @@ abstract class BaseBrowserFragment :
)
)
val view = inflater.inflate(R.layout.fragment_browser, container, false)
_binding = FragmentBrowserBinding.inflate(inflater, container, false)
val activity = activity as HomeActivity
activity.themeManager.applyStatusBarTheme(activity)
@ -232,7 +234,7 @@ abstract class BaseBrowserFragment :
)
}
return view
return binding.root
}
final override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -277,8 +279,8 @@ abstract class BaseBrowserFragment :
browserAnimator = BrowserAnimator(
fragment = WeakReference(this),
engineView = WeakReference(engineView),
swipeRefresh = WeakReference(swipeRefresh),
engineView = WeakReference(binding.engineView),
swipeRefresh = WeakReference(binding.swipeRefresh),
viewLifecycleScope = WeakReference(viewLifecycleOwner.lifecycleScope)
).apply {
beginAnimateInIfNecessary()
@ -291,7 +293,7 @@ abstract class BaseBrowserFragment :
val readerMenuController = DefaultReaderModeController(
readerViewFeature,
view.readerViewControlsBar,
binding.readerViewControlsBar,
isPrivate = activity.browsingModeManager.mode.isPrivate,
onReaderModeChanged = { activity.finishActionMode() }
)
@ -302,7 +304,7 @@ abstract class BaseBrowserFragment :
navController = findNavController(),
metrics = requireComponents.analytics.metrics,
readerModeController = readerMenuController,
engineView = engineView,
engineView = binding.engineView,
homeViewModel = homeViewModel,
customTabSessionId = customTabSessionId,
onTabCounterClicked = {
@ -322,7 +324,7 @@ abstract class BaseBrowserFragment :
}
viewLifecycleOwner.lifecycleScope.allowUndo(
requireView().browserLayout,
binding.browserLayout,
snackbarMessage,
requireContext().getString(R.string.snackbar_deleted_undo),
{
@ -342,7 +344,7 @@ abstract class BaseBrowserFragment :
readerModeController = readerMenuController,
sessionFeature = sessionFeature,
findInPageLauncher = { findInPageIntegration.withFeature { it.launch() } },
swipeRefresh = swipeRefresh,
swipeRefresh = binding.swipeRefresh,
browserAnimator = browserAnimator,
customTabSessionId = customTabSessionId,
openInFenixIntent = openInFenixIntent,
@ -363,7 +365,7 @@ abstract class BaseBrowserFragment :
)
_browserToolbarView = BrowserToolbarView(
container = view.browserLayout,
container = binding.browserLayout,
toolbarPosition = context.settings().toolbarPosition,
interactor = browserToolbarInteractor,
customTabSession = customTabSessionId?.let { store.state.findCustomTab(it) },
@ -380,8 +382,8 @@ abstract class BaseBrowserFragment :
feature = FindInPageIntegration(
store = store,
sessionId = customTabSessionId,
stub = view.stubFindInPage,
engineView = engineView,
stub = binding.stubFindInPage,
engineView = binding.engineView,
toolbarInfo = FindInPageIntegration.ToolbarInfo(
browserToolbarView.view,
!context.settings().shouldUseFixedTopToolbar && context.settings().isDynamicToolbarEnabled,
@ -400,8 +402,8 @@ abstract class BaseBrowserFragment :
feature = ContextMenuFeature(
fragmentManager = parentFragmentManager,
store = store,
candidates = getContextMenuCandidates(context, view.browserLayout),
engineView = view.engineView,
candidates = getContextMenuCandidates(context, binding.browserLayout),
engineView = binding.engineView,
useCases = context.components.useCases.contextMenuUseCases,
tabId = customTabSessionId
),
@ -483,15 +485,15 @@ abstract class BaseBrowserFragment :
)
val dynamicDownloadDialog = DynamicDownloadDialog(
container = view.browserLayout,
container = binding.browserLayout,
downloadState = downloadState,
metrics = requireComponents.analytics.metrics,
didFail = downloadJobStatus == DownloadState.Status.FAILED,
tryAgain = downloadFeature::tryAgain,
onCannotOpenFile = {
showCannotOpenFileError(view.browserLayout, context, it)
showCannotOpenFileError(binding.browserLayout, context, it)
},
view = view.viewDynamicDownloadDialog,
view = binding.viewDynamicDownloadDialog.root,
toolbarHeight = toolbarHeight,
onDismiss = { sharedViewModel.downloadDialogState.remove(downloadState.sessionId) }
)
@ -503,7 +505,7 @@ abstract class BaseBrowserFragment :
resumeDownloadDialogState(
getCurrentTab()?.id,
store, view, context, toolbarHeight
store, context, toolbarHeight
)
shareDownloadsFeature.set(
@ -587,7 +589,7 @@ abstract class BaseBrowserFragment :
onNeedToRequestPermissions = { permissions ->
requestPermissions(permissions, REQUEST_CODE_PROMPT_PERMISSIONS)
},
loginPickerView = loginSelectBar,
loginPickerView = binding.loginSelectBar,
onManageLogins = {
browserAnimator.captureEngineViewAndDrawStatically {
val directions =
@ -595,7 +597,7 @@ abstract class BaseBrowserFragment :
findNavController().navigate(directions)
}
},
creditCardPickerView = creditCardSelectBar,
creditCardPickerView = binding.creditCardSelectBar,
onManageCreditCards = {
val directions =
NavGraphDirections.actionGlobalCreditCardsSettingFragment()
@ -613,7 +615,7 @@ abstract class BaseBrowserFragment :
feature = SessionFeature(
requireComponents.core.store,
requireComponents.useCases.sessionUseCases.goBack,
view.engineView,
binding.engineView,
customTabSessionId
),
owner = this,
@ -719,17 +721,17 @@ abstract class BaseBrowserFragment :
.collect { tab -> pipModeChanged(tab) }
}
view.swipeRefresh.isEnabled = shouldPullToRefreshBeEnabled(false)
binding.swipeRefresh.isEnabled = shouldPullToRefreshBeEnabled(false)
if (view.swipeRefresh.isEnabled) {
if (binding.swipeRefresh.isEnabled) {
val primaryTextColor =
ThemeManager.resolveAttribute(R.attr.primaryText, context)
view.swipeRefresh.setColorSchemeColors(primaryTextColor)
binding.swipeRefresh.setColorSchemeColors(primaryTextColor)
swipeRefreshFeature.set(
feature = SwipeRefreshFeature(
requireComponents.core.store,
context.components.useCases.sessionUseCases.reload,
view.swipeRefresh,
binding.swipeRefresh,
customTabSessionId
),
owner = this,
@ -859,7 +861,6 @@ abstract class BaseBrowserFragment :
internal fun resumeDownloadDialogState(
sessionId: String?,
store: BrowserStore,
view: View,
context: Context,
toolbarHeight: Int
) {
@ -867,7 +868,7 @@ abstract class BaseBrowserFragment :
sharedViewModel.downloadDialogState[sessionId]
if (savedDownloadState == null || sessionId == null) {
view.viewDynamicDownloadDialog.visibility = View.GONE
binding.viewDynamicDownloadDialog.root.visibility = View.GONE
return
}
@ -885,15 +886,15 @@ abstract class BaseBrowserFragment :
{ sharedViewModel.downloadDialogState.remove(sessionId) }
DynamicDownloadDialog(
container = view.browserLayout,
container = binding.browserLayout,
downloadState = savedDownloadState.first,
metrics = requireComponents.analytics.metrics,
didFail = savedDownloadState.second,
tryAgain = onTryAgain,
onCannotOpenFile = {
showCannotOpenFileError(view.browserLayout, context, it)
showCannotOpenFileError(binding.browserLayout, context, it)
},
view = view.viewDynamicDownloadDialog,
view = binding.viewDynamicDownloadDialog.root,
toolbarHeight = toolbarHeight,
onDismiss = onDismiss
).show()
@ -1012,13 +1013,13 @@ abstract class BaseBrowserFragment :
}
if (browserInitialized) {
view?.let { view ->
view?.let {
fullScreenChanged(false)
browserToolbarView.expand()
val toolbarHeight = resources.getDimensionPixelSize(R.dimen.browser_toolbar_height)
val context = requireContext()
resumeDownloadDialogState(selectedTab.id, context.components.core.store, view, context, toolbarHeight)
resumeDownloadDialogState(selectedTab.id, context.components.core.store, context, toolbarHeight)
}
} else {
view?.let { view -> initializeUI(view) }
@ -1158,7 +1159,7 @@ abstract class BaseBrowserFragment :
)
/**
* Returns the layout [android.view.Gravity] for the quick settings and ETP dialog.
* Returns the layout [android.binding.Gravity] for the quick settings and ETP dialog.
*/
protected fun getAppropriateLayoutGravity(): Int =
requireComponents.settings.toolbarPosition.androidGravity
@ -1230,9 +1231,9 @@ abstract class BaseBrowserFragment :
withContext(Main) {
requireComponents.analytics.metrics.track(Event.AddBookmark)
view?.let { view ->
view?.let {
FenixSnackbar.make(
view = view.browserLayout,
view = binding.browserLayout,
duration = FenixSnackbar.LENGTH_LONG,
isDisplayedWithBrowserToolbar = true
)
@ -1283,7 +1284,7 @@ abstract class BaseBrowserFragment :
// Close find in page bar if opened
findInPageIntegration.onBackPressed()
FenixSnackbar.make(
view = requireView().browserLayout,
view = binding.browserLayout,
duration = Snackbar.LENGTH_SHORT,
isDisplayedWithBrowserToolbar = false
)
@ -1292,14 +1293,14 @@ abstract class BaseBrowserFragment :
activity?.enterToImmersiveMode()
browserToolbarView.collapse()
browserToolbarView.view.isVisible = false
val browserEngine = swipeRefresh.layoutParams as CoordinatorLayout.LayoutParams
val browserEngine = binding.swipeRefresh.layoutParams as CoordinatorLayout.LayoutParams
browserEngine.bottomMargin = 0
browserEngine.topMargin = 0
swipeRefresh.translationY = 0f
binding.swipeRefresh.translationY = 0f
engineView.setDynamicToolbarMaxHeight(0)
binding.engineView.setDynamicToolbarMaxHeight(0)
// Without this, fullscreen has a margin at the top.
engineView.setVerticalClipping(0)
binding.engineView.setVerticalClipping(0)
requireComponents.analytics.metrics.track(Event.MediaFullscreenState)
} else {
@ -1315,7 +1316,7 @@ abstract class BaseBrowserFragment :
}
}
activity?.swipeRefresh?.isEnabled = shouldPullToRefreshBeEnabled(inFullScreen)
binding.swipeRefresh.isEnabled = shouldPullToRefreshBeEnabled(inFullScreen)
}
/*
@ -1333,6 +1334,7 @@ abstract class BaseBrowserFragment :
requireContext().accessibilityManager.removeAccessibilityStateChangeListener(this)
_browserToolbarView = null
_browserToolbarInteractor = null
_binding = null
}
override fun onAttach(context: Context) {
@ -1409,13 +1411,13 @@ abstract class BaseBrowserFragment :
* Convenience method for replacing EngineView (id/engineView) in unit tests.
*/
@VisibleForTesting
internal fun getEngineView() = engineView
internal fun getEngineView() = binding.engineView
/**
* Convenience method for replacing SwipeRefreshLayout (id/swipeRefresh) in unit tests.
*/
@VisibleForTesting
internal fun getSwipeRefreshLayout() = swipeRefresh
internal fun getSwipeRefreshLayout() = binding.swipeRefresh
@VisibleForTesting
internal fun shouldShowCompletedDownloadDialog(

View File

@ -13,8 +13,6 @@ import androidx.appcompat.content.res.AppCompatResources
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.fragment_browser.*
import kotlinx.android.synthetic.main.fragment_browser.view.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import mozilla.components.browser.state.selector.findTab
import mozilla.components.browser.state.state.SessionState
@ -64,11 +62,11 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
val components = context.components
if (context.settings().isSwipeToolbarToSwitchTabsEnabled) {
gestureLayout.addGestureListener(
binding.gestureLayout.addGestureListener(
ToolbarGestureHandler(
activity = requireActivity(),
contentLayout = browserLayout,
tabPreview = tabPreview,
contentLayout = binding.browserLayout,
tabPreview = binding.tabPreview,
toolbarLayout = browserToolbarView.view,
store = components.core.store,
selectTabUseCase = components.useCases.tabsUseCases.selectTab
@ -196,7 +194,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
browserToolbarView.view.addPageAction(readerModeAction)
thumbnailsFeature.set(
feature = BrowserThumbnails(context, view.engineView, components.core.store),
feature = BrowserThumbnails(context, binding.engineView, components.core.store),
owner = this,
view = view
)
@ -207,7 +205,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
context,
components.core.engine,
components.core.store,
view.readerViewControlsBar
binding.readerViewControlsBar
) { available, active ->
if (available) {
components.analytics.metrics.track(Event.ReaderModeAvailable)
@ -240,7 +238,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
navController = findNavController(),
settings = context.settings(),
appLinksUseCases = context.components.useCases.appLinksUseCases,
container = browserLayout as ViewGroup,
container = binding.browserLayout as ViewGroup,
shouldScrollWithTopToolbar = !context.settings().shouldUseBottomToolbar
),
owner = this,
@ -353,7 +351,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
}
}
FenixSnackbar.make(
view = view.browserLayout,
view = binding.browserLayout,
duration = Snackbar.LENGTH_SHORT,
isDisplayedWithBrowserToolbar = true
)

View File

@ -13,11 +13,10 @@ import android.widget.FrameLayout
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.view.doOnNextLayout
import androidx.core.view.updateLayoutParams
import kotlinx.android.synthetic.main.tab_preview.view.*
import kotlinx.android.synthetic.main.tabs_tray_tab_counter.view.*
import mozilla.components.browser.thumbnails.loader.ThumbnailLoader
import mozilla.components.concept.base.images.ImageLoadRequest
import org.mozilla.fenix.R
import org.mozilla.fenix.databinding.TabPreviewBinding
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.theme.ThemeManager
@ -29,32 +28,30 @@ class TabPreview @JvmOverloads constructor(
defStyle: Int = 0
) : FrameLayout(context, attrs, defStyle) {
private val binding = TabPreviewBinding.inflate(LayoutInflater.from(context), this)
private val thumbnailLoader = ThumbnailLoader(context.components.core.thumbnailStorage)
init {
val inflater = LayoutInflater.from(context)
inflater.inflate(R.layout.tab_preview, this, true)
if (!context.settings().shouldUseBottomToolbar) {
fakeToolbar.updateLayoutParams<LayoutParams> {
binding.fakeToolbar.updateLayoutParams<LayoutParams> {
gravity = Gravity.TOP
}
fakeToolbar.background = AppCompatResources.getDrawable(
binding.fakeToolbar.background = AppCompatResources.getDrawable(
context,
ThemeManager.resolveAttribute(R.attr.bottomBarBackgroundTop, context)
)
}
// Change view properties to avoid confusing the UI tests
tab_button.counter_box.id = View.NO_ID
tab_button.counter_text.id = View.NO_ID
binding.tabButton.findViewById<View>(R.id.counter_box).id = View.NO_ID
binding.tabButton.findViewById<View>(R.id.counter_text).id = View.NO_ID
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
previewThumbnail.translationY = if (!context.settings().shouldUseBottomToolbar) {
fakeToolbar.height.toFloat()
binding.previewThumbnail.translationY = if (!context.settings().shouldUseBottomToolbar) {
binding.fakeToolbar.height.toFloat()
} else {
0f
}
@ -62,6 +59,7 @@ class TabPreview @JvmOverloads constructor(
fun loadPreviewThumbnail(thumbnailId: String) {
doOnNextLayout {
val previewThumbnail = binding.previewThumbnail
val thumbnailSize = max(previewThumbnail.height, previewThumbnail.width)
thumbnailLoader.loadIntoView(
previewThumbnail,

View File

@ -34,7 +34,7 @@ class DynamicInfoBanner(
super.showBanner()
if (shouldScrollWithTopToolbar) {
(bannerLayout.layoutParams as CoordinatorLayout.LayoutParams).behavior = DynamicInfoBannerBehavior(
(binding.root.layoutParams as CoordinatorLayout.LayoutParams).behavior = DynamicInfoBannerBehavior(
context, null
)
}

View File

@ -10,8 +10,7 @@ import android.view.LayoutInflater
import android.view.View.GONE
import android.view.ViewGroup
import androidx.annotation.VisibleForTesting
import kotlinx.android.synthetic.main.info_banner.view.*
import org.mozilla.fenix.R
import org.mozilla.fenix.databinding.InfoBannerBinding
import org.mozilla.fenix.ext.settings
/**
@ -40,27 +39,26 @@ open class InfoBanner(
) {
@SuppressLint("InflateParams")
@VisibleForTesting
internal val bannerLayout = LayoutInflater.from(context)
.inflate(R.layout.info_banner, null)
internal val binding = InfoBannerBinding.inflate(LayoutInflater.from(context), container, false)
internal open fun showBanner() {
bannerLayout.banner_info_message.text = message
bannerLayout.dismiss.text = dismissText
binding.bannerInfoMessage.text = message
binding.dismiss.text = dismissText
if (actionText.isNullOrEmpty()) {
bannerLayout.action.visibility = GONE
binding.action.visibility = GONE
} else {
bannerLayout.action.text = actionText
binding.action.text = actionText
}
container.addView(bannerLayout)
container.addView(binding.root)
bannerLayout.dismiss.setOnClickListener {
binding.dismiss.setOnClickListener {
dismissAction?.invoke()
if (dismissByHiding) { bannerLayout.visibility = GONE } else { dismiss() }
if (dismissByHiding) { binding.root.visibility = GONE } else { dismiss() }
}
bannerLayout.action.setOnClickListener {
binding.action.setOnClickListener {
actionToPerform?.invoke()
}
@ -68,6 +66,6 @@ open class InfoBanner(
}
internal fun dismiss() {
container.removeView(bannerLayout)
container.removeView(binding.root)
}
}

View File

@ -90,7 +90,7 @@ class BrowserFragmentTest {
every { browserFragment.requireContext() } returns context
every { browserFragment.initializeUI(any(), any()) } returns mockk()
every { browserFragment.fullScreenChanged(any()) } returns Unit
every { browserFragment.resumeDownloadDialogState(any(), any(), any(), any(), any()) } returns Unit
every { browserFragment.resumeDownloadDialogState(any(), any(), any(), any()) } returns Unit
testTab = createTab(url = "https://mozilla.org")
store = BrowserStore()
@ -160,7 +160,7 @@ class BrowserFragmentTest {
val newSelectedTab = createTab("https://firefox.com")
addAndSelectTab(newSelectedTab)
verify(exactly = 1) {
browserFragment.resumeDownloadDialogState(newSelectedTab.id, store, view, context, any())
browserFragment.resumeDownloadDialogState(newSelectedTab.id, store, context, any())
}
}

View File

@ -6,6 +6,7 @@ package org.mozilla.fenix.browser
import android.content.Context
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
@ -172,7 +173,7 @@ class OpenInAppOnboardingObserverTest {
openInAppOnboardingObserver = spyk(
OpenInAppOnboardingObserver(
testContext, mockk(), mockk(), mockk(), mockk(), mockk(), mockk(), shouldScrollWithTopToolbar = true
testContext, mockk(), mockk(), mockk(), mockk(), mockk(), FrameLayout(testContext), shouldScrollWithTopToolbar = true
)
)
val banner1 = openInAppOnboardingObserver.createInfoBanner()
@ -180,7 +181,7 @@ class OpenInAppOnboardingObserverTest {
openInAppOnboardingObserver = spyk(
OpenInAppOnboardingObserver(
testContext, mockk(), mockk(), mockk(), mockk(), mockk(), mockk(), shouldScrollWithTopToolbar = false
testContext, mockk(), mockk(), mockk(), mockk(), mockk(), FrameLayout(testContext), shouldScrollWithTopToolbar = false
)
)
val banner2 = openInAppOnboardingObserver.createInfoBanner()

View File

@ -25,7 +25,7 @@ class DynamicInfoBannerTest {
banner.showBanner()
assertTrue((banner.bannerLayout.layoutParams as CoordinatorLayout.LayoutParams).behavior is DynamicInfoBannerBehavior)
assertTrue((banner.binding.root.layoutParams as CoordinatorLayout.LayoutParams).behavior is DynamicInfoBannerBehavior)
}
@Test
@ -38,6 +38,6 @@ class DynamicInfoBannerTest {
banner.showBanner()
assertNull((banner.bannerLayout.layoutParams as CoordinatorLayout.LayoutParams).behavior)
assertNull((banner.binding.root.layoutParams as CoordinatorLayout.LayoutParams).behavior)
}
}