You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iceraven-browser/app/src/main/java/org/mozilla/fenix/tabstray/browser/InactiveTabsAdapter.kt

144 lines
5.1 KiB
Kotlin

/* 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.tabstray.browser
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import mozilla.components.concept.tabstray.Tab as TabsTrayTab
import mozilla.components.concept.tabstray.Tabs
import mozilla.components.concept.tabstray.TabsTray
import mozilla.components.support.base.observer.ObserverRegistry
import org.mozilla.fenix.tabstray.browser.InactiveTabViewHolder.FooterHolder
import org.mozilla.fenix.tabstray.browser.InactiveTabViewHolder.HeaderHolder
import org.mozilla.fenix.tabstray.browser.InactiveTabViewHolder.RecentlyClosedHolder
import org.mozilla.fenix.tabstray.browser.InactiveTabViewHolder.TabViewHolder
import org.mozilla.fenix.tabstray.ext.autoCloseInterval
import mozilla.components.support.base.observer.Observable as ComponentObservable
/**
* A convenience alias for readability.
*/
private typealias Adapter = ListAdapter<InactiveTabsAdapter.Item, InactiveTabViewHolder>
/**
* A convenience alias for readability.
*/
private typealias Observable = ComponentObservable<TabsTray.Observer>
/**
* The [ListAdapter] for displaying the list of inactive tabs.
*/
class InactiveTabsAdapter(
private val context: Context,
private val browserTrayInteractor: BrowserTrayInteractor,
delegate: Observable = ObserverRegistry()
) : Adapter(DiffCallback), TabsTray, Observable by delegate {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): InactiveTabViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(viewType, parent, false)
return when (viewType) {
HeaderHolder.LAYOUT_ID -> HeaderHolder(view)
TabViewHolder.LAYOUT_ID -> TabViewHolder(view, browserTrayInteractor)
FooterHolder.LAYOUT_ID -> FooterHolder(view)
RecentlyClosedHolder.LAYOUT_ID -> RecentlyClosedHolder(view, browserTrayInteractor)
else -> throw IllegalStateException("Unknown viewType: $viewType")
}
}
override fun onBindViewHolder(holder: InactiveTabViewHolder, position: Int) {
when (holder) {
is TabViewHolder -> {
val item = getItem(position) as Item.Tab
holder.bind(item.tab)
}
is FooterHolder -> {
val item = getItem(position) as Item.Footer
holder.bind(item.interval)
}
is HeaderHolder -> {
// do nothing.
}
is RecentlyClosedHolder -> {
holder.bind()
}
}
}
override fun getItemViewType(position: Int): Int {
return when (position) {
0 -> HeaderHolder.LAYOUT_ID
itemCount - 2 -> RecentlyClosedHolder.LAYOUT_ID
itemCount - 1 -> FooterHolder.LAYOUT_ID
else -> TabViewHolder.LAYOUT_ID
}
}
override fun updateTabs(tabs: Tabs) {
if (tabs.list.isEmpty()) {
// Early return with an empty list to remove the header/footer items.
submitList(emptyList())
return
}
val items = tabs.list.map { Item.Tab(it) }
val footer = Item.Footer(context.autoCloseInterval)
submitList(listOf(Item.Header) + items + listOf(Item.RecentlyClosed, footer))
}
override fun isTabSelected(tabs: Tabs, position: Int): Boolean = false
override fun onTabsChanged(position: Int, count: Int) = Unit
override fun onTabsInserted(position: Int, count: Int) = Unit
override fun onTabsMoved(fromPosition: Int, toPosition: Int) = Unit
override fun onTabsRemoved(position: Int, count: Int) = Unit
private object DiffCallback : DiffUtil.ItemCallback<Item>() {
override fun areItemsTheSame(oldItem: Item, newItem: Item): Boolean {
return if (oldItem is Item.Tab && newItem is Item.Tab) {
oldItem.tab.id == newItem.tab.id
} else {
oldItem == newItem
}
}
override fun areContentsTheSame(oldItem: Item, newItem: Item): Boolean {
return oldItem == newItem
}
}
/**
* The types of different data we can put into the [InactiveTabsAdapter].
*/
sealed class Item {
/**
* A title header for the inactive tab section. This may be seen only
* when at least one inactive tab is present.
*/
object Header : Item()
/**
* A tab that is now considered inactive.
*/
data class Tab(val tab: TabsTrayTab) : Item()
/**
* A button that leads to the Recently Closed section in History.
*/
object RecentlyClosed : Item()
/**
* A footer for the inactive tab section. This may be seen only
* when at least one inactive tab is present.
*/
data class Footer(val interval: AutoCloseInterval) : Item()
}
}