1
0
Fork 0

For #10925: Fix breaking APIs in tabs tray

master
Jonathan Almeida 2020-07-21 03:13:09 -04:00 committed by Jonathan Almeida
parent 8c1d3dc827
commit d15b8381a6
7 changed files with 50 additions and 55 deletions

View File

@ -28,7 +28,6 @@ import androidx.navigation.NavDirections
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.NavigationUI import androidx.navigation.ui.NavigationUI
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_home.* import kotlinx.android.synthetic.main.activity_home.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -41,10 +40,7 @@ import mozilla.components.browser.session.SessionManager
import mozilla.components.browser.state.state.SessionState import mozilla.components.browser.state.state.SessionState
import mozilla.components.browser.state.state.WebExtensionState import mozilla.components.browser.state.state.WebExtensionState
import mozilla.components.browser.state.store.BrowserStore import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.browser.tabstray.BrowserTabsTray
import mozilla.components.browser.thumbnails.loader.ThumbnailLoader
import mozilla.components.concept.engine.EngineView import mozilla.components.concept.engine.EngineView
import mozilla.components.concept.tabstray.TabsTray
import mozilla.components.feature.contextmenu.DefaultSelectionActionDelegate import mozilla.components.feature.contextmenu.DefaultSelectionActionDelegate
import mozilla.components.feature.search.BrowserStoreSearchAdapter import mozilla.components.feature.search.BrowserStoreSearchAdapter
import mozilla.components.feature.search.SearchAdapter import mozilla.components.feature.search.SearchAdapter
@ -97,7 +93,6 @@ import org.mozilla.fenix.settings.search.AddSearchEngineFragmentDirections
import org.mozilla.fenix.settings.search.EditCustomSearchEngineFragmentDirections import org.mozilla.fenix.settings.search.EditCustomSearchEngineFragmentDirections
import org.mozilla.fenix.share.AddNewDeviceFragmentDirections import org.mozilla.fenix.share.AddNewDeviceFragmentDirections
import org.mozilla.fenix.sync.SyncedTabsFragmentDirections import org.mozilla.fenix.sync.SyncedTabsFragmentDirections
import org.mozilla.fenix.tabtray.FenixTabsAdapter
import org.mozilla.fenix.tabtray.TabTrayDialogFragment import org.mozilla.fenix.tabtray.TabTrayDialogFragment
import org.mozilla.fenix.theme.DefaultThemeManager import org.mozilla.fenix.theme.DefaultThemeManager
import org.mozilla.fenix.theme.ThemeManager import org.mozilla.fenix.theme.ThemeManager
@ -315,17 +310,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
actionSorter = ::actionSorter actionSorter = ::actionSorter
) )
}.asView() }.asView()
TabsTray::class.java.name -> {
val layout = LinearLayoutManager(context).apply {
reverseLayout = true
stackFromEnd = true
}
val thumbnailLoader = ThumbnailLoader(components.core.thumbnailStorage)
val adapter = FenixTabsAdapter(context, thumbnailLoader)
BrowserTabsTray(context, attrs, 0, adapter, layout)
}
else -> super.onCreateView(parent, name, context, attrs) else -> super.onCreateView(parent, name, context, attrs)
} }

View File

