Issue #19112: Remove old Synced Tabs code

upstream-sync
Jonathan Almeida 3 years ago committed by Jonathan Almeida
parent dc11c334b6
commit bf3f81d271

@ -20,7 +20,6 @@ import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.FeatureFlags
import org.mozilla.fenix.IntentReceiverActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components

@ -9,7 +9,6 @@ import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mozilla.fenix.FeatureFlags
import org.mozilla.fenix.helpers.AndroidAssetDispatcher
import org.mozilla.fenix.helpers.HomeActivityTestRule
import org.mozilla.fenix.ui.robots.homeScreen

@ -18,7 +18,6 @@ enum class BrowserDirection(@IdRes val fragmentId: Int) {
FromHome(R.id.homeFragment),
FromSearchDialog(R.id.searchDialogFragment),
FromSettings(R.id.settingsFragment),
FromSyncedTabs(R.id.syncedTabsFragment),
FromBookmarks(R.id.bookmarkFragment),
FromHistory(R.id.historyFragment),
FromTrackingProtectionExceptions(R.id.trackingProtectionExceptionsFragment),

@ -111,7 +111,6 @@ import org.mozilla.fenix.settings.logins.fragment.SavedLoginsAuthFragmentDirecti
import org.mozilla.fenix.settings.search.AddSearchEngineFragmentDirections
import org.mozilla.fenix.settings.search.EditCustomSearchEngineFragmentDirections
import org.mozilla.fenix.share.AddNewDeviceFragmentDirections
import org.mozilla.fenix.sync.SyncedTabsFragmentDirections
import org.mozilla.fenix.tabstray.TabsTrayFragment
import org.mozilla.fenix.tabstray.TabsTrayFragmentDirections
import org.mozilla.fenix.theme.DefaultThemeManager
@ -786,8 +785,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
SearchDialogFragmentDirections.actionGlobalBrowser(customTabSessionId)
BrowserDirection.FromSettings ->
SettingsFragmentDirections.actionGlobalBrowser(customTabSessionId)
BrowserDirection.FromSyncedTabs ->
SyncedTabsFragmentDirections.actionGlobalBrowser(customTabSessionId)
BrowserDirection.FromBookmarks ->
BookmarkFragmentDirections.actionGlobalBrowser(customTabSessionId)
BrowserDirection.FromHistory ->

@ -219,12 +219,6 @@ class DefaultBrowserToolbarMenuController(
val directions = BrowserFragmentDirections.actionBrowserFragmentToSettingsFragment()
navController.nav(R.id.browserFragment, directions)
}
is ToolbarMenu.Item.SyncedTabs -> browserAnimator.captureEngineViewAndDrawStatically {
navController.nav(
R.id.browserFragment,
BrowserFragmentDirections.actionBrowserFragmentToSyncedTabsFragment()
)
}
is ToolbarMenu.Item.SyncAccount -> {
val directions = if (item.signedIn) {
BrowserFragmentDirections.actionGlobalAccountSettingsFragment()
@ -396,7 +390,6 @@ class DefaultBrowserToolbarMenuController(
is ToolbarMenu.Item.SaveToCollection -> Event.BrowserMenuItemTapped.Item.SAVE_TO_COLLECTION
is ToolbarMenu.Item.AddToTopSites -> Event.BrowserMenuItemTapped.Item.ADD_TO_TOP_SITES
is ToolbarMenu.Item.AddToHomeScreen -> Event.BrowserMenuItemTapped.Item.ADD_TO_HOMESCREEN
is ToolbarMenu.Item.SyncedTabs -> Event.BrowserMenuItemTapped.Item.SYNC_TABS
is ToolbarMenu.Item.SyncAccount -> Event.BrowserMenuItemTapped.Item.SYNC_ACCOUNT
is ToolbarMenu.Item.Bookmark -> Event.BrowserMenuItemTapped.Item.BOOKMARK
is ToolbarMenu.Item.AddonsManager -> Event.BrowserMenuItemTapped.Item.ADDONS_MANAGER

@ -332,14 +332,6 @@ open class DefaultToolbarMenu(
onItemTapped.invoke(ToolbarMenu.Item.Quit)
}
val syncedTabsItem = BrowserMenuImageText(
context.getString(R.string.synced_tabs),
R.drawable.ic_synced_tabs,
primaryTextColor()
) {
onItemTapped.invoke(ToolbarMenu.Item.SyncedTabs)
}
private fun getSyncItemTitle(): String {
val authenticatedAccount = accountManager.authenticatedAccount
val email = accountManager.accountProfileEmail

@ -22,7 +22,6 @@ interface ToolbarMenu {
object AddToTopSites : Item()
object InstallPwaToHomeScreen : Item()
object AddToHomeScreen : Item()
object SyncedTabs : Item()
data class SyncAccount(val signedIn: Boolean) : Item()
object AddonsManager : Item()
object Quit : Item()

@ -786,13 +786,6 @@ class HomeFragment : Fragment() {
)
requireComponents.analytics.metrics.track(Event.HomeMenuSettingsItemClicked)
}
HomeMenu.Item.SyncTabs -> {
hideOnboardingIfNeeded()
nav(
R.id.homeFragment,
HomeFragmentDirections.actionGlobalSyncedTabsFragment()
)
}
is HomeMenu.Item.SyncAccount -> {
hideOnboardingIfNeeded()
val directions = if (it.signedIn) {

@ -45,7 +45,6 @@ class HomeMenu(
object History : Item()
object Downloads : Item()
object Extensions : Item()
object SyncTabs : Item()
data class SyncAccount(val signedIn: Boolean) : Item()
object WhatsNew : Item()
object Help : Item()
@ -91,14 +90,6 @@ class HomeMenu(
}
}
val syncedTabsItem = BrowserMenuImageText(
context.getString(R.string.synced_tabs),
R.drawable.ic_synced_tabs,
primaryTextColor
) {
onItemTapped.invoke(Item.SyncTabs)
}
private fun getSyncItemTitle(): String {
val authenticatedAccount = accountManager.authenticatedAccount
val email = accountManager.accountProfileEmail
@ -110,7 +101,7 @@ class HomeMenu(
}
}
val syncSignInMenuItem = BrowserMenuImageText(
private val syncSignInMenuItem = BrowserMenuImageText(
getSyncItemTitle(),
R.drawable.ic_synced_tabs,
primaryTextColor

@ -1,103 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.sync
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.component_sync_tabs.view.*
import kotlinx.android.synthetic.main.fragment_synced_tabs.*
import kotlinx.android.synthetic.main.sync_tabs_error_row.view.*
import mozilla.components.browser.storage.sync.Tab
import mozilla.components.feature.syncedtabs.SyncedTabsFeature
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.library.LibraryPageFragment
import org.mozilla.fenix.theme.ThemeManager
class SyncedTabsFragment : LibraryPageFragment<Tab>() {
private val syncedTabsFeature = ViewBoundFeatureWrapper<SyncedTabsFeature>()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_synced_tabs, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val backgroundServices = requireContext().components.backgroundServices
/*
* Needed because the synced tabs error layout is also used in tabs tray where there is no private theme.
* See https://github.com/mozilla-mobile/fenix/issues/15061
*/
setProperErrorColor(view.synced_tabs_list as RecyclerView)
syncedTabsFeature.set(
feature = SyncedTabsFeature(
context = requireContext(),
storage = backgroundServices.syncedTabsStorage,
accountManager = backgroundServices.accountManager,
view = synced_tabs_layout,
lifecycleOwner = this.viewLifecycleOwner,
onTabClicked = ::handleTabClicked
),
owner = this,
view = view
)
}
private fun setProperErrorColor(syncedTabsList: RecyclerView) {
syncedTabsList.addOnChildAttachStateChangeListener(
object : RecyclerView.OnChildAttachStateChangeListener {
override fun onChildViewAttachedToWindow(view: View) {
val errorView = view.sync_tabs_error_description
val primaryText = ContextCompat.getColor(
view.context,
ThemeManager.resolveAttribute(R.attr.primaryText, view.context)
)
errorView?.let {
it.setTextColor(primaryText)
syncedTabsList.removeOnChildAttachStateChangeListener(
this
)
}
}
override fun onChildViewDetachedFromWindow(view: View) {
// do nothing
}
}
)
}
override fun onResume() {
super.onResume()
showToolbar(getString(R.string.library_synced_tabs))
}
private fun handleTabClicked(tab: Tab) {
(activity as HomeActivity).openToBrowserAndLoad(
searchTermOrURL = tab.active().url,
newTab = true,
from = BrowserDirection.FromSyncedTabs
)
}
override val selectedItems: Set<Tab>
get() = emptySet()
}

@ -1,124 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.sync
import android.content.Context
import android.util.AttributeSet
import android.widget.FrameLayout
import androidx.fragment.app.findFragment
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.component_sync_tabs.view.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import mozilla.components.browser.storage.sync.SyncedDeviceTabs
import mozilla.components.browser.storage.sync.Tab
import mozilla.components.feature.syncedtabs.view.SyncedTabsView
import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.sync.ext.toAdapterItem
import org.mozilla.fenix.sync.ext.toStringRes
import java.lang.IllegalStateException
class SyncedTabsLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr), SyncedTabsView {
override var listener: SyncedTabsView.Listener? = null
private val metrics = context.components.analytics.metrics
private val adapter = SyncedTabsAdapter(ListenerDelegate(metrics) { listener })
private val coroutineScope = CoroutineScope(Dispatchers.Main)
init {
inflate(getContext(), R.layout.component_sync_tabs, this)
synced_tabs_list.layoutManager = LinearLayoutManager(context)
synced_tabs_list.adapter = adapter
synced_tabs_pull_to_refresh.setOnRefreshListener { listener?.onRefresh() }
}
override fun onError(error: SyncedTabsView.ErrorType) {
coroutineScope.launch {
// We may still be displaying a "loading" spinner, hide it.
stopLoading()
val navController: NavController? = try {
findFragment<SyncedTabsFragment>().findNavController()
} catch (exception: IllegalStateException) {
null
}
val descriptionResId = error.toStringRes()
val errorItem = error.toAdapterItem(descriptionResId, navController)
val errorList: List<SyncedTabsAdapter.AdapterItem> = listOf(errorItem)
adapter.submitList(errorList)
synced_tabs_pull_to_refresh.isEnabled = pullToRefreshEnableState(error)
}
}
override fun displaySyncedTabs(syncedTabs: List<SyncedDeviceTabs>) {
coroutineScope.launch {
adapter.updateData(syncedTabs)
}
}
override fun startLoading() {
synced_tabs_pull_to_refresh.isRefreshing = true
}
override fun stopLoading() {
synced_tabs_pull_to_refresh.isRefreshing = false
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
coroutineScope.cancel()
}
companion object {
internal fun pullToRefreshEnableState(error: SyncedTabsView.ErrorType) = when (error) {
// Disable "pull-to-refresh" when we clearly can't sync tabs, and user needs to take an
// action within the app.
SyncedTabsView.ErrorType.SYNC_UNAVAILABLE,
SyncedTabsView.ErrorType.SYNC_NEEDS_REAUTHENTICATION -> false
// Enable "pull-to-refresh" when an external event (e.g. connecting a desktop client,
// or enabling tabs sync, or connecting to a network) may resolve our problem.
SyncedTabsView.ErrorType.SYNC_ENGINE_UNAVAILABLE,
SyncedTabsView.ErrorType.MULTIPLE_DEVICES_UNAVAILABLE,
SyncedTabsView.ErrorType.NO_TABS_AVAILABLE -> true
}
}
}
/**
* We have to do this weird daisy-chaining of callbacks because the listener is nullable and
* when we get a null reference, we never get a new binding to the non-null listener.
*/
class ListenerDelegate(
private val metrics: MetricController,
private val listener: (() -> SyncedTabsView.Listener?)
) : SyncedTabsView.Listener {
override fun onRefresh() {
listener.invoke()?.onRefresh()
}
override fun onTabClicked(tab: Tab) {
listener.invoke()?.onTabClicked(tab)
metrics.track(Event.SyncedTabOpened)
}
}

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/synced_tabs_wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/sync_tabs_progress_bar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:indeterminate="true"
android:layout_width="match_parent"
android:layout_height="8dp"
android:translationY="-3dp"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/synced_tabs_pull_to_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/synced_tabs_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/sync_tabs_list_item"/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<org.mozilla.fenix.sync.SyncedTabsLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/synced_tabs_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

@ -57,9 +57,6 @@
<action
android:id="@+id/action_global_settingsFragment"
app:destination="@id/settingsFragment" />
<action
android:id="@+id/action_global_syncedTabsFragment"
app:destination="@id/syncedTabsFragment" />
<action
android:id="@+id/action_global_privateBrowsingFragment"
app:destination="@id/privateBrowsingFragment" />
@ -196,9 +193,6 @@
android:name="activeSessionId"
app:argType="string"
app:nullable="true" />
<action
android:id="@+id/action_browserFragment_to_syncedTabsFragment"
app:destination="@id/syncedTabsFragment" />
<action
android:id="@+id/action_browserFragment_to_settingsFragment"
app:destination="@id/settingsFragment" />
@ -357,12 +351,6 @@
app:popUpToInclusive="true" />
</fragment>
<fragment
android:id="@+id/syncedTabsFragment"
android:name="org.mozilla.fenix.sync.SyncedTabsFragment"
android:label="@string/synced_tabs"
tools:layout="@layout/fragment_synced_tabs" />
<fragment
android:id="@+id/loginExceptionsFragment"
android:name="org.mozilla.fenix.exceptions.login.LoginExceptionsFragment"

@ -1,31 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.sync
import io.mockk.mockk
import io.mockk.verify
import mozilla.components.feature.syncedtabs.view.SyncedTabsView
import org.junit.Test
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController
class ListenerDelegateTest {
@Test
fun `delegate invokes nullable listener`() {
val listener: SyncedTabsView.Listener? = mockk(relaxed = true)
val metrics: MetricController = mockk(relaxed = true)
val delegate = ListenerDelegate(metrics) { listener }
delegate.onRefresh()
verify { listener?.onRefresh() }
delegate.onTabClicked(mockk())
verify { listener?.onTabClicked(any()) }
verify { metrics.track(Event.SyncedTabOpened) }
}
}

@ -1,22 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.sync
import mozilla.components.feature.syncedtabs.view.SyncedTabsView.ErrorType
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
class SyncedTabsLayoutTest {
@Test
fun `pull to refresh state`() {
assertTrue(SyncedTabsLayout.pullToRefreshEnableState(ErrorType.MULTIPLE_DEVICES_UNAVAILABLE))
assertTrue(SyncedTabsLayout.pullToRefreshEnableState(ErrorType.SYNC_ENGINE_UNAVAILABLE))
assertTrue(SyncedTabsLayout.pullToRefreshEnableState(ErrorType.NO_TABS_AVAILABLE))
assertFalse(SyncedTabsLayout.pullToRefreshEnableState(ErrorType.SYNC_NEEDS_REAUTHENTICATION))
assertFalse(SyncedTabsLayout.pullToRefreshEnableState(ErrorType.SYNC_UNAVAILABLE))
}
}
Loading…
Cancel
Save