mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-03 23:15:31 +00:00
[fenix] For https://github.com/mozilla-mobile/fenix/issues/12287: Address review comments
This commit is contained in:
parent
1a7ba25347
commit
4836894fd0
@ -6,13 +6,21 @@ package org.mozilla.fenix.tabtray
|
||||
|
||||
import android.view.View
|
||||
import androidx.fragment.app.FragmentManager.findFragment
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.ConcatAdapter
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import mozilla.components.browser.storage.sync.SyncedDeviceTabs
|
||||
import mozilla.components.feature.syncedtabs.view.SyncedTabsView
|
||||
import mozilla.components.lib.state.ext.flowScoped
|
||||
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged
|
||||
import org.mozilla.fenix.sync.ListenerDelegate
|
||||
import org.mozilla.fenix.sync.SyncedTabsAdapter
|
||||
import org.mozilla.fenix.sync.ext.toAdapterList
|
||||
@ -20,8 +28,12 @@ import org.mozilla.fenix.sync.ext.toAdapterItem
|
||||
import org.mozilla.fenix.sync.ext.toStringRes
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class SyncedTabsController(
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
private val view: View,
|
||||
store: TabTrayDialogFragmentStore,
|
||||
private val concatAdapter: ConcatAdapter,
|
||||
coroutineContext: CoroutineContext = Dispatchers.Main
|
||||
) : SyncedTabsView {
|
||||
override var listener: SyncedTabsView.Listener? = null
|
||||
@ -30,6 +42,24 @@ class SyncedTabsController(
|
||||
|
||||
private val scope: CoroutineScope = CoroutineScope(coroutineContext)
|
||||
|
||||
init {
|
||||
store.flowScoped(lifecycleOwner) { flow ->
|
||||
flow.map { it.mode }
|
||||
.ifChanged()
|
||||
.drop(1)
|
||||
.collect { mode ->
|
||||
when (mode) {
|
||||
is TabTrayDialogFragmentState.Mode.Normal -> {
|
||||
concatAdapter.addAdapter(0, adapter)
|
||||
}
|
||||
is TabTrayDialogFragmentState.Mode.MultiSelect -> {
|
||||
concatAdapter.removeAdapter(adapter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun displaySyncedTabs(syncedTabs: List<SyncedDeviceTabs>) {
|
||||
scope.launch {
|
||||
val tabsList = listOf(SyncedTabsAdapter.AdapterItem.Title) + syncedTabs.toAdapterList()
|
||||
|
@ -192,6 +192,7 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), UserInteractionHandler
|
||||
showAddNewCollectionDialog = ::showAddNewCollectionDialog
|
||||
)
|
||||
),
|
||||
store = tabTrayDialogStore,
|
||||
isPrivate = isPrivate,
|
||||
startingInLandscape = requireContext().resources.configuration.orientation ==
|
||||
Configuration.ORIENTATION_LANDSCAPE,
|
||||
|
@ -60,6 +60,7 @@ class TabTrayView(
|
||||
private val container: ViewGroup,
|
||||
private val tabsAdapter: FenixTabsAdapter,
|
||||
private val interactor: TabTrayInteractor,
|
||||
store: TabTrayDialogFragmentStore,
|
||||
isPrivate: Boolean,
|
||||
startingInLandscape: Boolean,
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
@ -78,13 +79,14 @@ class TabTrayView(
|
||||
|
||||
private val behavior = BottomSheetBehavior.from(view.tab_wrapper)
|
||||
|
||||
private val concatAdapter = ConcatAdapter(tabsAdapter)
|
||||
private val tabTrayItemMenu: TabTrayItemMenu
|
||||
private var menu: BrowserMenu? = null
|
||||
|
||||
private var tabsTouchHelper: TabsTouchHelper
|
||||
private val collectionsButtonAdapter = SaveToCollectionsButtonAdapter(interactor, isPrivate)
|
||||
|
||||
private val syncedTabsController = SyncedTabsController(view)
|
||||
private val syncedTabsController = SyncedTabsController(lifecycleOwner, view, store, concatAdapter)
|
||||
private val syncedTabsFeature = ViewBoundFeatureWrapper<SyncedTabsFeature>()
|
||||
|
||||
private var hasLoaded = false
|
||||
@ -160,7 +162,6 @@ class TabTrayView(
|
||||
)
|
||||
}
|
||||
|
||||
val concatAdapter = ConcatAdapter(tabsAdapter)
|
||||
view.tabsTray.apply {
|
||||
layoutManager = LinearLayoutManager(container.context).apply {
|
||||
reverseLayout = true
|
||||
|
@ -1,4 +1,7 @@
|
||||
<?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/. -->
|
||||
|
||||
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="275"
|
||||
|
@ -6,9 +6,10 @@
|
||||
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:paddingTop="6dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="?android:attr/selectableItemBackground">
|
||||
|
||||
<TextView
|
||||
@ -17,7 +18,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="72dp"
|
||||
android:layout_marginEnd="48dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?primaryText"
|
||||
|
@ -23,6 +23,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="60dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
app:srcCompat="@drawable/mozac_ic_refresh"
|
||||
app:tint="?primaryText" />
|
||||
|
||||
|
@ -2,31 +2,70 @@ package org.mozilla.fenix.tabtray
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LifecycleRegistry
|
||||
import androidx.recyclerview.widget.ConcatAdapter
|
||||
import io.mockk.Called
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import mozilla.components.browser.storage.sync.SyncedDeviceTabs
|
||||
import mozilla.components.feature.syncedtabs.view.SyncedTabsView.ErrorType
|
||||
import mozilla.components.support.test.ext.joinBlocking
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import mozilla.components.support.test.rule.MainCoroutineRule
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.sync.SyncedTabsViewHolder
|
||||
import org.mozilla.fenix.tabtray.TabTrayDialogFragmentAction.EnterMultiSelectMode
|
||||
import org.mozilla.fenix.tabtray.TabTrayDialogFragmentAction.ExitMultiSelectMode
|
||||
import org.mozilla.fenix.tabtray.TabTrayDialogFragmentState.Mode
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class SyncedTabsControllerTest {
|
||||
|
||||
private val testDispatcher = TestCoroutineDispatcher()
|
||||
@get:Rule
|
||||
val coroutinesTestRule = MainCoroutineRule(testDispatcher)
|
||||
|
||||
private lateinit var view: View
|
||||
private lateinit var controller: SyncedTabsController
|
||||
private lateinit var lifecycleOwner: LifecycleOwner
|
||||
private lateinit var lifecycle: LifecycleRegistry
|
||||
private lateinit var concatAdapter: ConcatAdapter
|
||||
private lateinit var store: TabTrayDialogFragmentStore
|
||||
|
||||
@Before
|
||||
fun setup() = runBlockingTest {
|
||||
lifecycleOwner = mockk()
|
||||
lifecycle = LifecycleRegistry(lifecycleOwner)
|
||||
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START)
|
||||
every { lifecycleOwner.lifecycle } returns lifecycle
|
||||
|
||||
concatAdapter = mockk()
|
||||
every { concatAdapter.addAdapter(any(), any()) } returns true
|
||||
every { concatAdapter.removeAdapter(any()) } returns true
|
||||
|
||||
store = TabTrayDialogFragmentStore(
|
||||
initialState = TabTrayDialogFragmentState(
|
||||
mode = Mode.Normal,
|
||||
browserState = mockk(relaxed = true)
|
||||
)
|
||||
)
|
||||
|
||||
view = LayoutInflater.from(testContext).inflate(R.layout.about_list_item, null)
|
||||
controller = SyncedTabsController(view, coroutineContext)
|
||||
controller =
|
||||
SyncedTabsController(lifecycleOwner, view, store, concatAdapter, coroutineContext)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -75,4 +114,20 @@ class SyncedTabsControllerTest {
|
||||
controller.adapter.getItemViewType(0)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `do nothing on init, drop first event`() {
|
||||
verify { concatAdapter wasNot Called }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `concatAdapter updated on mode changes`() = testDispatcher.runBlockingTest {
|
||||
store.dispatch(EnterMultiSelectMode).joinBlocking()
|
||||
|
||||
verify { concatAdapter.removeAdapter(any()) }
|
||||
|
||||
store.dispatch(ExitMultiSelectMode).joinBlocking()
|
||||
|
||||
verify { concatAdapter.addAdapter(0, any()) }
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user