@ -16,7 +16,7 @@ class FenixTabsAdapter(
context: Context, context: Context,
imageLoader: ImageLoader imageLoader: ImageLoader
) : TabsAdapter( ) : TabsAdapter(
viewHolderProvider = { parentView, _ -> viewHolderProvider = { parentView ->
TabTrayViewHolder( TabTrayViewHolder(
LayoutInflater.from(context).inflate( LayoutInflater.from(context).inflate(
R.layout.tab_tray_item, R.layout.tab_tray_item,

View File

@ -23,6 +23,7 @@ import kotlinx.android.synthetic.main.fragment_tab_tray_dialog.view.*
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import mozilla.components.browser.session.Session import mozilla.components.browser.session.Session
import mozilla.components.browser.state.state.TabSessionState import mozilla.components.browser.state.state.TabSessionState
import mozilla.components.browser.thumbnails.loader.ThumbnailLoader
import mozilla.components.feature.tab.collections.TabCollection import mozilla.components.feature.tab.collections.TabCollection
import mozilla.components.feature.tabs.TabsUseCases import mozilla.components.feature.tabs.TabsUseCases
import mozilla.components.feature.tabs.tabstray.TabsFeature import mozilla.components.feature.tabs.tabstray.TabsFeature
@ -127,8 +128,12 @@ class TabTrayDialogFragment : AppCompatDialogFragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val isPrivate = (activity as HomeActivity).browsingModeManager.mode.isPrivate val isPrivate = (activity as HomeActivity).browsingModeManager.mode.isPrivate
val thumbnailLoader = ThumbnailLoader(requireContext().components.core.thumbnailStorage)
val adapter = FenixTabsAdapter(requireContext(), thumbnailLoader)
_tabTrayView = TabTrayView( _tabTrayView = TabTrayView(
view.tabLayout, view.tabLayout,
adapter,
interactor = TabTrayFragmentInteractor( interactor = TabTrayFragmentInteractor(
DefaultTabTrayController( DefaultTabTrayController(
activity = (activity as HomeActivity), activity = (activity as HomeActivity),
@ -152,7 +157,7 @@ class TabTrayDialogFragment : AppCompatDialogFragment() {
tabsFeature.set( tabsFeature.set(
TabsFeature( TabsFeature(
tabTrayView.view.tabsTray, adapter,
view.context.components.core.store, view.context.components.core.store,
selectTabUseCase, selectTabUseCase,
removeTabUseCase, removeTabUseCase,

View File

@ -13,6 +13,7 @@ import androidx.cardview.widget.CardView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.LifecycleCoroutineScope import androidx.lifecycle.LifecycleCoroutineScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import kotlinx.android.extensions.LayoutContainer import kotlinx.android.extensions.LayoutContainer
@ -29,7 +30,6 @@ import mozilla.components.browser.menu.item.SimpleBrowserMenuItem
import mozilla.components.browser.state.selector.normalTabs import mozilla.components.browser.state.selector.normalTabs
import mozilla.components.browser.state.selector.privateTabs import mozilla.components.browser.state.selector.privateTabs
import mozilla.components.browser.state.state.BrowserState import mozilla.components.browser.state.state.BrowserState
import mozilla.components.browser.tabstray.BrowserTabsTray
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
@ -41,6 +41,7 @@ import org.mozilla.fenix.ext.settings
@Suppress("LongParameterList", "TooManyFunctions", "LargeClass") @Suppress("LongParameterList", "TooManyFunctions", "LargeClass")
class TabTrayView( class TabTrayView(
private val container: ViewGroup, private val container: ViewGroup,
private val tabsAdapter: FenixTabsAdapter,
private val interactor: TabTrayInteractor, private val interactor: TabTrayInteractor,
isPrivate: Boolean, isPrivate: Boolean,
startingInLandscape: Boolean, startingInLandscape: Boolean,
@ -118,27 +119,32 @@ class TabTrayView(
setTopOffset(startingInLandscape) setTopOffset(startingInLandscape)
(view.tabsTray as? BrowserTabsTray)?.also { tray -> view.tabsTray.apply {
TabsTouchHelper(tray.tabsAdapter).attachToRecyclerView(tray) layoutManager = LinearLayoutManager(container.context).apply {
(tray.tabsAdapter as? FenixTabsAdapter)?.also { adapter -> reverseLayout = true
adapter.onTabsUpdated = { stackFromEnd = true
if (hasAccessibilityEnabled) { }
adapter.notifyDataSetChanged() adapter = tabsAdapter
}
if (!hasLoaded) { TabsTouchHelper(tabsAdapter).attachToRecyclerView(this)
hasLoaded = true
scrollToTab(view.context.components.core.store.state.selectedTabId) tabsAdapter.onTabsUpdated = {
if (view.context.settings().accessibilityServicesEnabled) { if (hasAccessibilityEnabled) {
lifecycleScope.launch { tabsAdapter.notifyDataSetChanged()
delay(SELECTION_DELAY.toLong()) }
lifecycleScope.launch(Main) { if (!hasLoaded) {
tray.layoutManager?.findViewByPosition(selectedBrowserTabIndex) hasLoaded = true
?.requestFocus() scrollToTab(view.context.components.core.store.state.selectedTabId)
tray.layoutManager?.findViewByPosition(selectedBrowserTabIndex) if (view.context.settings().accessibilityServicesEnabled) {
?.sendAccessibilityEvent( lifecycleScope.launch {
AccessibilityEvent.TYPE_VIEW_FOCUSED delay(SELECTION_DELAY.toLong())
) lifecycleScope.launch(Main) {
} layoutManager?.findViewByPosition(selectedBrowserTabIndex)
?.requestFocus()
layoutManager?.findViewByPosition(selectedBrowserTabIndex)
?.sendAccessibilityEvent(
AccessibilityEvent.TYPE_VIEW_FOCUSED
)
} }
} }
} }
@ -241,7 +247,7 @@ class TabTrayView(
} }
} }
view.tabsTray.asView().visibility = if (hasNoTabs) { view.tabsTray.visibility = if (hasNoTabs) {
View.INVISIBLE View.INVISIBLE
} else { } else {
View.VISIBLE View.VISIBLE
@ -288,7 +294,7 @@ class TabTrayView(
} }
fun scrollToTab(sessionId: String?) { fun scrollToTab(sessionId: String?) {
(view.tabsTray as? BrowserTabsTray)?.also { tray -> view.tabsTray.apply {
val tabs = if (isPrivateModeSelected) { val tabs = if (isPrivateModeSelected) {
view.context.components.core.store.state.privateTabs view.context.components.core.store.state.privateTabs
} else { } else {
@ -298,7 +304,7 @@ class TabTrayView(
val selectedBrowserTabIndex = tabs val selectedBrowserTabIndex = tabs
.indexOfFirst { it.id == sessionId } .indexOfFirst { it.id == sessionId }
tray.layoutManager?.scrollToPosition(selectedBrowserTabIndex) layoutManager?.scrollToPosition(selectedBrowserTabIndex)
} }
} }

View File

@ -16,6 +16,7 @@ import androidx.core.content.ContextCompat
import mozilla.components.browser.state.state.MediaState import mozilla.components.browser.state.state.MediaState
import mozilla.components.browser.state.store.BrowserStore import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.browser.tabstray.TabViewHolder import mozilla.components.browser.tabstray.TabViewHolder
import mozilla.components.browser.tabstray.TabsTrayStyling
import mozilla.components.browser.tabstray.thumbnail.TabThumbnailView import mozilla.components.browser.tabstray.thumbnail.TabThumbnailView
import mozilla.components.browser.toolbar.MAX_URI_LENGTH import mozilla.components.browser.toolbar.MAX_URI_LENGTH
import mozilla.components.concept.tabstray.Tab import mozilla.components.concept.tabstray.Tab
@ -64,7 +65,12 @@ class TabTrayViewHolder(
/** /**
* Displays the data of the given session and notifies the given observable about events. * Displays the data of the given session and notifies the given observable about events.
*/ */
override fun bind(tab: Tab, isSelected: Boolean, observable: Observable<TabsTray.Observer>) { override fun bind(
tab: Tab,
isSelected: Boolean,
styling: TabsTrayStyling,
observable: Observable<TabsTray.Observer>
) {
// This is a hack to workaround a bug in a-c. // This is a hack to workaround a bug in a-c.
// https://github.com/mozilla-mobile/android-components/issues/7186 // https://github.com/mozilla-mobile/android-components/issues/7186
val isSelected2 = tab.id == getSelectedTabId() val isSelected2 = tab.id == getSelectedTabId()

View File

@ -105,7 +105,7 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tab_layout" /> app:layout_constraintTop_toBottomOf="@+id/tab_layout" />
<mozilla.components.concept.tabstray.TabsTray <androidx.recyclerview.widget.RecyclerView
android:id="@+id/tabsTray" android:id="@+id/tabsTray"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
@ -115,12 +115,6 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/divider" app:layout_constraintTop_toBottomOf="@+id/divider" />
mozac:tabsTrayItemBackgroundColor="@color/foundation_normal_theme"
mozac:tabsTrayItemTextColor="@color/tab_tray_item_text_normal_theme"
mozac:tabsTraySelectedItemBackgroundColor="@color/tab_tray_item_selected_background_normal_theme"
mozac:tabsTraySelectedItemTextColor="@color/tab_tray_item_selected_background_normal_theme"
mozac:tabsTrayItemUrlTextColor="@color/tab_tray_item_selected_background_normal_theme"
mozac:tabsTraySelectedItemUrlTextColor="@color/tab_tray_item_url_normal_theme" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -59,7 +59,7 @@ class TabTrayViewHolderTest {
id = "123", id = "123",
url = extremelyLongUrl url = extremelyLongUrl
) )
tabViewHolder.bind(tab, false, mockk()) tabViewHolder.bind(tab, false, mockk(), mockk())
assertEquals("m".repeat(MAX_URI_LENGTH), tabViewHolder.urlView?.text) assertEquals("m".repeat(MAX_URI_LENGTH), tabViewHolder.urlView?.text)
verify { imageLoader.loadIntoView(any(), ImageLoadRequest("123", 92)) } verify { imageLoader.loadIntoView(any(), ImageLoadRequest("123", 92)) }
@ -82,7 +82,7 @@ class TabTrayViewHolderTest {
) )
) )
) )
tabViewHolder.bind(tab, false, mockk()) tabViewHolder.bind(tab, false, mockk(), mockk())
assertEquals("Play", playPauseButtonView.contentDescription) assertEquals("Play", playPauseButtonView.contentDescription)
} }
@ -104,7 +104,7 @@ class TabTrayViewHolderTest {
) )
) )
) )
tabViewHolder.bind(tab, false, mockk()) tabViewHolder.bind(tab, false, mockk(), mockk())
assertEquals("Pause", playPauseButtonView.contentDescription) assertEquals("Pause", playPauseButtonView.contentDescription)
} }