diff --git a/app/src/androidTest/java/org/mozilla/fenix/perf/StartupExcessiveResourceUseTest.kt b/app/src/androidTest/java/org/mozilla/fenix/perf/StartupExcessiveResourceUseTest.kt index 4e32f0de4..5cc9f0e81 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/perf/StartupExcessiveResourceUseTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/perf/StartupExcessiveResourceUseTest.kt @@ -7,16 +7,17 @@ package org.mozilla.fenix.perf import android.util.Log import android.view.View import android.view.ViewGroup +import android.widget.LinearLayout import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.view.children import androidx.recyclerview.widget.RecyclerView import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.UiDevice -import kotlinx.android.synthetic.main.activity_home.* import org.junit.Assert.assertEquals import org.junit.Ignore import org.junit.Rule import org.junit.Test +import org.mozilla.fenix.R import org.mozilla.fenix.ext.components import org.mozilla.fenix.helpers.HomeActivityTestRule @@ -94,7 +95,7 @@ class StartupExcessiveResourceUseTest { val actualRunBlocking = RunBlockingCounter.count.get() val actualComponentInitCount = ComponentInitCount.count.get() - val rootView = activityTestRule.activity.rootContainer + val rootView = activityTestRule.activity.findViewById(R.id.rootContainer) val actualViewHierarchyDepth = countAndLogViewHierarchyDepth(rootView, 1) val actualRecyclerViewConstraintLayoutChildren = countRecyclerViewConstraintLayoutChildren(rootView, null) diff --git a/app/src/main/java/org/mozilla/fenix/addons/AddonDetailsView.kt b/app/src/main/java/org/mozilla/fenix/addons/AddonDetailsBindingDelegate.kt similarity index 99% rename from app/src/main/java/org/mozilla/fenix/addons/AddonDetailsView.kt rename to app/src/main/java/org/mozilla/fenix/addons/AddonDetailsBindingDelegate.kt index 7a81f3f9f..99bfb4be5 100644 --- a/app/src/main/java/org/mozilla/fenix/addons/AddonDetailsView.kt +++ b/app/src/main/java/org/mozilla/fenix/addons/AddonDetailsBindingDelegate.kt @@ -38,7 +38,7 @@ interface AddonDetailsInteractor { /** * Shows the details of an add-on. */ -class AddonDetailsView( +class AddonDetailsBindingDelegate( private val binding: FragmentAddOnDetailsBinding, private val interactor: AddonDetailsInteractor ) { diff --git a/app/src/main/java/org/mozilla/fenix/addons/AddonDetailsFragment.kt b/app/src/main/java/org/mozilla/fenix/addons/AddonDetailsFragment.kt index 7bc8471a6..8767e27ec 100644 --- a/app/src/main/java/org/mozilla/fenix/addons/AddonDetailsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/addons/AddonDetailsFragment.kt @@ -40,7 +40,7 @@ class AddonDetailsFragment : Fragment(R.layout.fragment_add_on_details), AddonDe } val binding = FragmentAddOnDetailsBinding.bind(view) - AddonDetailsView(binding, interactor = this).bind(args.addon) + AddonDetailsBindingDelegate(binding, interactor = this).bind(args.addon) } override fun openWebsite(addonSiteUrl: Uri) { diff --git a/app/src/main/java/org/mozilla/fenix/addons/WebExtensionActionPopupFragment.kt b/app/src/main/java/org/mozilla/fenix/addons/WebExtensionActionPopupFragment.kt index 2a4d572a1..a55623712 100644 --- a/app/src/main/java/org/mozilla/fenix/addons/WebExtensionActionPopupFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/addons/WebExtensionActionPopupFragment.kt @@ -10,13 +10,13 @@ import android.view.View import android.view.ViewGroup import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs -import kotlinx.android.synthetic.main.fragment_add_on_internal_settings.* import kotlinx.coroutines.ExperimentalCoroutinesApi import mozilla.components.browser.state.action.WebExtensionAction import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineView import mozilla.components.lib.state.ext.consumeFrom import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.FragmentAddOnInternalSettingsBinding import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.showToolbar @@ -57,10 +57,12 @@ class WebExtensionActionPopupFragment : AddonPopupBaseFragment(), EngineSession. override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + val binding = FragmentAddOnInternalSettingsBinding.bind(view) + val session = engineSession // If we have the session, render it otherwise consume it from the store. if (session != null) { - addonSettingsEngineView.render(session) + binding.addonSettingsEngineView.render(session) consumePopupSession() } else { consumeFrom(coreComponents.store) { state -> @@ -68,7 +70,7 @@ class WebExtensionActionPopupFragment : AddonPopupBaseFragment(), EngineSession. val popupSession = extState.popupSession if (popupSession != null) { initializeSession(popupSession) - addonSettingsEngineView.render(popupSession) + binding.addonSettingsEngineView.render(popupSession) popupSession.register(this) consumePopupSession() engineSession = popupSession diff --git a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index 086181c04..0e573f3ac 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -484,7 +484,7 @@ abstract class BaseBrowserFragment : ) val dynamicDownloadDialog = DynamicDownloadDialog( - container = binding.browserLayout, + context = context, downloadState = downloadState, metrics = requireComponents.analytics.metrics, didFail = downloadJobStatus == DownloadState.Status.FAILED, @@ -492,7 +492,7 @@ abstract class BaseBrowserFragment : onCannotOpenFile = { showCannotOpenFileError(binding.browserLayout, context, it) }, - view = binding.viewDynamicDownloadDialog.root, + binding = binding.viewDynamicDownloadDialog, toolbarHeight = toolbarHeight, onDismiss = { sharedViewModel.downloadDialogState.remove(downloadState.sessionId) } ) @@ -885,7 +885,7 @@ abstract class BaseBrowserFragment : { sharedViewModel.downloadDialogState.remove(sessionId) } DynamicDownloadDialog( - container = binding.browserLayout, + context = context, downloadState = savedDownloadState.first, metrics = requireComponents.analytics.metrics, didFail = savedDownloadState.second, @@ -893,7 +893,7 @@ abstract class BaseBrowserFragment : onCannotOpenFile = { showCannotOpenFileError(binding.browserLayout, context, it) }, - view = binding.viewDynamicDownloadDialog.root, + binding = binding.viewDynamicDownloadDialog, toolbarHeight = toolbarHeight, onDismiss = onDismiss ).show() @@ -1158,7 +1158,7 @@ abstract class BaseBrowserFragment : ) /** - * Returns the layout [android.binding.Gravity] for the quick settings and ETP dialog. + * Returns the layout [android.view.Gravity] for the quick settings and ETP dialog. */ protected fun getAppropriateLayoutGravity(): Int = requireComponents.settings.toolbarPosition.androidGravity diff --git a/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationView.kt b/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationView.kt index ffeeb0e78..6645082c5 100644 --- a/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationView.kt +++ b/app/src/main/java/org/mozilla/fenix/collections/CollectionCreationView.kt @@ -9,7 +9,6 @@ import android.os.Looper import android.text.InputFilter import android.view.KeyEvent import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import android.view.inputmethod.EditorInfo import androidx.constraintlayout.widget.ConstraintSet @@ -18,7 +17,6 @@ import androidx.recyclerview.widget.RecyclerView import androidx.transition.AutoTransition import androidx.transition.Transition import androidx.transition.TransitionManager -import kotlinx.android.extensions.LayoutContainer import mozilla.components.feature.tab.collections.TabCollection import mozilla.components.support.ktx.android.view.hideKeyboard import mozilla.components.support.ktx.android.view.showKeyboard @@ -30,16 +28,15 @@ import org.mozilla.fenix.ext.toShortUrl import org.mozilla.fenix.home.Tab class CollectionCreationView( - container: ViewGroup, + private val container: ViewGroup, private val interactor: CollectionCreationInteractor -) : LayoutContainer { +) { private val binding = ComponentCollectionCreationBinding.inflate( LayoutInflater.from(container.context), container, true ) - override val containerView: View = binding.root private val bottomBarView = CollectionCreationBottomBarView( interactor = interactor, @@ -82,12 +79,12 @@ class CollectionCreationView( binding.tabList.run { adapter = collectionCreationTabListAdapter itemAnimator = null - layoutManager = LinearLayoutManager(containerView.context, RecyclerView.VERTICAL, true) + layoutManager = LinearLayoutManager(container.context, RecyclerView.VERTICAL, true) } binding.collectionsList.run { adapter = collectionSaveListAdapter - layoutManager = LinearLayoutManager(containerView.context, RecyclerView.VERTICAL, true) + layoutManager = LinearLayoutManager(container.context, RecyclerView.VERTICAL, true) } } @@ -113,7 +110,7 @@ class CollectionCreationView( } private fun updateForSelectTabs(state: CollectionCreationState) { - containerView.context.components.analytics.metrics.track(Event.CollectionTabSelectOpened) + container.context.components.analytics.metrics.track(Event.CollectionTabSelectOpened) binding.tabList.isClickable = true @@ -136,7 +133,7 @@ class CollectionCreationView( } selectTabsConstraints.clone( - containerView.context, + container.context, R.layout.component_collection_creation ) collectionCreationTabListAdapter.updateData(state.tabs, state.selectedTabs) @@ -146,7 +143,7 @@ class CollectionCreationView( private fun updateForSelectCollection() { binding.tabList.isClickable = false selectCollectionConstraints.clone( - containerView.context, + container.context, R.layout.component_collection_creation_select_collection ) selectCollectionConstraints.applyTo(binding.collectionConstraintLayout) @@ -163,7 +160,7 @@ class CollectionCreationView( private fun updateForNameCollection(state: CollectionCreationState) { binding.tabList.isClickable = false nameCollectionConstraints.clone( - containerView.context, + container.context, R.layout.component_collection_creation_name_collection ) nameCollectionConstraints.applyTo(binding.collectionConstraintLayout) @@ -186,7 +183,7 @@ class CollectionCreationView( binding.nameCollectionEdittext.showKeyboard() binding.nameCollectionEdittext.setText( - containerView.context.getString( + container.context.getString( R.string.create_collection_default_name, state.defaultCollectionNumber ) @@ -198,7 +195,7 @@ class CollectionCreationView( binding.tabList.isClickable = false state.selectedTabCollection?.let { tabCollection -> - val publicSuffixList = containerView.context.components.publicSuffixList + val publicSuffixList = container.context.components.publicSuffixList tabCollection.tabs.map { tab -> Tab( sessionId = tab.id.toString(), @@ -211,7 +208,7 @@ class CollectionCreationView( } } nameCollectionConstraints.clone( - containerView.context, + container.context, R.layout.component_collection_creation_name_collection ) nameCollectionConstraints.applyTo(binding.collectionConstraintLayout) diff --git a/app/src/main/java/org/mozilla/fenix/components/FenixSnackbar.kt b/app/src/main/java/org/mozilla/fenix/components/FenixSnackbar.kt index 2d4948f04..68244c772 100644 --- a/app/src/main/java/org/mozilla/fenix/components/FenixSnackbar.kt +++ b/app/src/main/java/org/mozilla/fenix/components/FenixSnackbar.kt @@ -18,8 +18,8 @@ import androidx.core.widget.TextViewCompat import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.snackbar.ContentViewCallback import com.google.android.material.snackbar.Snackbar -import kotlinx.android.synthetic.main.fenix_snackbar.view.* import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.FenixSnackbarBinding import org.mozilla.fenix.ext.increaseTapArea import org.mozilla.fenix.ext.settings import org.mozilla.fenix.utils.Mockable @@ -27,20 +27,20 @@ import org.mozilla.fenix.utils.Mockable @Mockable class FenixSnackbar private constructor( parent: ViewGroup, - content: View, + private val binding: FenixSnackbarBinding, contentViewCallback: FenixSnackbarCallback, isError: Boolean -) : BaseTransientBottomBar(parent, content, contentViewCallback) { +) : BaseTransientBottomBar(parent, binding.root, contentViewCallback) { init { view.setBackgroundColor(Color.TRANSPARENT) setAppropriateBackground(isError) - content.snackbar_btn.increaseTapArea(actionButtonIncreaseDps) + binding.snackbarBtn.increaseTapArea(actionButtonIncreaseDps) TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration( - content.snackbar_text, + binding.snackbarText, minTextSize, maxTextSize, stepGranularity, @@ -49,7 +49,7 @@ class FenixSnackbar private constructor( } fun setAppropriateBackground(isError: Boolean) { - view.snackbar_layout.background = if (isError) { + binding.snackbarLayout.background = if (isError) { AppCompatResources.getDrawable(context, R.drawable.fenix_snackbar_error_background) } else { AppCompatResources.getDrawable(context, R.drawable.fenix_snackbar_background) @@ -57,7 +57,7 @@ class FenixSnackbar private constructor( } fun setText(text: String) = this.apply { - view.snackbar_text.text = text + binding.snackbarText.text = text } fun setLength(duration: Int) = this.apply { @@ -65,7 +65,7 @@ class FenixSnackbar private constructor( } fun setAction(text: String, action: () -> Unit) = this.apply { - view.snackbar_btn.apply { + binding.snackbarBtn.apply { setText(text) visibility = View.VISIBLE setOnClickListener { @@ -110,7 +110,7 @@ class FenixSnackbar private constructor( } val inflater = LayoutInflater.from(parent.context) - val content = inflater.inflate(R.layout.fenix_snackbar, parent, false) + val binding = FenixSnackbarBinding.inflate(inflater, parent, false) val durationOrAccessibleDuration = if (parent.context.settings().accessibilityServicesEnabled) { @@ -119,12 +119,12 @@ class FenixSnackbar private constructor( duration } - val callback = FenixSnackbarCallback(content) + val callback = FenixSnackbarCallback(binding.root) val shouldUseBottomToolbar = view.context.settings().shouldUseBottomToolbar val toolbarHeight = view.resources.getDimensionPixelSize(R.dimen.browser_toolbar_height) val dynamicToolbarEnabled = view.context.settings().isDynamicToolbarEnabled - return FenixSnackbar(parent, content, callback, isError).also { + return FenixSnackbar(parent, binding, callback, isError).also { it.duration = durationOrAccessibleDuration it.view.updatePadding( diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt index e3f38d074..90ae16ca4 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt @@ -13,7 +13,6 @@ import androidx.annotation.VisibleForTesting import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.content.ContextCompat import androidx.lifecycle.LifecycleOwner -import kotlinx.android.extensions.LayoutContainer import kotlinx.coroutines.ExperimentalCoroutinesApi import mozilla.components.browser.domains.autocomplete.ShippedDomainsProvider import mozilla.components.browser.state.selector.selectedTab @@ -43,10 +42,7 @@ class BrowserToolbarView( private val interactor: BrowserToolbarInteractor, private val customTabSession: CustomTabSessionState?, private val lifecycleOwner: LifecycleOwner -) : LayoutContainer { - - override val containerView: View? - get() = container +) { private val settings = container.context.settings() diff --git a/app/src/main/java/org/mozilla/fenix/crashes/CrashReporterFragment.kt b/app/src/main/java/org/mozilla/fenix/crashes/CrashReporterFragment.kt index 6f74525ea..8adfdd306 100644 --- a/app/src/main/java/org/mozilla/fenix/crashes/CrashReporterFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/crashes/CrashReporterFragment.kt @@ -9,9 +9,9 @@ import android.view.View import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs -import kotlinx.android.synthetic.main.fragment_crash_reporter.* import mozilla.components.lib.crash.Crash import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.FragmentCrashReporterBinding import org.mozilla.fenix.ext.hideToolbar import org.mozilla.fenix.ext.increaseTapArea import org.mozilla.fenix.ext.requireComponents @@ -25,10 +25,12 @@ class CrashReporterFragment : Fragment(R.layout.fragment_crash_reporter) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + val binding = FragmentCrashReporterBinding.bind(view) + val args: CrashReporterFragmentArgs by navArgs() val crash = Crash.fromIntent(args.crashIntent) - title.text = getString(R.string.tab_crash_title_2, getString(R.string.app_name)) + binding.title.text = getString(R.string.tab_crash_title_2, getString(R.string.app_name)) val controller = CrashReporterController( crash, @@ -38,17 +40,17 @@ class CrashReporterFragment : Fragment(R.layout.fragment_crash_reporter) { settings = requireContext().settings() ) - restoreTabButton.apply { + binding.restoreTabButton.apply { increaseTapArea(TAP_INCREASE_DP) setOnClickListener { - controller.handleCloseAndRestore(sendCrashCheckbox.isChecked) + controller.handleCloseAndRestore(binding.sendCrashCheckbox.isChecked) } } - closeTabButton.apply { + binding.closeTabButton.apply { increaseTapArea(TAP_INCREASE_DP) setOnClickListener { - controller.handleCloseAndRemove(sendCrashCheckbox.isChecked) + controller.handleCloseAndRemove(binding.sendCrashCheckbox.isChecked) } } } diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserActivity.kt b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserActivity.kt index a8331af69..0603c0a6c 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserActivity.kt @@ -8,7 +8,6 @@ import android.content.Intent import androidx.annotation.VisibleForTesting import androidx.navigation.NavDestination import androidx.navigation.NavDirections -import kotlinx.android.synthetic.main.activity_home.* import mozilla.components.browser.state.selector.findCustomTab import mozilla.components.browser.state.state.SessionState import mozilla.components.concept.engine.manifest.WebAppManifestParser diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt index 9fc057793..13c13eda3 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt @@ -11,10 +11,9 @@ import android.view.View import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.view.isVisible import androidx.navigation.fragment.navArgs -import kotlinx.android.synthetic.main.component_browser_top_toolbar.* -import kotlinx.android.synthetic.main.fragment_browser.* import kotlinx.coroutines.ExperimentalCoroutinesApi import mozilla.components.browser.state.state.SessionState +import mozilla.components.browser.toolbar.BrowserToolbar import mozilla.components.concept.engine.manifest.WebAppManifestParser import mozilla.components.concept.engine.manifest.getOrNull import mozilla.components.feature.contextmenu.ContextMenuCandidate @@ -58,6 +57,8 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), UserInteractionHandler val customTabSessionId = customTabSessionId ?: return val activity = requireActivity() val components = activity.components + val toolbar = binding.root.findViewById(R.id.toolbar) + val manifest = args.webAppManifest?.let { json -> WebAppManifestParser().parse(json).getOrNull() } customTabsIntegration.set( @@ -105,9 +106,9 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), UserInteractionHandler browserToolbarView.view.isVisible = toolbarVisible webAppToolbarShouldBeVisible = toolbarVisible if (!toolbarVisible) { - engineView.setDynamicToolbarMaxHeight(0) + binding.engineView.setDynamicToolbarMaxHeight(0) val browserEngine = - swipeRefresh.layoutParams as CoordinatorLayout.LayoutParams + binding.swipeRefresh.layoutParams as CoordinatorLayout.LayoutParams browserEngine.bottomMargin = 0 } }, diff --git a/app/src/main/java/org/mozilla/fenix/downloads/DynamicDownloadDialog.kt b/app/src/main/java/org/mozilla/fenix/downloads/DynamicDownloadDialog.kt index df3fd5513..518dd569a 100644 --- a/app/src/main/java/org/mozilla/fenix/downloads/DynamicDownloadDialog.kt +++ b/app/src/main/java/org/mozilla/fenix/downloads/DynamicDownloadDialog.kt @@ -9,14 +9,13 @@ import android.view.View import android.view.ViewGroup import android.webkit.MimeTypeMap import androidx.coordinatorlayout.widget.CoordinatorLayout -import kotlinx.android.extensions.LayoutContainer -import kotlinx.android.synthetic.main.download_dialog_layout.view.* import mozilla.components.browser.state.state.content.DownloadState import mozilla.components.feature.downloads.AbstractFetchDownloadService import mozilla.components.feature.downloads.toMegabyteOrKilobyteString import org.mozilla.fenix.R import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.MetricController +import org.mozilla.fenix.databinding.DownloadDialogLayoutBinding import org.mozilla.fenix.ext.metrics import org.mozilla.fenix.ext.settings @@ -27,29 +26,26 @@ import org.mozilla.fenix.ext.settings */ @Suppress("LongParameterList") class DynamicDownloadDialog( - private val container: ViewGroup, + private val context: Context, private val downloadState: DownloadState?, private val metrics: MetricController, private val didFail: Boolean, private val tryAgain: (String) -> Unit, private val onCannotOpenFile: (DownloadState) -> Unit, - private val view: View, + private val binding: DownloadDialogLayoutBinding, private val toolbarHeight: Int, private val onDismiss: () -> Unit -) : LayoutContainer { +) { - override val containerView: View? - get() = container - - private val settings = container.context.settings() + private val settings = context.settings() init { - setupDownloadDialog(view) + setupDownloadDialog() } - private fun setupDownloadDialog(view: View) { + private fun setupDownloadDialog() { if (downloadState == null) return - view.apply { + binding.root.apply { if (layoutParams is CoordinatorLayout.LayoutParams) { (layoutParams as CoordinatorLayout.LayoutParams).apply { @@ -65,40 +61,40 @@ class DynamicDownloadDialog( if (settings.shouldUseBottomToolbar) { val params: ViewGroup.MarginLayoutParams = - view.layoutParams as ViewGroup.MarginLayoutParams + binding.root.layoutParams as ViewGroup.MarginLayoutParams params.bottomMargin = toolbarHeight } if (didFail) { - view.download_dialog_title.text = - container.context.getString(R.string.mozac_feature_downloads_failed_notification_text2) + binding.downloadDialogTitle.text = + context.getString(R.string.mozac_feature_downloads_failed_notification_text2) - view.download_dialog_icon.setImageResource( + binding.downloadDialogIcon.setImageResource( mozilla.components.feature.downloads.R.drawable.mozac_feature_download_ic_download_failed ) - view.download_dialog_action_button.apply { + binding.downloadDialogActionButton.apply { text = context.getString( mozilla.components.feature.downloads.R.string.mozac_feature_downloads_button_try_again ) setOnClickListener { tryAgain(downloadState.id) context.metrics.track(Event.InAppNotificationDownloadTryAgain) - dismiss(view) + dismiss() } } } else { - val titleText = container.context.getString( + val titleText = context.getString( R.string.mozac_feature_downloads_completed_notification_text2 ) + " (${downloadState.contentLength?.toMegabyteOrKilobyteString()})" - view.download_dialog_title.text = titleText + binding.downloadDialogTitle.text = titleText - view.download_dialog_icon.setImageResource( + binding.downloadDialogIcon.setImageResource( mozilla.components.feature.downloads.R.drawable.mozac_feature_download_ic_download_complete ) - view.download_dialog_action_button.apply { + binding.downloadDialogActionButton.apply { text = context.getString( mozilla.components.feature.downloads.R.string.mozac_feature_downloads_button_open ) @@ -115,28 +111,28 @@ class DynamicDownloadDialog( } context.metrics.track(Event.InAppNotificationDownloadOpen) - dismiss(view) + dismiss() } } } - view.download_dialog_close_button.setOnClickListener { - dismiss(view) + binding.downloadDialogCloseButton.setOnClickListener { + dismiss() } - view.download_dialog_filename.text = downloadState.fileName + binding.downloadDialogFilename.text = downloadState.fileName } fun show() { - view.visibility = View.VISIBLE + binding.root.visibility = View.VISIBLE - (view.layoutParams as CoordinatorLayout.LayoutParams).apply { - (behavior as DynamicDownloadDialogBehavior).forceExpand(view) + (binding.root.layoutParams as CoordinatorLayout.LayoutParams).apply { + (behavior as DynamicDownloadDialogBehavior).forceExpand(binding.root) } } - private fun dismiss(view: View) { - view.visibility = View.GONE + private fun dismiss() { + binding.root.visibility = View.GONE onDismiss() } diff --git a/app/src/main/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataGroupViewHolder.kt b/app/src/main/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataGroupViewHolder.kt index 5a103db52..61e3bcc12 100644 --- a/app/src/main/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataGroupViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataGroupViewHolder.kt @@ -5,8 +5,8 @@ package org.mozilla.fenix.historymetadata.view import android.view.View -import kotlinx.android.synthetic.main.history_metadata_group.* import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.HistoryMetadataGroupBinding import org.mozilla.fenix.historymetadata.HistoryMetadataGroup import org.mozilla.fenix.historymetadata.interactor.HistoryMetadataInteractor import org.mozilla.fenix.utils.view.ViewHolder @@ -22,8 +22,10 @@ class HistoryMetadataGroupViewHolder( private val interactor: HistoryMetadataInteractor ) : ViewHolder(view) { + private val binding = HistoryMetadataGroupBinding.bind(view) + fun bind(historyMetadataGroup: HistoryMetadataGroup) { - history_metadata_group_title.text = historyMetadataGroup.title + binding.historyMetadataGroupTitle.text = historyMetadataGroup.title itemView.isActivated = historyMetadataGroup.expanded diff --git a/app/src/main/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataHeaderViewHolder.kt b/app/src/main/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataHeaderViewHolder.kt index 6118dbf7d..d8186aa61 100644 --- a/app/src/main/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataHeaderViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataHeaderViewHolder.kt @@ -5,8 +5,8 @@ package org.mozilla.fenix.historymetadata.view import android.view.View -import kotlinx.android.synthetic.main.history_metadata_header.* import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.HistoryMetadataHeaderBinding import org.mozilla.fenix.historymetadata.interactor.HistoryMetadataInteractor import org.mozilla.fenix.utils.view.ViewHolder @@ -22,7 +22,8 @@ class HistoryMetadataHeaderViewHolder( ) : ViewHolder(view) { init { - show_all_button.setOnClickListener { + val binding = HistoryMetadataHeaderBinding.bind(view) + binding.showAllButton.setOnClickListener { interactor.onHistoryMetadataShowAllClicked() } } diff --git a/app/src/main/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataViewHolder.kt b/app/src/main/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataViewHolder.kt index 43f0dff7f..d7dfe22b7 100644 --- a/app/src/main/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataViewHolder.kt @@ -5,11 +5,11 @@ package org.mozilla.fenix.historymetadata.view import android.view.View -import kotlinx.android.synthetic.main.history_metadata_list_row.* import mozilla.components.browser.icons.BrowserIcons import mozilla.components.browser.state.state.ContentState import mozilla.components.concept.storage.HistoryMetadata import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.HistoryMetadataListRowBinding import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.loadIntoView import org.mozilla.fenix.historymetadata.interactor.HistoryMetadataInteractor @@ -29,14 +29,16 @@ class HistoryMetadataViewHolder( private val icons: BrowserIcons = view.context.components.core.icons ) : ViewHolder(view) { + val binding = HistoryMetadataListRowBinding.bind(view) + fun bind(historyMetadata: HistoryMetadata) { - history_metadata_title.text = if (historyMetadata.title.isNullOrEmpty()) { + binding.historyMetadataTitle.text = if (historyMetadata.title.isNullOrEmpty()) { historyMetadata.key.url } else { historyMetadata.title } - icons.loadIntoView(history_metadata_icon, historyMetadata.key.url) + icons.loadIntoView(binding.historyMetadataIcon, historyMetadata.key.url) itemView.setOnClickListener { interactor.onHistoryMetadataItemClicked(historyMetadata.key.url, historyMetadata.key) diff --git a/app/src/main/java/org/mozilla/fenix/library/LibraryPageView.kt b/app/src/main/java/org/mozilla/fenix/library/LibraryPageView.kt index 183f62abf..a9d8ece85 100644 --- a/app/src/main/java/org/mozilla/fenix/library/LibraryPageView.kt +++ b/app/src/main/java/org/mozilla/fenix/library/LibraryPageView.kt @@ -8,15 +8,14 @@ import android.content.Context import android.view.ViewGroup import androidx.appcompat.widget.Toolbar import androidx.core.content.ContextCompat -import kotlinx.android.extensions.LayoutContainer import mozilla.components.support.ktx.android.content.getColorFromAttr import org.mozilla.fenix.R import org.mozilla.fenix.ext.asActivity import org.mozilla.fenix.ext.setToolbarColors open class LibraryPageView( - override val containerView: ViewGroup -) : LayoutContainer { + val containerView: ViewGroup +) { protected val context: Context inline get() = containerView.context protected val activity = context.asActivity() diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/addfolder/AddBookmarkFolderFragment.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/addfolder/AddBookmarkFolderFragment.kt index 59df17b23..e1d8be465 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/addfolder/AddBookmarkFolderFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/addfolder/AddBookmarkFolderFragment.kt @@ -14,7 +14,6 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.lifecycle.lifecycleScope import androidx.navigation.Navigation -import kotlinx.android.synthetic.main.fragment_edit_bookmark.* import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.launch @@ -24,6 +23,7 @@ import mozilla.components.support.ktx.android.view.hideKeyboard import mozilla.components.support.ktx.android.view.showKeyboard import org.mozilla.fenix.R import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.databinding.FragmentEditBookmarkBinding import org.mozilla.fenix.ext.nav import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.showToolbar @@ -34,6 +34,8 @@ import org.mozilla.fenix.library.bookmarks.friendlyRootTitle * Menu to create a new bookmark folder. */ class AddBookmarkFolderFragment : Fragment(R.layout.fragment_edit_bookmark) { + private var _binding: FragmentEditBookmarkBinding? = null + private val binding get() = _binding!! private val sharedViewModel: BookmarksSharedViewModel by activityViewModels() @@ -46,10 +48,12 @@ class AddBookmarkFolderFragment : Fragment(R.layout.fragment_edit_bookmark) { * Hides fields for bookmark items present in the shared layout file. */ override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - bookmarkUrlLabel.visibility = GONE - bookmarkUrlEdit.visibility = GONE - inputLayoutBookmarkUrl.visibility = GONE - bookmarkNameEdit.showKeyboard() + _binding = FragmentEditBookmarkBinding.bind(view) + + binding.bookmarkUrlLabel.visibility = GONE + binding.bookmarkUrlEdit.visibility = GONE + binding.inputLayoutBookmarkUrl.visibility = GONE + binding.bookmarkNameEdit.showKeyboard() } override fun onResume() { @@ -63,9 +67,9 @@ class AddBookmarkFolderFragment : Fragment(R.layout.fragment_edit_bookmark) { ?: requireComponents.core.bookmarksStorage.getBookmark(BookmarkRoot.Mobile.id) } - bookmarkParentFolderSelector.text = + binding.bookmarkParentFolderSelector.text = friendlyRootTitle(context, sharedViewModel.selectedFolder!!) - bookmarkParentFolderSelector.setOnClickListener { + binding.bookmarkParentFolderSelector.setOnClickListener { nav( R.id.bookmarkAddFolderFragment, AddBookmarkFolderFragmentDirections @@ -79,7 +83,7 @@ class AddBookmarkFolderFragment : Fragment(R.layout.fragment_edit_bookmark) { override fun onPause() { super.onPause() - bookmarkNameEdit.hideKeyboard() + binding.bookmarkNameEdit.hideKeyboard() } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { @@ -89,8 +93,8 @@ class AddBookmarkFolderFragment : Fragment(R.layout.fragment_edit_bookmark) { override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.confirm_add_folder_button -> { - if (bookmarkNameEdit.text.isNullOrBlank()) { - bookmarkNameEdit.error = + if (binding.bookmarkNameEdit.text.isNullOrBlank()) { + binding.bookmarkNameEdit.error = getString(R.string.bookmark_empty_title_error) return true } @@ -98,7 +102,7 @@ class AddBookmarkFolderFragment : Fragment(R.layout.fragment_edit_bookmark) { viewLifecycleOwner.lifecycleScope.launch(IO) { val newGuid = requireComponents.core.bookmarksStorage.addFolder( sharedViewModel.selectedFolder!!.guid, - bookmarkNameEdit.text.toString(), + binding.bookmarkNameEdit.text.toString(), null ) sharedViewModel.selectedFolder = @@ -114,4 +118,10 @@ class AddBookmarkFolderFragment : Fragment(R.layout.fragment_edit_bookmark) { else -> super.onOptionsItemSelected(item) } } + + override fun onDestroyView() { + super.onDestroyView() + + _binding = null + } } diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/edit/EditBookmarkFragment.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/edit/EditBookmarkFragment.kt index 2df8e09ae..99bc5869f 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/edit/EditBookmarkFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/edit/EditBookmarkFragment.kt @@ -23,8 +23,6 @@ import androidx.lifecycle.lifecycleScope import androidx.navigation.Navigation import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs -import kotlinx.android.synthetic.main.fragment_edit_bookmark.* -import kotlinx.android.synthetic.main.fragment_edit_bookmark.view.* import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.launch @@ -40,6 +38,7 @@ import org.mozilla.fenix.NavHostActivity import org.mozilla.fenix.R import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.metrics.Event +import org.mozilla.fenix.databinding.FragmentEditBookmarkBinding import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.getRootView import org.mozilla.fenix.ext.nav @@ -54,6 +53,8 @@ import org.mozilla.fenix.library.bookmarks.friendlyRootTitle * Menu to edit the name, URL, and location of a bookmark item. */ class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) { + private var _binding: FragmentEditBookmarkBinding? = null + private val binding get() = _binding!! private val args by navArgs() private val sharedViewModel: BookmarksSharedViewModel by activityViewModels() @@ -68,6 +69,9 @@ class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + + _binding = FragmentEditBookmarkBinding.bind(view) + initToolbar() viewLifecycleOwner.lifecycleScope.launch(Main) { @@ -95,9 +99,9 @@ class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) { when (bookmarkNode?.type) { BookmarkNodeType.FOLDER -> { activity?.title = getString(R.string.edit_bookmark_folder_fragment_title) - inputLayoutBookmarkUrl.visibility = View.GONE - bookmarkUrlEdit.visibility = View.GONE - bookmarkUrlLabel.visibility = View.GONE + binding.inputLayoutBookmarkUrl.visibility = View.GONE + binding.bookmarkUrlEdit.visibility = View.GONE + binding.bookmarkUrlLabel.visibility = View.GONE } BookmarkNodeType.ITEM -> { activity?.title = getString(R.string.edit_bookmark_fragment_title) @@ -107,15 +111,15 @@ class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) { val currentBookmarkNode = bookmarkNode if (currentBookmarkNode != null && currentBookmarkNode != bookmarkNodeBeforeReload) { - bookmarkNameEdit.setText(currentBookmarkNode.title) - bookmarkUrlEdit.setText(currentBookmarkNode.url) + binding.bookmarkNameEdit.setText(currentBookmarkNode.title) + binding.bookmarkUrlEdit.setText(currentBookmarkNode.url) } bookmarkParent?.let { node -> - bookmarkParentFolderSelector.text = friendlyRootTitle(context, node) + binding.bookmarkParentFolderSelector.text = friendlyRootTitle(context, node) } - bookmarkParentFolderSelector.setOnClickListener { + binding.bookmarkParentFolderSelector.setOnClickListener { sharedViewModel.selectedFolder = null nav( R.id.bookmarkEditFragment, @@ -131,22 +135,22 @@ class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) { ) } - view.bookmarkNameEdit.apply { + binding.bookmarkNameEdit.apply { requestFocus() placeCursorAtEnd() showKeyboard() } - view.bookmarkUrlEdit.addTextChangedListener(object : TextWatcher { + binding.bookmarkUrlEdit.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { // NOOP } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { - bookmarkUrlEdit.onTextChanged(s) + binding.bookmarkUrlEdit.onTextChanged(s) - inputLayoutBookmarkUrl.error = null - inputLayoutBookmarkUrl.errorIconDrawable = null + binding.inputLayoutBookmarkUrl.error = null + binding.inputLayoutBookmarkUrl.errorIconDrawable = null } override fun afterTextChanged(s: Editable?) { @@ -169,9 +173,9 @@ class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) { override fun onPause() { super.onPause() - bookmarkNameEdit.hideKeyboard() - bookmarkUrlEdit.hideKeyboard() - progress_bar_bookmark.visibility = View.GONE + binding.bookmarkNameEdit.hideKeyboard() + binding.bookmarkUrlEdit.hideKeyboard() + binding.progressBarBookmark.visibility = View.GONE } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { @@ -234,9 +238,9 @@ class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) { } private fun updateBookmarkFromTextChanges() { - progress_bar_bookmark.visibility = View.VISIBLE - val nameText = bookmarkNameEdit.text.toString() - val urlText = bookmarkUrlEdit.text.toString() + binding.progressBarBookmark.visibility = View.VISIBLE + val nameText = binding.bookmarkNameEdit.text.toString() + val urlText = binding.bookmarkUrlEdit.text.toString() updateBookmarkNode(nameText, urlText) } @@ -265,16 +269,16 @@ class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) { ) } withContext(Main) { - inputLayoutBookmarkUrl.error = null - inputLayoutBookmarkUrl.errorIconDrawable = null + binding.inputLayoutBookmarkUrl.error = null + binding.inputLayoutBookmarkUrl.errorIconDrawable = null findNavController().popBackStack() } } catch (e: UrlParseFailed) { withContext(Main) { - inputLayoutBookmarkUrl.error = getString(R.string.bookmark_invalid_url_error) - inputLayoutBookmarkUrl.setErrorIconDrawable(R.drawable.mozac_ic_warning_with_bottom_padding) - inputLayoutBookmarkUrl.setErrorIconTintList( + binding.inputLayoutBookmarkUrl.error = getString(R.string.bookmark_invalid_url_error) + binding.inputLayoutBookmarkUrl.setErrorIconDrawable(R.drawable.mozac_ic_warning_with_bottom_padding) + binding.inputLayoutBookmarkUrl.setErrorIconTintList( ColorStateList.valueOf( ContextCompat.getColor(requireContext(), R.color.design_error) ) @@ -282,6 +286,12 @@ class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) { } } } - progress_bar_bookmark.visibility = View.INVISIBLE + binding.progressBarBookmark.visibility = View.INVISIBLE + } + + override fun onDestroyView() { + super.onDestroyView() + + _binding = null } } diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/selectfolder/SelectBookmarkFolderAdapter.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/selectfolder/SelectBookmarkFolderAdapter.kt index 3fc46631d..527647b24 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/selectfolder/SelectBookmarkFolderAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/selectfolder/SelectBookmarkFolderAdapter.kt @@ -12,7 +12,6 @@ import androidx.core.view.updatePaddingRelative import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView -import kotlinx.android.extensions.LayoutContainer import mozilla.components.concept.storage.BookmarkNode import org.mozilla.fenix.R import org.mozilla.fenix.library.LibrarySiteItemView @@ -61,9 +60,7 @@ class SelectBookmarkFolderAdapter(private val sharedViewModel: BookmarksSharedVi class BookmarkFolderViewHolder( val view: LibrarySiteItemView - ) : RecyclerView.ViewHolder(view), LayoutContainer { - - override val containerView get() = view + ) : RecyclerView.ViewHolder(view) { init { view.displayAs(LibrarySiteItemView.ItemType.FOLDER) @@ -74,12 +71,12 @@ class SelectBookmarkFolderAdapter(private val sharedViewModel: BookmarksSharedVi view.changeSelected(selected) view.iconView.setImageDrawable( AppCompatResources.getDrawable( - containerView.context, + view.context, R.drawable.ic_folder_icon )?.apply { setTint( ContextCompat.getColor( - containerView.context, + view.context, R.color.primary_text_light_theme ) ) diff --git a/app/src/main/java/org/mozilla/fenix/library/bookmarks/selectfolder/SelectBookmarkFolderFragment.kt b/app/src/main/java/org/mozilla/fenix/library/bookmarks/selectfolder/SelectBookmarkFolderFragment.kt index dfc079dc8..3b52fa6ec 100644 --- a/app/src/main/java/org/mozilla/fenix/library/bookmarks/selectfolder/SelectBookmarkFolderFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/bookmarks/selectfolder/SelectBookmarkFolderFragment.kt @@ -15,7 +15,6 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.navArgs -import kotlinx.android.synthetic.main.fragment_select_bookmark_folder.* import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.launch @@ -23,6 +22,7 @@ import kotlinx.coroutines.withContext import mozilla.appservices.places.BookmarkRoot import mozilla.components.concept.storage.BookmarkNode import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.FragmentSelectBookmarkFolderBinding import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.nav import org.mozilla.fenix.ext.showToolbar @@ -30,6 +30,8 @@ import org.mozilla.fenix.library.bookmarks.BookmarksSharedViewModel import org.mozilla.fenix.library.bookmarks.DesktopFolders class SelectBookmarkFolderFragment : Fragment() { + private var _binding: FragmentSelectBookmarkFolderBinding? = null + private val binding get() = _binding!! private val sharedViewModel: BookmarksSharedViewModel by activityViewModels() private var bookmarkNode: BookmarkNode? = null @@ -40,7 +42,15 @@ class SelectBookmarkFolderFragment : Fragment() { } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.fragment_select_bookmark_folder, container, false) + _binding = FragmentSelectBookmarkFolderBinding.inflate(inflater, container, false) + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + + _binding = null } override fun onResume() { @@ -57,7 +67,7 @@ class SelectBookmarkFolderFragment : Fragment() { ?.let { DesktopFolders(context, showMobileRoot = true).withOptionalDesktopFolders(it) } } val adapter = SelectBookmarkFolderAdapter(sharedViewModel) - recylerViewBookmarkFolders.adapter = adapter + binding.recylerViewBookmarkFolders.adapter = adapter adapter.updateData(bookmarkNode, args.hideFolderGuid) } } diff --git a/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadView.kt b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadView.kt index c060b29f5..dcc0f88eb 100644 --- a/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadView.kt +++ b/app/src/main/java/org/mozilla/fenix/library/downloads/DownloadView.kt @@ -9,8 +9,6 @@ import android.view.ViewGroup import androidx.core.view.isVisible import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.SimpleItemAnimator -import kotlinx.android.synthetic.main.component_downloads.* -import kotlinx.android.synthetic.main.component_downloads.view.* import mozilla.components.support.base.feature.UserInteractionHandler import org.mozilla.fenix.R import org.mozilla.fenix.databinding.ComponentDownloadsBinding @@ -112,10 +110,10 @@ class DownloadView( } fun updateEmptyState(userHasDownloads: Boolean) { - download_list.isVisible = userHasDownloads - download_empty_view.isVisible = !userHasDownloads + binding.downloadList.isVisible = userHasDownloads + binding.downloadEmptyView.isVisible = !userHasDownloads if (!userHasDownloads) { - download_empty_view.announceForAccessibility(context.getString(R.string.download_empty_message_1)) + binding.downloadEmptyView.announceForAccessibility(context.getString(R.string.download_empty_message_1)) } } diff --git a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragment.kt b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragment.kt index 7505df7e9..3b9c72a34 100644 --- a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragment.kt @@ -15,7 +15,6 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import androidx.navigation.fragment.findNavController -import kotlinx.android.synthetic.main.fragment_recently_closed_tabs.view.* import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map @@ -30,6 +29,7 @@ import org.mozilla.fenix.R import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.StoreProvider +import org.mozilla.fenix.databinding.FragmentRecentlyClosedTabsBinding import org.mozilla.fenix.ext.getRootView import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.setTextColor @@ -100,8 +100,8 @@ class RecentlyClosedFragment : LibraryPageFragment(), UserIntera inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - val view = inflater.inflate(R.layout.fragment_recently_closed_tabs, container, false) + ): View { + val binding = FragmentRecentlyClosedTabsBinding.inflate(inflater, container, false) recentlyClosedFragmentStore = StoreProvider.get(this) { RecentlyClosedFragmentStore( RecentlyClosedFragmentState( @@ -126,10 +126,10 @@ class RecentlyClosedFragment : LibraryPageFragment(), UserIntera ) recentlyClosedInteractor = RecentlyClosedFragmentInteractor(recentlyClosedController) _recentlyClosedFragmentView = RecentlyClosedFragmentView( - view.recentlyClosedLayout, + binding.recentlyClosedLayout, recentlyClosedInteractor ) - return view + return binding.root } override fun onDestroyView() { diff --git a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentView.kt b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentView.kt index 0b9054ee4..16bfa738e 100644 --- a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentView.kt +++ b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedFragmentView.kt @@ -5,15 +5,14 @@ package org.mozilla.fenix.library.recentlyclosed import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import androidx.appcompat.content.res.AppCompatResources import androidx.core.view.isVisible import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.SimpleItemAnimator -import kotlinx.android.synthetic.main.component_recently_closed.* import mozilla.components.browser.state.state.recover.RecoverableTab import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.ComponentRecentlyClosedBinding import org.mozilla.fenix.library.LibraryPageView import org.mozilla.fenix.selection.SelectionInteractor @@ -74,19 +73,20 @@ class RecentlyClosedFragmentView( private val interactor: RecentlyClosedFragmentInteractor ) : LibraryPageView(container) { - val view: View = LayoutInflater.from(container.context) - .inflate(R.layout.component_recently_closed, container, true) + private val binding = ComponentRecentlyClosedBinding.inflate( + LayoutInflater.from(container.context), container, true + ) private val recentlyClosedAdapter: RecentlyClosedAdapter = RecentlyClosedAdapter(interactor) init { - recently_closed_list.apply { + binding.recentlyClosedList.apply { layoutManager = LinearLayoutManager(containerView.context) adapter = recentlyClosedAdapter (itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false } - view_more_history.apply { + binding.viewMoreHistory.apply { titleView.text = containerView.context.getString(R.string.recently_closed_show_full_history) urlView.isVisible = false @@ -106,8 +106,8 @@ class RecentlyClosedFragmentView( fun update(state: RecentlyClosedFragmentState) { state.apply { - recently_closed_empty_view.isVisible = items.isEmpty() - recently_closed_list.isVisible = items.isNotEmpty() + binding.recentlyClosedEmptyView.isVisible = items.isEmpty() + binding.recentlyClosedList.isVisible = items.isNotEmpty() recentlyClosedAdapter.updateData(items, selectedTabs) diff --git a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedItemViewHolder.kt b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedItemViewHolder.kt index 03373a94d..eca26d56d 100644 --- a/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedItemViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/library/recentlyclosed/RecentlyClosedItemViewHolder.kt @@ -6,10 +6,9 @@ package org.mozilla.fenix.library.recentlyclosed import android.view.View import androidx.recyclerview.widget.RecyclerView -import kotlinx.android.synthetic.main.history_list_item.view.* -import kotlinx.android.synthetic.main.library_site_item.view.* import mozilla.components.browser.state.state.recover.RecoverableTab import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.HistoryListItemBinding import org.mozilla.fenix.ext.hideAndDisable import org.mozilla.fenix.ext.showAndEnable import org.mozilla.fenix.selection.SelectionHolder @@ -22,6 +21,8 @@ class RecentlyClosedItemViewHolder( private val selectionHolder: SelectionHolder ) : RecyclerView.ViewHolder(view) { + private val binding = HistoryListItemBinding.bind(view) + private var item: RecoverableTab? = null init { @@ -31,21 +32,21 @@ class RecentlyClosedItemViewHolder( fun bind( item: RecoverableTab ) { - itemView.history_layout.titleView.text = + binding.historyLayout.titleView.text = if (item.title.isNotEmpty()) item.title else item.url - itemView.history_layout.urlView.text = item.url + binding.historyLayout.urlView.text = item.url - itemView.history_layout.setSelectionInteractor(item, selectionHolder, recentlyClosedFragmentInteractor) - itemView.history_layout.changeSelected(item in selectionHolder.selectedItems) + binding.historyLayout.setSelectionInteractor(item, selectionHolder, recentlyClosedFragmentInteractor) + binding.historyLayout.changeSelected(item in selectionHolder.selectedItems) if (this.item?.url != item.url) { - itemView.history_layout.loadFavicon(item.url) + binding.historyLayout.loadFavicon(item.url) } if (selectionHolder.selectedItems.isEmpty()) { - itemView.overflow_menu.showAndEnable() + binding.historyLayout.overflowView.showAndEnable() } else { - itemView.overflow_menu.hideAndDisable() + binding.historyLayout.overflowView.hideAndDisable() } this.item = item @@ -67,7 +68,7 @@ class RecentlyClosedItemViewHolder( } } - itemView.history_layout.attachMenu(historyMenu.menuController) + binding.historyLayout.attachMenu(historyMenu.menuController) } companion object { diff --git a/app/src/main/java/org/mozilla/fenix/migration/MigrationProgressActivity.kt b/app/src/main/java/org/mozilla/fenix/migration/MigrationProgressActivity.kt index 92be23ec6..e2b832f71 100644 --- a/app/src/main/java/org/mozilla/fenix/migration/MigrationProgressActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/migration/MigrationProgressActivity.kt @@ -9,7 +9,6 @@ import android.os.Bundle import android.view.View import androidx.core.content.ContextCompat import androidx.recyclerview.widget.LinearLayoutManager -import kotlinx.android.synthetic.main.activity_migration.* import mozilla.components.support.base.log.logger.Logger import mozilla.components.support.ktx.android.content.getColorFromAttr import mozilla.components.support.migration.AbstractMigrationProgressActivity @@ -21,6 +20,7 @@ import mozilla.components.support.migration.state.MigrationStore import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.IntentReceiverActivity import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.ActivityMigrationBinding import org.mozilla.fenix.ext.components class MigrationProgressActivity : AbstractMigrationProgressActivity() { @@ -28,38 +28,43 @@ class MigrationProgressActivity : AbstractMigrationProgressActivity() { private val statusAdapter = MigrationStatusAdapter() override val store: MigrationStore by lazy { components.migrationStore } + private lateinit var binding: ActivityMigrationBinding + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_migration) + + binding = ActivityMigrationBinding.inflate(layoutInflater) + setContentView(binding.root) + init() } fun init() { window.navigationBarColor = getColorFromAttr(R.attr.foundation) - val appName = migration_description.context.getString(R.string.app_name) + val appName = binding.migrationDescription.context.getString(R.string.app_name) - migration_description.apply { + binding.migrationDescription.apply { text = context.getString(R.string.migration_description, appName) } - migration_status_list.apply { + binding.migrationStatusList.apply { val margin = resources.getDimensionPixelSize(R.dimen.migration_margin) addItemDecoration(MigrationStatusItemDecoration(margin)) layoutManager = LinearLayoutManager(this@MigrationProgressActivity) adapter = statusAdapter } - migration_welcome_title.apply { + binding.migrationWelcomeTitle.apply { text = context.getString(R.string.migration_title, appName) } - migration_button_text_view.text = getString(R.string.migration_updating_app_button_text, appName) + binding.migrationButtonTextView.text = getString(R.string.migration_updating_app_button_text, appName) } override fun onMigrationCompleted(results: MigrationResults) { // Enable clicking the finish button - migration_button.apply { + binding.migrationButton.apply { setOnClickListener { AbstractMigrationService.dismissNotification(context) @@ -79,12 +84,12 @@ class MigrationProgressActivity : AbstractMigrationProgressActivity() { } } } - migration_button_text_view.apply { + binding.migrationButtonTextView.apply { text = getString(R.string.migration_update_app_button, getString(R.string.app_name)) setTextColor(ContextCompat.getColor(context, R.color.white_color)) } - migration_button.setBackgroundResource(R.drawable.migration_button_background) - migration_button_progress_bar.visibility = View.INVISIBLE + binding.migrationButton.setBackgroundResource(R.drawable.migration_button_background) + binding.migrationButtonProgressBar.visibility = View.INVISIBLE // Keep the results list up-to-date. statusAdapter.updateData(results) } diff --git a/app/src/main/java/org/mozilla/fenix/migration/MigrationStatusAdapter.kt b/app/src/main/java/org/mozilla/fenix/migration/MigrationStatusAdapter.kt index 34f55e59c..0145fa114 100644 --- a/app/src/main/java/org/mozilla/fenix/migration/MigrationStatusAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/migration/MigrationStatusAdapter.kt @@ -13,10 +13,10 @@ import androidx.core.view.isInvisible import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView -import kotlinx.android.synthetic.main.migration_list_item.view.* import mozilla.components.support.migration.Migration import mozilla.components.support.migration.MigrationResults import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.MigrationListItemBinding internal data class MigrationItem( val migration: Migration, @@ -60,9 +60,11 @@ internal class MigrationStatusAdapter : } class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { + private val context = view.context - private val title = view.migration_item_name - private val status = view.migration_status_image + private val binding = MigrationListItemBinding.bind(view) + private val title = binding.migrationItemName + private val status = binding.migrationStatusImage fun bind(item: MigrationItem) { // Get the resource ID for the item. diff --git a/app/src/main/java/org/mozilla/fenix/nimbus/view/NimbusBranchesView.kt b/app/src/main/java/org/mozilla/fenix/nimbus/view/NimbusBranchesView.kt index 5fdb59137..9a1213b80 100644 --- a/app/src/main/java/org/mozilla/fenix/nimbus/view/NimbusBranchesView.kt +++ b/app/src/main/java/org/mozilla/fenix/nimbus/view/NimbusBranchesView.kt @@ -7,7 +7,6 @@ package org.mozilla.fenix.nimbus.view import android.view.ViewGroup import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import kotlinx.android.extensions.LayoutContainer import mozilla.components.service.nimbus.ui.NimbusBranchAdapter import org.mozilla.fenix.nimbus.NimbusBranchesState import org.mozilla.fenix.nimbus.controller.NimbusBranchesController @@ -16,9 +15,9 @@ import org.mozilla.fenix.nimbus.controller.NimbusBranchesController * View used for managing a Nimbus experiment's branches. */ class NimbusBranchesView( - override val containerView: ViewGroup, + private val containerView: ViewGroup, val controller: NimbusBranchesController -) : LayoutContainer { +) { private val nimbusAdapter = NimbusBranchAdapter(controller) diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt index 06df6b870..3acf7c6ec 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt @@ -35,9 +35,6 @@ import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs -import kotlinx.android.synthetic.main.fragment_search_dialog.* -import kotlinx.android.synthetic.main.fragment_search_dialog.view.* -import kotlinx.android.synthetic.main.search_suggestions_hint.view.* import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map @@ -62,6 +59,8 @@ import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.toolbar.ToolbarPosition +import org.mozilla.fenix.databinding.FragmentSearchDialogBinding +import org.mozilla.fenix.databinding.SearchSuggestionsHintBinding import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.settings @@ -74,6 +73,9 @@ typealias SearchDialogFragmentStore = SearchFragmentStore @SuppressWarnings("LargeClass", "TooManyFunctions") class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { + private var _binding: FragmentSearchDialogBinding? = null + private val binding get() = _binding!! + private var voiceSearchButtonAlreadyAdded: Boolean = false private lateinit var interactor: SearchDialogInteractor private lateinit var store: SearchDialogFragmentStore @@ -134,9 +136,9 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { + ): View { val args by navArgs() - val view = inflater.inflate(R.layout.fragment_search_dialog, container, false) + _binding = FragmentSearchDialogBinding.inflate(inflater, container, false) val activity = requireActivity() as HomeActivity val isPrivate = activity.browsingModeManager.mode.isPrivate @@ -187,12 +189,12 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { interactor, historyStorageProvider(), isPrivate, - view.toolbar, + binding.toolbar, requireComponents.core.engine, fromHomeFragment ) - val awesomeBar = view.awesome_bar + val awesomeBar = binding.awesomeBar awesomeBar.customizeForBottomToolbar = requireContext().settings().shouldUseBottomToolbar awesomeBarView = AwesomeBarView( @@ -202,8 +204,8 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { fromHomeFragment ) - view.awesome_bar.setOnTouchListener { _, _ -> - view.hideKeyboard() + binding.awesomeBar.setOnTouchListener { _, _ -> + binding.root.hideKeyboard() false } @@ -217,14 +219,14 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { if (fromHomeFragment) { // When displayed above home, dispatches the touch events to scrim area to the HomeFragment - view.search_wrapper.background = ColorDrawable(Color.TRANSPARENT) + binding.searchWrapper.background = ColorDrawable(Color.TRANSPARENT) dialog?.window?.decorView?.setOnTouchListener { _, event -> requireActivity().dispatchTouchEvent(event) false } } - return view + return binding.root } @ExperimentalCoroutinesApi @@ -244,13 +246,13 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { // When displayed above browser, dismisses dialog on clicking scrim area if (findNavController().previousBackStackEntry?.destination?.id == R.id.browserFragment) { - search_wrapper.setOnClickListener { + binding.searchWrapper.setOnClickListener { it.hideKeyboard() dismissAllowingStateLoss() } } - view.search_engines_shortcut_button.setOnClickListener { + binding.searchEnginesShortcutButton.setOnClickListener { interactor.onSearchShortcutsButtonClicked() } @@ -260,18 +262,18 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { view = view ) - qr_scan_button.visibility = if (context?.hasCamera() == true) View.VISIBLE else View.GONE + binding.qrScanButton.visibility = if (context?.hasCamera() == true) View.VISIBLE else View.GONE - qr_scan_button.setOnClickListener { + binding.qrScanButton.setOnClickListener { if (!requireContext().hasCamera()) { return@setOnClickListener } view.hideKeyboard() toolbarView.view.clearFocus() if (requireContext().settings().shouldShowCameraPermissionPrompt) { - qrFeature.get()?.scan(R.id.search_wrapper) + qrFeature.get()?.scan(binding.searchWrapper.id) } else { if (requireContext().isPermissionGranted(Manifest.permission.CAMERA)) { - qrFeature.get()?.scan(R.id.search_wrapper) + qrFeature.get()?.scan(binding.searchWrapper.id) } else { interactor.onCameraPermissionsNeeded() resetFocus() @@ -282,7 +284,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { requireContext().settings().setCameraPermissionNeededState = false } - fill_link_from_clipboard.setOnClickListener { + binding.fillLinkFromClipboard.setOnClickListener { requireComponents.analytics.metrics.track(Event.ClipboardSuggestionClicked) view.hideKeyboard() toolbarView.view.clearFocus() @@ -295,7 +297,9 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { } val stubListener = ViewStub.OnInflateListener { _, inflated -> - inflated.learn_more.setOnClickListener { + val searchSuggestionHintBinding = SearchSuggestionsHintBinding.bind(inflated) + + searchSuggestionHintBinding.learnMore.setOnClickListener { (activity as HomeActivity) .openToBrowserAndLoad( searchTermOrURL = SupportUtils.getGenericSumoURLForTopic( @@ -306,7 +310,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { ) } - inflated.allow.setOnClickListener { + searchSuggestionHintBinding.allow.setOnClickListener { inflated.visibility = View.GONE requireContext().settings().also { it.shouldShowSearchSuggestionsInPrivate = true @@ -317,7 +321,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { requireComponents.analytics.metrics.track(Event.PrivateBrowsingShowSearchSuggestions) } - inflated.dismiss.setOnClickListener { + searchSuggestionHintBinding.dismiss.setOnClickListener { inflated.visibility = View.GONE requireContext().settings().also { it.shouldShowSearchSuggestionsInPrivate = false @@ -325,14 +329,14 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { } } - inflated.text.text = + searchSuggestionHintBinding.text.text = getString(R.string.search_suggestions_onboarding_text, getString(R.string.app_name)) - inflated.title.text = + searchSuggestionHintBinding.title.text = getString(R.string.search_suggestions_onboarding_title) } - view.search_suggestions_hint.setOnInflateListener((stubListener)) + binding.searchSuggestionsHint.setOnInflateListener((stubListener)) if (view.context.settings().accessibilityServicesEnabled) { updateAccessibilityTraversalOrder() } @@ -344,7 +348,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { * query as consumeFrom may run several times on fragment start due to state updates. * */ if (it.url != it.query) firstUpdate = false - awesome_bar?.visibility = if (shouldShowAwesomebar(it)) View.VISIBLE else View.INVISIBLE + binding.awesomeBar.visibility = if (shouldShowAwesomebar(it)) View.VISIBLE else View.INVISIBLE updateSearchSuggestionsHintVisibility(it) updateClipboardSuggestion(it, requireContext().components.clipboardHandler.url) updateToolbarContentDescription(it) @@ -359,14 +363,14 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { !firstUpdate && searchFragmentState.query.isNotBlank() || searchFragmentState.showSearchShortcuts private fun updateAccessibilityTraversalOrder() { - val searchWrapperId = search_wrapper.id + val searchWrapperId = binding.searchWrapper.id if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { - qr_scan_button.accessibilityTraversalAfter = searchWrapperId - search_engines_shortcut_button.accessibilityTraversalAfter = searchWrapperId - fill_link_from_clipboard.accessibilityTraversalAfter = searchWrapperId + binding.qrScanButton.accessibilityTraversalAfter = searchWrapperId + binding.searchEnginesShortcutButton.accessibilityTraversalAfter = searchWrapperId + binding.fillLinkFromClipboard.accessibilityTraversalAfter = searchWrapperId } else { viewLifecycleOwner.lifecycleScope.launch { - search_wrapper.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED) + binding.searchWrapper.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED) } } } @@ -376,6 +380,12 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { view?.hideKeyboard() } + override fun onDestroyView() { + super.onDestroyView() + + _binding = null + } + /* * This way of dismissing the keyboard is needed to smoothly dismiss the keyboard while the dialog * is also dismissing. For example, when clicking a top site on home while this dialog is showing. @@ -442,7 +452,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { requestPermissions(permissions, REQUEST_CODE_CAMERA_PERMISSIONS) }, onScanResult = { result -> - qr_scan_button.isChecked = false + binding.qrScanButton.isChecked = false activity?.let { AlertDialog.Builder(it).apply { val spannable = resources.getSpanned( @@ -487,7 +497,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { } private fun resetFocus() { - qr_scan_button.isChecked = false + binding.qrScanButton.isChecked = false toolbarView.view.edit.focus() toolbarView.view.requestFocus() } @@ -495,31 +505,31 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { private fun setupConstraints(view: View) { if (view.context.settings().toolbarPosition == ToolbarPosition.BOTTOM) { ConstraintSet().apply { - clone(search_wrapper) + clone(binding.searchWrapper) - clear(toolbar.id, TOP) - connect(toolbar.id, BOTTOM, PARENT_ID, BOTTOM) + clear(binding.toolbar.id, TOP) + connect(binding.toolbar.id, BOTTOM, PARENT_ID, BOTTOM) - clear(pill_wrapper.id, BOTTOM) - connect(pill_wrapper.id, BOTTOM, toolbar.id, TOP) + clear(binding.pillWrapper.id, BOTTOM) + connect(binding.pillWrapper.id, BOTTOM, binding.toolbar.id, TOP) - clear(awesome_bar.id, TOP) - clear(awesome_bar.id, BOTTOM) - connect(awesome_bar.id, TOP, search_suggestions_hint.id, BOTTOM) - connect(awesome_bar.id, BOTTOM, pill_wrapper.id, TOP) + clear(binding.awesomeBar.id, TOP) + clear(binding.awesomeBar.id, BOTTOM) + connect(binding.awesomeBar.id, TOP, binding.searchSuggestionsHint.id, BOTTOM) + connect(binding.awesomeBar.id, BOTTOM, binding.pillWrapper.id, TOP) - clear(search_suggestions_hint.id, TOP) - clear(search_suggestions_hint.id, BOTTOM) - connect(search_suggestions_hint.id, TOP, PARENT_ID, TOP) - connect(search_suggestions_hint.id, BOTTOM, search_hint_bottom_barrier.id, TOP) + clear(binding.searchSuggestionsHint.id, TOP) + clear(binding.searchSuggestionsHint.id, BOTTOM) + connect(binding.searchSuggestionsHint.id, TOP, PARENT_ID, TOP) + connect(binding.searchSuggestionsHint.id, BOTTOM, binding.searchHintBottomBarrier.id, TOP) - clear(fill_link_from_clipboard.id, TOP) - connect(fill_link_from_clipboard.id, BOTTOM, pill_wrapper.id, TOP) + clear(binding.fillLinkFromClipboard.id, TOP) + connect(binding.fillLinkFromClipboard.id, BOTTOM, binding.pillWrapper.id, TOP) - clear(fill_link_divider.id, TOP) - connect(fill_link_divider.id, BOTTOM, fill_link_from_clipboard.id, TOP) + clear(binding.fillLinkDivider.id, TOP) + connect(binding.fillLinkDivider.id, BOTTOM, binding.fillLinkFromClipboard.id, TOP) - applyTo(search_wrapper) + applyTo(binding.searchWrapper) } } } @@ -530,8 +540,8 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { !state.showSearchShortcuts && state.url != state.query - findViewById(R.id.search_suggestions_hint)?.isVisible = showHint - search_suggestions_hint_divider?.isVisible = showHint + binding.searchSuggestionsHint.isVisible = showHint + binding.searchSuggestionsHintDivider.isVisible = showHint } } @@ -581,17 +591,18 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { searchState.query.isEmpty() && !clipboardUrl.isNullOrEmpty() && !searchState.showSearchShortcuts - fill_link_from_clipboard.isVisible = shouldShowView - fill_link_divider.isVisible = shouldShowView - pill_wrapper_divider.isVisible = + binding.fillLinkFromClipboard.isVisible = shouldShowView + binding.fillLinkDivider.isVisible = shouldShowView + binding.pillWrapperDivider.isVisible = !(shouldShowView && requireComponents.settings.shouldUseBottomToolbar) - clipboard_url.isVisible = shouldShowView - clipboard_title.isVisible = shouldShowView - link_icon.isVisible = shouldShowView + binding.clipboardUrl.isVisible = shouldShowView + binding.clipboardTitle.isVisible = shouldShowView + binding.linkIcon.isVisible = shouldShowView - clipboard_url.text = clipboardUrl + binding.clipboardUrl.text = clipboardUrl - fill_link_from_clipboard.contentDescription = "${clipboard_title.text}, ${clipboard_url.text}." + binding.fillLinkFromClipboard.contentDescription = + "${binding.clipboardTitle.text}, ${binding.clipboardUrl.text}." if (clipboardUrl != null && !((activity as HomeActivity).browsingModeManager.mode.isPrivate)) { requireComponents.core.engine.speculativeConnect(clipboardUrl) @@ -611,13 +622,13 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { private fun updateSearchShortcutsIcon(searchState: SearchFragmentState) { view?.apply { - search_engines_shortcut_button.isVisible = searchState.areShortcutsAvailable + binding.searchEnginesShortcutButton.isVisible = searchState.areShortcutsAvailable val showShortcuts = searchState.showSearchShortcuts - search_engines_shortcut_button.isChecked = showShortcuts + binding.searchEnginesShortcutButton.isChecked = showShortcuts val color = if (showShortcuts) R.attr.contrastText else R.attr.primaryText - search_engines_shortcut_button.compoundDrawables[0]?.setTint( + binding.searchEnginesShortcutButton.compoundDrawables[0]?.setTint( requireContext().getColorFromAttr(color) ) } diff --git a/app/src/main/java/org/mozilla/fenix/settings/account/TurnOnSyncFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/account/TurnOnSyncFragment.kt index 7162b11df..ff3447a68 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/account/TurnOnSyncFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/account/TurnOnSyncFragment.kt @@ -87,7 +87,6 @@ class TurnOnSyncFragment : Fragment(), AccountObserver { override fun onDestroy() { super.onDestroy() requireComponents.analytics.metrics.track(Event.SyncAuthClosed) - _binding = null } override fun onResume() { @@ -139,6 +138,12 @@ class TurnOnSyncFragment : Fragment(), AccountObserver { return binding.root } + override fun onDestroyView() { + super.onDestroyView() + + _binding = null + } + override fun onAuthenticated(account: OAuthAccount, authType: AuthType) { // If we're in a `shouldLoginJustWithEmail = true` state, we won't have a view available, // and can't display a snackbar. diff --git a/app/src/main/java/org/mozilla/fenix/settings/advanced/LocaleSettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/advanced/LocaleSettingsFragment.kt index 37e342fd2..6e951e476 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/advanced/LocaleSettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/advanced/LocaleSettingsFragment.kt @@ -104,9 +104,14 @@ class LocaleSettingsFragment : Fragment() { } } + override fun onDestroyView() { + super.onDestroyView() + + _binding = null + } + override fun onDestroy() { super.onDestroy() requireComponents.analytics.metrics.track(Event.SyncAuthClosed) - _binding = null } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/logins/view/SavedLoginsListView.kt b/app/src/main/java/org/mozilla/fenix/settings/logins/view/SavedLoginsListView.kt index 005e20bd5..362261aa9 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/logins/view/SavedLoginsListView.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/logins/view/SavedLoginsListView.kt @@ -7,44 +7,41 @@ package org.mozilla.fenix.settings.logins.view import android.text.method.LinkMovementMethod import android.view.LayoutInflater import android.view.ViewGroup -import android.widget.FrameLayout import androidx.core.view.isVisible import androidx.recyclerview.widget.LinearLayoutManager -import kotlinx.android.extensions.LayoutContainer -import kotlinx.android.synthetic.main.component_saved_logins.view.* import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.ComponentSavedLoginsBinding +import org.mozilla.fenix.ext.addUnderline import org.mozilla.fenix.settings.logins.LoginsListState import org.mozilla.fenix.settings.logins.interactor.SavedLoginsInteractor -import org.mozilla.fenix.ext.addUnderline /** * View that contains and configures the Saved Logins List */ class SavedLoginsListView( - override val containerView: ViewGroup, + private val containerView: ViewGroup, val interactor: SavedLoginsInteractor -) : LayoutContainer { - - val view: FrameLayout = LayoutInflater.from(containerView.context) - .inflate(R.layout.component_saved_logins, containerView, true) - .findViewById(R.id.saved_logins_wrapper) +) { + private val binding = ComponentSavedLoginsBinding.inflate( + LayoutInflater.from(containerView.context), containerView, true + ) private val loginsAdapter = LoginsAdapter(interactor) init { - view.saved_logins_list.apply { + binding.savedLoginsList.apply { adapter = loginsAdapter layoutManager = LinearLayoutManager(containerView.context) itemAnimator = null } - with(view.saved_passwords_empty_learn_more) { + with(binding.savedPasswordsEmptyLearnMore) { movementMethod = LinkMovementMethod.getInstance() addUnderline() setOnClickListener { interactor.onLearnMoreClicked() } } - with(view.saved_passwords_empty_message) { + with(binding.savedPasswordsEmptyMessage) { val appName = context.getString(R.string.app_name) text = String.format( context.getString( @@ -57,11 +54,11 @@ class SavedLoginsListView( fun update(state: LoginsListState) { if (state.isLoading) { - view.progress_bar.isVisible = true + binding.progressBar.isVisible = true } else { - view.progress_bar.isVisible = false - view.saved_logins_list.isVisible = state.loginList.isNotEmpty() - view.saved_passwords_empty_view.isVisible = state.loginList.isEmpty() + binding.progressBar.isVisible = false + binding.savedLoginsList.isVisible = state.loginList.isNotEmpty() + binding.savedPasswordsEmptyView.isVisible = state.loginList.isEmpty() } loginsAdapter.submitList(state.filteredItems) } diff --git a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/ConnectionPanelDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/ConnectionPanelDialogFragment.kt index 743de354e..d47bdb945 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/ConnectionPanelDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/ConnectionPanelDialogFragment.kt @@ -71,6 +71,12 @@ class ConnectionPanelDialogFragment : FenixDialogFragment() { ) } + override fun onDestroyView() { + super.onDestroyView() + + _binding = null + } + private fun getCurrentTab(): SessionState? { return requireComponents.core.store.state.findTabOrCustomTab(args.sessionId) } diff --git a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt index 90a3660ca..1d86c2b00 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/quicksettings/QuickSettingsSheetDialogFragment.kt @@ -43,6 +43,7 @@ import org.mozilla.fenix.settings.PhoneFeature * - website tracking protection. * - website permission. */ +@Suppress("TooManyFunctions") class QuickSettingsSheetDialogFragment : FenixDialogFragment() { private lateinit var quickSettingsStore: QuickSettingsFragmentStore @@ -131,6 +132,12 @@ class QuickSettingsSheetDialogFragment : FenixDialogFragment() { } } + override fun onDestroyView() { + super.onDestroyView() + + _binding = null + } + override fun onRequestPermissionsResult( requestCode: Int, permissions: Array, diff --git a/app/src/main/java/org/mozilla/fenix/share/AddNewDeviceFragment.kt b/app/src/main/java/org/mozilla/fenix/share/AddNewDeviceFragment.kt index 17c0db0f0..bf9132875 100644 --- a/app/src/main/java/org/mozilla/fenix/share/AddNewDeviceFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/share/AddNewDeviceFragment.kt @@ -8,10 +8,10 @@ import android.os.Bundle import android.view.View import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment -import kotlinx.android.synthetic.main.fragment_add_new_device.* import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.FragmentAddNewDeviceBinding import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.settings.SupportUtils @@ -27,7 +27,9 @@ class AddNewDeviceFragment : Fragment(R.layout.fragment_add_new_device) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - learn_button.setOnClickListener { + + val binding = FragmentAddNewDeviceBinding.bind(view) + binding.learnButton.setOnClickListener { (activity as HomeActivity).openToBrowserAndLoad( searchTermOrURL = SupportUtils.getSumoURLForTopic( requireContext(), @@ -38,7 +40,7 @@ class AddNewDeviceFragment : Fragment(R.layout.fragment_add_new_device) { ) } - connect_button.setOnClickListener { + binding.connectButton.setOnClickListener { AlertDialog.Builder(requireContext()).apply { setMessage(R.string.sync_connect_device_dialog) setPositiveButton(R.string.sync_confirmation_button) { dialog, _ -> dialog.cancel() } diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareToAccountDevicesView.kt b/app/src/main/java/org/mozilla/fenix/share/ShareToAccountDevicesView.kt index 346417f6c..fe8cd1efb 100644 --- a/app/src/main/java/org/mozilla/fenix/share/ShareToAccountDevicesView.kt +++ b/app/src/main/java/org/mozilla/fenix/share/ShareToAccountDevicesView.kt @@ -6,7 +6,6 @@ package org.mozilla.fenix.share import android.view.LayoutInflater import android.view.ViewGroup -import kotlinx.android.extensions.LayoutContainer import mozilla.components.concept.sync.Device import org.mozilla.fenix.databinding.ShareToAccountDevicesBinding import org.mozilla.fenix.share.listadapters.AccountDevicesShareAdapter @@ -24,9 +23,9 @@ interface ShareToAccountDevicesInteractor { } class ShareToAccountDevicesView( - override val containerView: ViewGroup, + containerView: ViewGroup, interactor: ShareToAccountDevicesInteractor -) : LayoutContainer { +) { private val adapter = AccountDevicesShareAdapter(interactor) diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareToAppsView.kt b/app/src/main/java/org/mozilla/fenix/share/ShareToAppsView.kt index 2fc773ed3..4556a83df 100644 --- a/app/src/main/java/org/mozilla/fenix/share/ShareToAppsView.kt +++ b/app/src/main/java/org/mozilla/fenix/share/ShareToAppsView.kt @@ -7,7 +7,6 @@ package org.mozilla.fenix.share import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import kotlinx.android.extensions.LayoutContainer import org.mozilla.fenix.databinding.ShareToAppsBinding import org.mozilla.fenix.share.listadapters.AppShareAdapter import org.mozilla.fenix.share.listadapters.AppShareOption @@ -20,9 +19,9 @@ interface ShareToAppsInteractor { } class ShareToAppsView( - override val containerView: ViewGroup, + containerView: ViewGroup, interactor: ShareToAppsInteractor -) : LayoutContainer { +) { private val adapter = AppShareAdapter(interactor) private val recentAdapter = AppShareAdapter(interactor) diff --git a/app/src/main/java/org/mozilla/fenix/shortcut/CreateShortcutFragment.kt b/app/src/main/java/org/mozilla/fenix/shortcut/CreateShortcutFragment.kt index c7289d93e..d9b9df3dc 100644 --- a/app/src/main/java/org/mozilla/fenix/shortcut/CreateShortcutFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/shortcut/CreateShortcutFragment.kt @@ -11,14 +11,17 @@ import android.view.ViewGroup import androidx.core.widget.addTextChangedListener import androidx.fragment.app.DialogFragment import androidx.lifecycle.lifecycleScope -import kotlinx.android.synthetic.main.fragment_create_shortcut.* import kotlinx.coroutines.launch import mozilla.components.browser.state.selector.selectedTab import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.FragmentCreateShortcutBinding import org.mozilla.fenix.ext.loadIntoView import org.mozilla.fenix.ext.requireComponents class CreateShortcutFragment : DialogFragment() { + private var _binding: FragmentCreateShortcutBinding? = null + private val binding get() = _binding!! + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(STYLE_NO_TITLE, R.style.CreateShortcutDialogStyle) @@ -28,7 +31,11 @@ class CreateShortcutFragment : DialogFragment() { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? = inflater.inflate(R.layout.fragment_create_shortcut, container, false) + ): View { + _binding = FragmentCreateShortcutBinding.inflate(inflater, container, false) + + return binding.root + } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -38,29 +45,35 @@ class CreateShortcutFragment : DialogFragment() { if (tab == null) { dismiss() } else { - requireComponents.core.icons.loadIntoView(favicon_image, tab.content.url) + requireComponents.core.icons.loadIntoView(binding.faviconImage, tab.content.url) - cancel_button.setOnClickListener { dismiss() } - add_button.setOnClickListener { - val text = shortcut_text.text.toString().trim() + binding.cancelButton.setOnClickListener { dismiss() } + binding.addButton.setOnClickListener { + val text = binding.shortcutText.text.toString().trim() requireActivity().lifecycleScope.launch { requireComponents.useCases.webAppUseCases.addToHomescreen(text) } dismiss() } - shortcut_text.addTextChangedListener { + binding.shortcutText.addTextChangedListener { updateAddButtonEnabledState() } - shortcut_text.setText(tab.content.title) + binding.shortcutText.setText(tab.content.title) } } + override fun onDestroyView() { + super.onDestroyView() + + _binding = null + } + private fun updateAddButtonEnabledState() { - val text = shortcut_text.text - add_button.isEnabled = text.isNotBlank() - add_button.alpha = if (text.isNotBlank()) ENABLED_ALPHA else DISABLED_ALPHA + val text = binding.shortcutText.text + binding.addButton.isEnabled = text.isNotBlank() + binding.addButton.alpha = if (text.isNotBlank()) ENABLED_ALPHA else DISABLED_ALPHA } companion object { diff --git a/app/src/main/java/org/mozilla/fenix/shortcut/PwaOnboardingDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/shortcut/PwaOnboardingDialogFragment.kt index 05d8520e3..952751fa2 100644 --- a/app/src/main/java/org/mozilla/fenix/shortcut/PwaOnboardingDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/shortcut/PwaOnboardingDialogFragment.kt @@ -10,9 +10,9 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.DialogFragment import androidx.lifecycle.lifecycleScope -import kotlinx.android.synthetic.main.fragment_create_shortcut.* import kotlinx.coroutines.launch import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.FragmentPwaOnboardingBinding import org.mozilla.fenix.ext.requireComponents /** @@ -33,9 +33,10 @@ class PwaOnboardingDialogFragment : DialogFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val components = requireComponents + val binding = FragmentPwaOnboardingBinding.bind(view) - cancel_button.setOnClickListener { dismiss() } - add_button.setOnClickListener { + binding.cancelButton.setOnClickListener { dismiss() } + binding.addButton.setOnClickListener { viewLifecycleOwner.lifecycleScope.launch { components.useCases.webAppUseCases.addToHomescreen() }.invokeOnCompletion { diff --git a/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsViewHolder.kt b/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsViewHolder.kt index 158450696..bf57fb1d4 100644 --- a/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsViewHolder.kt @@ -32,7 +32,6 @@ sealed class SyncedTabsViewHolder(itemView: View) : RecyclerView.ViewHolder(item abstract fun bind(item: T, interactor: SyncedTabsView.Listener) class TabViewHolder(itemView: View) : SyncedTabsViewHolder(itemView) { - override fun bind(item: T, interactor: SyncedTabsView.Listener) { bindTab(item as AdapterItem.Tab) @@ -56,7 +55,6 @@ sealed class SyncedTabsViewHolder(itemView: View) : RecyclerView.ViewHolder(item } class ErrorViewHolder(itemView: View) : SyncedTabsViewHolder(itemView) { - override fun bind(item: T, interactor: SyncedTabsView.Listener) { val errorItem = item as AdapterItem.Error val binding = SyncTabsErrorRowBinding.bind(itemView) @@ -105,7 +103,6 @@ sealed class SyncedTabsViewHolder(itemView: View) : RecyclerView.ViewHolder(item } class TitleViewHolder(itemView: View) : SyncedTabsViewHolder(itemView) { - override fun bind(item: T, interactor: SyncedTabsView.Listener) { val binding = ViewSyncedTabsTitleBinding.bind(itemView) binding.refreshIcon.setOnClickListener { v -> diff --git a/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryDialogFragment.kt index eece98cea..f8b3cb278 100644 --- a/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryDialogFragment.kt @@ -12,7 +12,6 @@ import androidx.navigation.fragment.findNavController import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialogFragment -import kotlinx.android.synthetic.main.fragment_tab_history_dialog.* import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.mapNotNull @@ -21,6 +20,7 @@ import mozilla.components.lib.state.ext.flowScoped import mozilla.components.support.ktx.android.content.getColorFromAttr import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.FragmentTabHistoryDialogBinding import org.mozilla.fenix.ext.requireComponents class TabHistoryDialogFragment : BottomSheetDialogFragment() { @@ -37,6 +37,8 @@ class TabHistoryDialogFragment : BottomSheetDialogFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + val binding = FragmentTabHistoryDialogBinding.bind(view) + view.setBackgroundColor(view.context.getColorFromAttr(R.attr.foundation)) customTabSessionId = requireArguments().getString(EXTRA_SESSION_ID) @@ -47,7 +49,7 @@ class TabHistoryDialogFragment : BottomSheetDialogFragment() { customTabId = customTabSessionId ) val tabHistoryView = TabHistoryView( - container = tabHistoryLayout, + container = binding.tabHistoryLayout, expandDialog = ::expand, interactor = TabHistoryInteractor(controller) ) diff --git a/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryView.kt b/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryView.kt index 789db3d60..87f710e56 100644 --- a/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryView.kt +++ b/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryView.kt @@ -5,14 +5,11 @@ package org.mozilla.fenix.tabhistory import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import kotlinx.android.extensions.LayoutContainer -import kotlinx.android.synthetic.main.component_tabhistory.* import mozilla.components.browser.state.state.content.HistoryState -import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.ComponentTabhistoryBinding interface TabHistoryViewInteractor { @@ -26,13 +23,12 @@ class TabHistoryView( container: ViewGroup, private val expandDialog: () -> Unit, interactor: TabHistoryViewInteractor -) : LayoutContainer { +) { - override val containerView: View = LayoutInflater.from(container.context) - .inflate(R.layout.component_tabhistory, container, true) + private val binding = ComponentTabhistoryBinding.inflate(LayoutInflater.from(container.context), container, true) private val adapter = TabHistoryAdapter(interactor) - private val layoutManager = object : LinearLayoutManager(containerView.context) { + private val layoutManager = object : LinearLayoutManager(container.context) { private var shouldScrollToSelected = true @@ -45,10 +41,10 @@ class TabHistoryView( // Force expansion of the dialog, otherwise scrolling to the current history item // won't work when its position is near the bottom of the recyclerview. expandDialog.invoke() - val itemView = tabHistoryRecyclerView.findViewHolderForLayoutPosition( + val itemView = binding.tabHistoryRecyclerView.findViewHolderForLayoutPosition( findFirstCompletelyVisibleItemPosition() )?.itemView - val offset = tabHistoryRecyclerView.height / 2 - (itemView?.height ?: 0) / 2 + val offset = binding.tabHistoryRecyclerView.height / 2 - (itemView?.height ?: 0) / 2 scrollToPositionWithOffset(index, offset) shouldScrollToSelected = false } @@ -61,8 +57,8 @@ class TabHistoryView( private var currentIndex: Int? = null init { - tabHistoryRecyclerView.adapter = adapter - tabHistoryRecyclerView.layoutManager = layoutManager + binding.tabHistoryRecyclerView.adapter = adapter + binding.tabHistoryRecyclerView.layoutManager = layoutManager } fun updateState(historyState: HistoryState) { diff --git a/app/src/main/java/org/mozilla/fenix/utils/ToolbarPopupWindow.kt b/app/src/main/java/org/mozilla/fenix/utils/ToolbarPopupWindow.kt index db2d0b5a9..da0cadc58 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/ToolbarPopupWindow.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/ToolbarPopupWindow.kt @@ -14,7 +14,6 @@ import android.widget.PopupWindow import androidx.annotation.VisibleForTesting import androidx.core.view.isVisible import com.google.android.material.snackbar.Snackbar -import kotlinx.android.synthetic.main.browser_toolbar_popup_window.view.* import mozilla.components.browser.state.selector.selectedTab import mozilla.components.browser.state.store.BrowserStore import org.mozilla.fenix.R @@ -23,6 +22,7 @@ import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.ext.components import java.lang.ref.WeakReference import mozilla.components.browser.state.selector.findCustomTab +import org.mozilla.fenix.databinding.BrowserToolbarPopupWindowBinding object ToolbarPopupWindow { fun show( @@ -38,10 +38,9 @@ object ToolbarPopupWindow { val isCustomTabSession = customTabId != null - val customView = LayoutInflater.from(context) - .inflate(R.layout.browser_toolbar_popup_window, null) + val binding = BrowserToolbarPopupWindowBinding.inflate(LayoutInflater.from(context)) val popupWindow = PopupWindow( - customView, + binding.root, LinearLayout.LayoutParams.WRAP_CONTENT, context.resources.getDimensionPixelSize(R.dimen.context_menu_height), true @@ -53,13 +52,13 @@ object ToolbarPopupWindow { // See: https://github.com/mozilla-mobile/fenix/issues/10027 popupWindow.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - customView.copy.isVisible = copyVisible + binding.copy.isVisible = copyVisible - customView.paste.isVisible = !clipboard.text.isNullOrEmpty() && !isCustomTabSession - customView.paste_and_go.isVisible = + binding.paste.isVisible = !clipboard.text.isNullOrEmpty() && !isCustomTabSession + binding.pasteAndGo.isVisible = !clipboard.text.isNullOrEmpty() && !isCustomTabSession - customView.copy.setOnClickListener { + binding.copy.setOnClickListener { popupWindow.dismiss() clipboard.text = getUrlForClipboard( it.context.components.core.store, @@ -78,12 +77,12 @@ object ToolbarPopupWindow { context.components.analytics.metrics.track(Event.CopyUrlUsed) } - customView.paste.setOnClickListener { + binding.paste.setOnClickListener { popupWindow.dismiss() handlePaste(clipboard.text!!) } - customView.paste_and_go.setOnClickListener { + binding.pasteAndGo.setOnClickListener { popupWindow.dismiss() handlePasteAndGo(clipboard.text!!) } diff --git a/app/src/main/java/org/mozilla/fenix/utils/view/ViewHolder.kt b/app/src/main/java/org/mozilla/fenix/utils/view/ViewHolder.kt index 21a1eb638..61901a8d1 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/view/ViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/view/ViewHolder.kt @@ -6,12 +6,11 @@ package org.mozilla.fenix.utils.view import android.view.View import androidx.recyclerview.widget.RecyclerView -import kotlinx.android.extensions.LayoutContainer /** * A base class for all recycler view holders supporting Android Extensions-style view access. * This allows views to be used without an `itemView.` prefix, and additionally caches them. */ abstract class ViewHolder( - override val containerView: View -) : RecyclerView.ViewHolder(containerView), LayoutContainer + val containerView: View +) : RecyclerView.ViewHolder(containerView) diff --git a/app/src/test/java/org/mozilla/fenix/addons/AddonDetailsViewTest.kt b/app/src/test/java/org/mozilla/fenix/addons/AddonDetailsBindingDelegateTest.kt similarity index 87% rename from app/src/test/java/org/mozilla/fenix/addons/AddonDetailsViewTest.kt rename to app/src/test/java/org/mozilla/fenix/addons/AddonDetailsBindingDelegateTest.kt index 98af34120..7f2ace7fc 100644 --- a/app/src/test/java/org/mozilla/fenix/addons/AddonDetailsViewTest.kt +++ b/app/src/test/java/org/mozilla/fenix/addons/AddonDetailsBindingDelegateTest.kt @@ -21,12 +21,12 @@ import org.mozilla.fenix.databinding.FragmentAddOnDetailsBinding import org.mozilla.fenix.helpers.FenixRobolectricTestRunner @RunWith(FenixRobolectricTestRunner::class) -class AddonDetailsViewTest { +class AddonDetailsBindingDelegateTest { private lateinit var view: View private lateinit var binding: FragmentAddOnDetailsBinding private lateinit var interactor: AddonDetailsInteractor - private lateinit var detailsView: AddonDetailsView + private lateinit var detailsBindingDelegate: AddonDetailsBindingDelegate private val baseAddon = Addon( id = "", translatableDescription = mapOf( @@ -41,19 +41,19 @@ class AddonDetailsViewTest { view = binding.root interactor = mockk(relaxed = true) - detailsView = AddonDetailsView(binding, interactor) + detailsBindingDelegate = AddonDetailsBindingDelegate(binding, interactor) } @Test fun `bind addons rating`() { - detailsView.bind( + detailsBindingDelegate.bind( baseAddon.copy( rating = null ) ) assertEquals(0f, binding.ratingView.rating) - detailsView.bind( + detailsBindingDelegate.bind( baseAddon.copy( rating = Addon.Rating( average = 4.3f, @@ -68,7 +68,7 @@ class AddonDetailsViewTest { @Test fun `bind addons website`() { - detailsView.bind( + detailsBindingDelegate.bind( baseAddon.copy( siteUrl = "https://mozilla.org" ) @@ -81,7 +81,7 @@ class AddonDetailsViewTest { @Test fun `bind addons last updated`() { - detailsView.bind(baseAddon) + detailsBindingDelegate.bind(baseAddon) assertEquals("Nov 23, 2020", binding.lastUpdatedText.text) } @@ -93,7 +93,7 @@ class AddonDetailsViewTest { installedState = null ) - detailsView.bind(addon1) + detailsBindingDelegate.bind(addon1) assertEquals("1.0.0", binding.versionText.text) binding.versionText.performLongClick() verify(exactly = 0) { interactor.showUpdaterDialog(addon1) } @@ -106,7 +106,7 @@ class AddonDetailsViewTest { optionsPageUrl = null ) ) - detailsView.bind(addon2) + detailsBindingDelegate.bind(addon2) assertEquals("2.0.0", binding.versionText.text) binding.versionText.performLongClick() verify { interactor.showUpdaterDialog(addon2) } @@ -115,7 +115,7 @@ class AddonDetailsViewTest { @Test fun `bind addons authors`() { val baseAuthor = Addon.Author("", "", "", "") - detailsView.bind( + detailsBindingDelegate.bind( baseAddon.copy( authors = listOf( baseAuthor.copy(name = " Sarah Jane"), @@ -129,7 +129,7 @@ class AddonDetailsViewTest { @Test fun `bind addons details`() { - detailsView.bind(baseAddon) + detailsBindingDelegate.bind(baseAddon) assertEquals( "Some blank addon\nwith a blank line", diff --git a/app/src/test/java/org/mozilla/fenix/collections/CollectionCreationTabListAdapterTest.kt b/app/src/test/java/org/mozilla/fenix/collections/CollectionCreationTabListAdapterTest.kt index 2d75a5565..83a169faa 100644 --- a/app/src/test/java/org/mozilla/fenix/collections/CollectionCreationTabListAdapterTest.kt +++ b/app/src/test/java/org/mozilla/fenix/collections/CollectionCreationTabListAdapterTest.kt @@ -12,7 +12,6 @@ import io.mockk.every import io.mockk.just import io.mockk.mockk import io.mockk.verify -import kotlinx.android.synthetic.main.collection_tab_list_row.* import mozilla.components.support.test.robolectric.testContext import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -20,6 +19,7 @@ import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mozilla.fenix.databinding.CollectionTabListRowBinding import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.home.Tab @@ -67,20 +67,21 @@ class CollectionCreationTabListAdapterTest { val holder = adapter.createViewHolder(FrameLayout(testContext), 0) adapter.bindViewHolder(holder, 0) + val binding = CollectionTabListRowBinding.bind(holder.itemView) - assertEquals("Mozilla", holder.tab_title.text) - assertEquals("mozilla.org", holder.hostname.text) - assertFalse(holder.tab_selected_checkbox.isInvisible) + assertEquals("Mozilla", binding.tabTitle.text) + assertEquals("mozilla.org", binding.hostname.text) + assertFalse(binding.tabSelectedCheckbox.isInvisible) assertTrue(holder.itemView.isClickable) every { interactor.addTabToSelection(mozillaTab) } just Runs every { interactor.removeTabFromSelection(mozillaTab) } just Runs - assertFalse(holder.tab_selected_checkbox.isChecked) + assertFalse(binding.tabSelectedCheckbox.isChecked) - holder.tab_selected_checkbox.isChecked = true + binding.tabSelectedCheckbox.isChecked = true verify { interactor.addTabToSelection(mozillaTab) } - holder.tab_selected_checkbox.isChecked = false + binding.tabSelectedCheckbox.isChecked = false verify { interactor.removeTabFromSelection(mozillaTab) } } @@ -96,10 +97,11 @@ class CollectionCreationTabListAdapterTest { val holder = adapter.createViewHolder(FrameLayout(testContext), 0) adapter.bindViewHolder(holder, 0) + val binding = CollectionTabListRowBinding.bind(holder.itemView) - assertEquals("Mozilla", holder.tab_title.text) - assertEquals("mozilla.org", holder.hostname.text) - assertTrue(holder.tab_selected_checkbox.isInvisible) + assertEquals("Mozilla", binding.tabTitle.text) + assertEquals("mozilla.org", binding.hostname.text) + assertTrue(binding.tabSelectedCheckbox.isInvisible) assertFalse(holder.itemView.isClickable) } diff --git a/app/src/test/java/org/mozilla/fenix/collections/SaveCollectionListAdapterTest.kt b/app/src/test/java/org/mozilla/fenix/collections/SaveCollectionListAdapterTest.kt index ddcff8572..88ea459d4 100644 --- a/app/src/test/java/org/mozilla/fenix/collections/SaveCollectionListAdapterTest.kt +++ b/app/src/test/java/org/mozilla/fenix/collections/SaveCollectionListAdapterTest.kt @@ -11,13 +11,13 @@ import io.mockk.every import io.mockk.just import io.mockk.mockk import io.mockk.verify -import kotlinx.android.synthetic.main.collections_list_item.view.* import mozilla.components.feature.tab.collections.TabCollection import mozilla.components.support.test.robolectric.testContext import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mozilla.fenix.databinding.CollectionsListItemBinding import org.mozilla.fenix.helpers.FenixRobolectricTestRunner @RunWith(FenixRobolectricTestRunner::class) @@ -70,9 +70,10 @@ class SaveCollectionListAdapterTest { val holder = adapter.createViewHolder(parent, 0) adapter.bindViewHolder(holder, 0) + val binding = CollectionsListItemBinding.bind(holder.itemView) - assertEquals("Collection", holder.itemView.collection_item.text) - assertEquals("mozilla.org, firefox.com", holder.itemView.collection_description.text) + assertEquals("Collection", binding.collectionItem.text) + assertEquals("mozilla.org, firefox.com", binding.collectionDescription.text) holder.itemView.performClick() verify { interactor.selectCollection(collection, emptyList()) } diff --git a/app/src/test/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataGroupViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataGroupViewHolderTest.kt index 370110588..5522c48bb 100644 --- a/app/src/test/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataGroupViewHolderTest.kt +++ b/app/src/test/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataGroupViewHolderTest.kt @@ -5,10 +5,8 @@ package org.mozilla.fenix.historymetadata.view import android.view.LayoutInflater -import android.view.View import io.mockk.mockk import io.mockk.verify -import kotlinx.android.synthetic.main.history_metadata_group.view.* import mozilla.components.concept.storage.DocumentType import mozilla.components.concept.storage.HistoryMetadata import mozilla.components.concept.storage.HistoryMetadataKey @@ -17,6 +15,7 @@ import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mozilla.fenix.databinding.HistoryMetadataGroupBinding import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.historymetadata.HistoryMetadataGroup import org.mozilla.fenix.historymetadata.interactor.HistoryMetadataInteractor @@ -24,7 +23,7 @@ import org.mozilla.fenix.historymetadata.interactor.HistoryMetadataInteractor @RunWith(FenixRobolectricTestRunner::class) class HistoryMetadataGroupViewHolderTest { - private lateinit var view: View + private lateinit var binding: HistoryMetadataGroupBinding private lateinit var interactor: HistoryMetadataInteractor private val historyEntry = HistoryMetadata( @@ -42,23 +41,23 @@ class HistoryMetadataGroupViewHolderTest { @Before fun setup() { - view = LayoutInflater.from(testContext).inflate(HistoryMetadataGroupViewHolder.LAYOUT_ID, null) + binding = HistoryMetadataGroupBinding.inflate(LayoutInflater.from(testContext)) interactor = mockk(relaxed = true) } @Test fun `GIVEN a history metadata group on bind THEN set the title text and isActivated state`() { - HistoryMetadataGroupViewHolder(view, interactor).bind(historyGroup) + HistoryMetadataGroupViewHolder(binding.root, interactor).bind(historyGroup) - assertEquals(historyGroup.title, view.history_metadata_group_title.text) - assertEquals(historyGroup.expanded, view.isActivated) + assertEquals(historyGroup.title, binding.historyMetadataGroupTitle.text) + assertEquals(historyGroup.expanded, binding.root.isActivated) } @Test fun `WHEN a history metadata group is clicked THEN interactor is called`() { - HistoryMetadataGroupViewHolder(view, interactor).bind(historyGroup) + HistoryMetadataGroupViewHolder(binding.root, interactor).bind(historyGroup) - view.performClick() + binding.root.performClick() verify { interactor.onToggleHistoryMetadataGroupExpanded(historyGroup) } } diff --git a/app/src/test/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataHeaderViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataHeaderViewHolderTest.kt index cad99bcce..f9b52f2aa 100644 --- a/app/src/test/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataHeaderViewHolderTest.kt +++ b/app/src/test/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataHeaderViewHolderTest.kt @@ -5,34 +5,33 @@ package org.mozilla.fenix.historymetadata.view import android.view.LayoutInflater -import android.view.View import io.mockk.mockk import io.mockk.verify -import kotlinx.android.synthetic.main.history_metadata_header.view.* import mozilla.components.support.test.robolectric.testContext import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mozilla.fenix.databinding.HistoryMetadataHeaderBinding import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.home.sessioncontrol.SessionControlInteractor @RunWith(FenixRobolectricTestRunner::class) class HistoryMetadataHeaderViewHolderTest { - private lateinit var view: View + private lateinit var binding: HistoryMetadataHeaderBinding private lateinit var interactor: SessionControlInteractor @Before fun setup() { - view = LayoutInflater.from(testContext).inflate(HistoryMetadataHeaderViewHolder.LAYOUT_ID, null) + binding = HistoryMetadataHeaderBinding.inflate(LayoutInflater.from(testContext)) interactor = mockk(relaxed = true) } @Test fun `WHEN show all button is clicked THEN interactor is called`() { - HistoryMetadataHeaderViewHolder(view, interactor) + HistoryMetadataHeaderViewHolder(binding.root, interactor) - view.show_all_button.performClick() + binding.showAllButton.performClick() verify { interactor.onHistoryMetadataShowAllClicked() } } diff --git a/app/src/test/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataViewHolderTest.kt index 8c94cc0df..e86431c51 100644 --- a/app/src/test/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataViewHolderTest.kt +++ b/app/src/test/java/org/mozilla/fenix/historymetadata/view/HistoryMetadataViewHolderTest.kt @@ -5,11 +5,9 @@ package org.mozilla.fenix.historymetadata.view import android.view.LayoutInflater -import android.view.View import io.mockk.every import io.mockk.mockk import io.mockk.verify -import kotlinx.android.synthetic.main.history_metadata_list_row.view.* import mozilla.components.browser.icons.BrowserIcons import mozilla.components.browser.icons.IconRequest import mozilla.components.concept.storage.DocumentType @@ -20,13 +18,14 @@ import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mozilla.fenix.databinding.HistoryMetadataListRowBinding import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.home.sessioncontrol.SessionControlInteractor @RunWith(FenixRobolectricTestRunner::class) class HistoryMetadataViewHolderTest { - private lateinit var view: View + private lateinit var binding: HistoryMetadataListRowBinding private lateinit var interactor: SessionControlInteractor private lateinit var icons: BrowserIcons @@ -41,28 +40,28 @@ class HistoryMetadataViewHolderTest { @Before fun setup() { - view = LayoutInflater.from(testContext).inflate(HistoryMetadataViewHolder.LAYOUT_ID, null) + binding = HistoryMetadataListRowBinding.inflate(LayoutInflater.from(testContext)) interactor = mockk(relaxed = true) icons = mockk(relaxed = true) - every { icons.loadIntoView(view.history_metadata_icon, any()) } returns mockk() + every { icons.loadIntoView(binding.historyMetadataIcon, any()) } returns mockk() } @Test fun `GIVEN a history metadata on bind THEN set the title text and load the tab icon`() { - HistoryMetadataViewHolder(view, interactor, icons).bind(historyEntry) + HistoryMetadataViewHolder(binding.root, interactor, icons).bind(historyEntry) - assertEquals(historyEntry.title, view.history_metadata_title.text) + assertEquals(historyEntry.title, binding.historyMetadataTitle.text) - verify { icons.loadIntoView(view.history_metadata_icon, IconRequest(historyEntry.key.url)) } + verify { icons.loadIntoView(binding.historyMetadataIcon, IconRequest(historyEntry.key.url)) } } @Test fun `WHEN a history metadata item is clicked THEN interactor is called`() { - HistoryMetadataViewHolder(view, interactor, icons).bind(historyEntry) + HistoryMetadataViewHolder(binding.root, interactor, icons).bind(historyEntry) - view.performClick() + binding.root.performClick() verify { interactor.onHistoryMetadataItemClicked(historyEntry.key.url, historyEntry.key) } } @@ -78,8 +77,8 @@ class HistoryMetadataViewHolderTest { documentType = DocumentType.Regular ) - HistoryMetadataViewHolder(view, interactor, icons).bind(historyEntryWithoutTitle) + HistoryMetadataViewHolder(binding.root, interactor, icons).bind(historyEntryWithoutTitle) - assertEquals(historyEntry.key.url, view.history_metadata_title.text) + assertEquals(historyEntry.key.url, binding.historyMetadataTitle.text) } } diff --git a/app/src/test/java/org/mozilla/fenix/migration/MigrationStatusAdapterTest.kt b/app/src/test/java/org/mozilla/fenix/migration/MigrationStatusAdapterTest.kt index ca56d9dd8..1dfe88539 100644 --- a/app/src/test/java/org/mozilla/fenix/migration/MigrationStatusAdapterTest.kt +++ b/app/src/test/java/org/mozilla/fenix/migration/MigrationStatusAdapterTest.kt @@ -6,7 +6,6 @@ package org.mozilla.fenix.migration import android.view.View import android.widget.FrameLayout -import kotlinx.android.synthetic.main.migration_list_item.view.* import mozilla.components.support.migration.Migration import mozilla.components.support.migration.MigrationRun import mozilla.components.support.test.robolectric.testContext @@ -14,6 +13,7 @@ import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mozilla.fenix.databinding.MigrationListItemBinding import org.mozilla.fenix.helpers.FenixRobolectricTestRunner @RunWith(FenixRobolectricTestRunner::class) @@ -50,14 +50,16 @@ class MigrationStatusAdapterTest { val holder1 = adapter.createViewHolder(FrameLayout(testContext), 0) val holder2 = adapter.createViewHolder(FrameLayout(testContext), 0) + val binding1 = MigrationListItemBinding.bind(holder1.itemView) + val binding2 = MigrationListItemBinding.bind(holder2.itemView) adapter.bindViewHolder(holder1, 0) adapter.bindViewHolder(holder2, 1) - assertEquals("Settings", holder1.itemView.migration_item_name.text) - assertEquals(View.INVISIBLE, holder1.itemView.migration_status_image.visibility) + assertEquals("Settings", binding1.migrationItemName.text) + assertEquals(View.INVISIBLE, binding1.migrationStatusImage.visibility) - assertEquals("History", holder2.itemView.migration_item_name.text) - assertEquals(View.VISIBLE, holder2.itemView.migration_status_image.visibility) - assertEquals("Migration completed", holder2.itemView.migration_status_image.contentDescription) + assertEquals("History", binding2.migrationItemName.text) + assertEquals(View.VISIBLE, binding2.migrationStatusImage.visibility) + assertEquals("Migration completed", binding2.migrationStatusImage.contentDescription) } } diff --git a/app/src/test/java/org/mozilla/fenix/share/viewholders/AccountDeviceViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/share/viewholders/AccountDeviceViewHolderTest.kt index 4a183f365..ac34a332f 100644 --- a/app/src/test/java/org/mozilla/fenix/share/viewholders/AccountDeviceViewHolderTest.kt +++ b/app/src/test/java/org/mozilla/fenix/share/viewholders/AccountDeviceViewHolderTest.kt @@ -8,7 +8,6 @@ import android.view.LayoutInflater import io.mockk.Called import io.mockk.mockk import io.mockk.verify -import kotlinx.android.synthetic.main.account_share_list_item.view.* import mozilla.components.concept.sync.Device import mozilla.components.concept.sync.DeviceType import mozilla.components.support.test.robolectric.testContext @@ -17,6 +16,7 @@ import org.junit.Assert.assertFalse import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mozilla.fenix.databinding.AccountShareListItemBinding import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.share.ShareToAccountDevicesInteractor import org.mozilla.fenix.share.listadapters.SyncShareOption @@ -34,6 +34,7 @@ class AccountDeviceViewHolderTest { subscriptionExpired = false, subscription = null ) + private lateinit var binding: AccountShareListItemBinding private lateinit var viewHolder: AccountDeviceViewHolder private lateinit var interactor: ShareToAccountDevicesInteractor @@ -41,14 +42,14 @@ class AccountDeviceViewHolderTest { fun setup() { interactor = mockk(relaxUnitFun = true) - val view = LayoutInflater.from(testContext).inflate(AccountDeviceViewHolder.LAYOUT_ID, null) - viewHolder = AccountDeviceViewHolder(view, interactor) + binding = AccountShareListItemBinding.inflate(LayoutInflater.from(testContext)) + viewHolder = AccountDeviceViewHolder(binding.root, interactor) } @Test fun `bind SignIn option`() { viewHolder.bind(SyncShareOption.SignIn) - assertEquals("Sign in to Sync", viewHolder.itemView.deviceName.text) + assertEquals("Sign in to Sync", binding.deviceName.text) viewHolder.itemView.performClick() verify { interactor.onSignIn() } @@ -58,7 +59,7 @@ class AccountDeviceViewHolderTest { @Test fun `bind Reconnect option`() { viewHolder.bind(SyncShareOption.Reconnect) - assertEquals("Reconnect to Sync", viewHolder.itemView.deviceName.text) + assertEquals("Reconnect to Sync", binding.deviceName.text) viewHolder.itemView.performClick() verify { interactor.onReauth() } @@ -68,7 +69,7 @@ class AccountDeviceViewHolderTest { @Test fun `bind Offline option`() { viewHolder.bind(SyncShareOption.Offline) - assertEquals("Offline", viewHolder.itemView.deviceName.text) + assertEquals("Offline", binding.deviceName.text) viewHolder.itemView.performClick() verify { interactor wasNot Called } @@ -78,7 +79,7 @@ class AccountDeviceViewHolderTest { @Test fun `bind AddNewDevice option`() { viewHolder.bind(SyncShareOption.AddNewDevice) - assertEquals("Connect another device", viewHolder.itemView.deviceName.text) + assertEquals("Connect another device", binding.deviceName.text) viewHolder.itemView.performClick() verify { interactor.onAddNewDevice() } @@ -89,7 +90,7 @@ class AccountDeviceViewHolderTest { fun `bind SendAll option`() { val devices = listOf(mockk()) viewHolder.bind(SyncShareOption.SendAll(devices)) - assertEquals("Send to all devices", viewHolder.itemView.deviceName.text) + assertEquals("Send to all devices", binding.deviceName.text) viewHolder.itemView.performClick() verify { interactor.onShareToAllDevices(devices) } @@ -103,7 +104,7 @@ class AccountDeviceViewHolderTest { displayName = "Mobile" ) viewHolder.bind(SyncShareOption.SingleDevice(device)) - assertEquals("Mobile", viewHolder.itemView.deviceName.text) + assertEquals("Mobile", binding.deviceName.text) viewHolder.itemView.performClick() verify { interactor.onShareToDevice(device) } @@ -117,7 +118,7 @@ class AccountDeviceViewHolderTest { displayName = "Desktop" ) viewHolder.bind(SyncShareOption.SingleDevice(device)) - assertEquals("Desktop", viewHolder.itemView.deviceName.text) + assertEquals("Desktop", binding.deviceName.text) viewHolder.itemView.performClick() verify { interactor.onShareToDevice(device) } diff --git a/app/src/test/java/org/mozilla/fenix/share/viewholders/AppViewHolderTest.kt b/app/src/test/java/org/mozilla/fenix/share/viewholders/AppViewHolderTest.kt index f43081830..39b94b9fe 100644 --- a/app/src/test/java/org/mozilla/fenix/share/viewholders/AppViewHolderTest.kt +++ b/app/src/test/java/org/mozilla/fenix/share/viewholders/AppViewHolderTest.kt @@ -9,13 +9,13 @@ import androidx.appcompat.content.res.AppCompatResources.getDrawable import io.mockk.Called import io.mockk.mockk import io.mockk.verify -import kotlinx.android.synthetic.main.app_share_list_item.view.* import mozilla.components.support.test.robolectric.testContext import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mozilla.fenix.R +import org.mozilla.fenix.databinding.AppShareListItemBinding import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.share.ShareToAppsInteractor import org.mozilla.fenix.share.listadapters.AppShareOption @@ -23,6 +23,7 @@ import org.mozilla.fenix.share.listadapters.AppShareOption @RunWith(FenixRobolectricTestRunner::class) class AppViewHolderTest { + private lateinit var binding: AppShareListItemBinding private lateinit var viewHolder: AppViewHolder private lateinit var interactor: ShareToAppsInteractor @@ -30,8 +31,8 @@ class AppViewHolderTest { fun setup() { interactor = mockk(relaxUnitFun = true) - val view = LayoutInflater.from(testContext).inflate(AppViewHolder.LAYOUT_ID, null) - viewHolder = AppViewHolder(view, interactor) + binding = AppShareListItemBinding.inflate(LayoutInflater.from(testContext)) + viewHolder = AppViewHolder(binding.root, interactor) } @Test @@ -44,8 +45,8 @@ class AppViewHolderTest { ) viewHolder.bind(app) - assertEquals("Pocket", viewHolder.itemView.appName.text) - assertEquals(app.icon, viewHolder.itemView.appIcon.drawable) + assertEquals("Pocket", binding.appName.text) + assertEquals(app.icon, binding.appIcon.drawable) } @Test