From 9373e7fcf4ec2897b55f5e655e123204a6280347 Mon Sep 17 00:00:00 2001 From: Mihai Branescu Date: Thu, 16 Jul 2020 21:39:31 +0300 Subject: [PATCH] For #12201 - forced callbacks to be on the main thread (#12543) --- .../mozilla/fenix/sync/SyncedTabsLayout.kt | 66 +++++++++++-------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsLayout.kt b/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsLayout.kt index ba3db15fb..c5bbf4d4e 100644 --- a/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsLayout.kt +++ b/app/src/main/java/org/mozilla/fenix/sync/SyncedTabsLayout.kt @@ -10,6 +10,10 @@ import android.view.View import android.widget.FrameLayout import androidx.recyclerview.widget.LinearLayoutManager import kotlinx.android.synthetic.main.component_sync_tabs.view.* +import kotlinx.coroutines.launch +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.cancel import mozilla.components.browser.storage.sync.SyncedDeviceTabs import mozilla.components.feature.syncedtabs.view.SyncedTabsView import org.mozilla.fenix.R @@ -23,6 +27,7 @@ class SyncedTabsLayout @JvmOverloads constructor( override var listener: SyncedTabsView.Listener? = null private val adapter = SyncedTabsAdapter { listener?.onTabClicked(it) } + private val coroutineScope = CoroutineScope(Dispatchers.Main) init { inflate(getContext(), R.layout.component_sync_tabs, this) @@ -34,42 +39,46 @@ class SyncedTabsLayout @JvmOverloads constructor( } override fun onError(error: SyncedTabsView.ErrorType) { - // We may still be displaying a "loading" spinner, hide it. - stopLoading() + coroutineScope.launch { + // We may still be displaying a "loading" spinner, hide it. + stopLoading() - val stringResId = when (error) { - SyncedTabsView.ErrorType.MULTIPLE_DEVICES_UNAVAILABLE -> R.string.synced_tabs_connect_another_device - SyncedTabsView.ErrorType.SYNC_ENGINE_UNAVAILABLE -> R.string.synced_tabs_enable_tab_syncing - SyncedTabsView.ErrorType.SYNC_UNAVAILABLE -> R.string.synced_tabs_connect_to_sync_account - SyncedTabsView.ErrorType.SYNC_NEEDS_REAUTHENTICATION -> R.string.synced_tabs_reauth - SyncedTabsView.ErrorType.NO_TABS_AVAILABLE -> R.string.synced_tabs_no_tabs + val stringResId = when (error) { + SyncedTabsView.ErrorType.MULTIPLE_DEVICES_UNAVAILABLE -> R.string.synced_tabs_connect_another_device + SyncedTabsView.ErrorType.SYNC_ENGINE_UNAVAILABLE -> R.string.synced_tabs_enable_tab_syncing + SyncedTabsView.ErrorType.SYNC_UNAVAILABLE -> R.string.synced_tabs_connect_to_sync_account + SyncedTabsView.ErrorType.SYNC_NEEDS_REAUTHENTICATION -> R.string.synced_tabs_reauth + SyncedTabsView.ErrorType.NO_TABS_AVAILABLE -> R.string.synced_tabs_no_tabs + } + + sync_tabs_status.text = context.getText(stringResId) + + synced_tabs_list.visibility = View.GONE + sync_tabs_status.visibility = View.VISIBLE + + synced_tabs_pull_to_refresh.isEnabled = pullToRefreshEnableState(error) } - - sync_tabs_status.text = context.getText(stringResId) - - synced_tabs_list.visibility = View.GONE - sync_tabs_status.visibility = View.VISIBLE - - synced_tabs_pull_to_refresh.isEnabled = pullToRefreshEnableState(error) } override fun displaySyncedTabs(syncedTabs: List) { - synced_tabs_list.visibility = View.VISIBLE - sync_tabs_status.visibility = View.GONE + coroutineScope.launch { + synced_tabs_list.visibility = View.VISIBLE + sync_tabs_status.visibility = View.GONE - val allDeviceTabs = emptyList().toMutableList() + val allDeviceTabs = emptyList().toMutableList() - syncedTabs.forEach { (device, tabs) -> - if (tabs.isEmpty()) { - return@forEach + syncedTabs.forEach { (device, tabs) -> + if (tabs.isEmpty()) { + return@forEach + } + + val deviceTabs = tabs.map { SyncedTabsAdapter.AdapterItem.Tab(it) } + + allDeviceTabs += listOf(SyncedTabsAdapter.AdapterItem.Device(device)) + deviceTabs } - val deviceTabs = tabs.map { SyncedTabsAdapter.AdapterItem.Tab(it) } - - allDeviceTabs += listOf(SyncedTabsAdapter.AdapterItem.Device(device)) + deviceTabs + adapter.submitList(allDeviceTabs) } - - adapter.submitList(allDeviceTabs) } override fun startLoading() { @@ -83,6 +92,11 @@ class SyncedTabsLayout @JvmOverloads constructor( 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