forked from mozilla-mobile/fenix
-
Notifications
You must be signed in to change notification settings - Fork 0
/
BrowserTabsAdapter.kt
149 lines (131 loc) · 6.14 KB
/
BrowserTabsAdapter.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* 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.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import mozilla.components.browser.tabstray.TabsAdapter.Companion.PAYLOAD_DONT_HIGHLIGHT_SELECTED_ITEM
import mozilla.components.browser.tabstray.TabsAdapter.Companion.PAYLOAD_HIGHLIGHT_SELECTED_ITEM
import mozilla.components.browser.thumbnails.loader.ThumbnailLoader
import mozilla.components.concept.tabstray.Tab
import mozilla.components.concept.tabstray.TabsTray
import mozilla.components.support.base.observer.Observable
import mozilla.components.support.base.observer.ObserverRegistry
import org.mozilla.fenix.components.Components
import org.mozilla.fenix.databinding.TabTrayGridItemBinding
import org.mozilla.fenix.databinding.TabTrayItemBinding
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.selection.SelectionHolder
import org.mozilla.fenix.tabstray.TabsTrayStore
/**
* A [RecyclerView.Adapter] for browser tabs.
*
* @param context [Context] used for various platform interactions or accessing [Components]
* @param interactor [BrowserTrayInteractor] handling tabs interactions in a tab tray.
* @param store [TabsTrayStore] containing the complete state of tabs tray and methods to update that.
* @param featureName [String] representing the name of the feature displaying tabs. Used in telemetry reporting.
* @param delegate [Observable]<[TabsTray.Observer]> for observing tabs tray changes. Defaults to [ObserverRegistry].
*/
class BrowserTabsAdapter(
private val context: Context,
private val interactor: BrowserTrayInteractor,
private val store: TabsTrayStore,
private val featureName: String,
delegate: Observable<TabsTray.Observer> = ObserverRegistry()
) : TabsAdapter<AbstractBrowserTabViewHolder>(delegate) {
/**
* The layout types for the tabs.
*/
enum class ViewType(val layoutRes: Int) {
LIST(BrowserTabViewHolder.ListViewHolder.LAYOUT_ID),
GRID(BrowserTabViewHolder.GridViewHolder.LAYOUT_ID)
}
/**
* Tracks the selected tabs in multi-select mode.
*/
var selectionHolder: SelectionHolder<Tab>? = null
private val selectedItemAdapterBinding = SelectedItemAdapterBinding(store, this)
private val imageLoader = ThumbnailLoader(context.components.core.thumbnailStorage)
override fun getItemViewType(position: Int): Int {
return when {
context.components.settings.gridTabView -> {
ViewType.GRID.layoutRes
}
else -> {
ViewType.LIST.layoutRes
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AbstractBrowserTabViewHolder {
val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false)
return when (viewType) {
ViewType.GRID.layoutRes ->
BrowserTabViewHolder.GridViewHolder(imageLoader, interactor, store, selectionHolder, view, featureName)
else ->
BrowserTabViewHolder.ListViewHolder(imageLoader, interactor, store, selectionHolder, view, featureName)
}
}
override fun onBindViewHolder(holder: AbstractBrowserTabViewHolder, position: Int) {
super.onBindViewHolder(holder, position)
var selectedMaskView: View? = null
holder.tab?.let { tab ->
when (getItemViewType(position)) {
ViewType.GRID.layoutRes -> {
val gridBinding = TabTrayGridItemBinding.bind(holder.itemView)
selectedMaskView = gridBinding.checkboxInclude.selectedMask
gridBinding.mozacBrowserTabstrayClose.setOnClickListener { interactor.close(tab, featureName) }
}
ViewType.LIST.layoutRes -> {
val listBinding = TabTrayItemBinding.bind(holder.itemView)
selectedMaskView = listBinding.checkboxInclude.selectedMask
listBinding.mozacBrowserTabstrayClose.setOnClickListener { interactor.close(tab, featureName) }
}
}
selectionHolder?.let {
holder.showTabIsMultiSelectEnabled(selectedMaskView, it.selectedItems.contains(tab))
}
}
}
/**
* Over-ridden [onBindViewHolder] that uses the payloads to notify the selected tab how to
* display itself.
*/
override fun onBindViewHolder(holder: AbstractBrowserTabViewHolder, position: Int, payloads: List<Any>) {
val tabs = tabs ?: return
if (tabs.list.isEmpty()) return
if (payloads.isEmpty()) {
onBindViewHolder(holder, position)
return
}
if (position == tabs.selectedIndex) {
if (payloads.contains(PAYLOAD_HIGHLIGHT_SELECTED_ITEM)) {
holder.updateSelectedTabIndicator(true)
} else if (payloads.contains(PAYLOAD_DONT_HIGHLIGHT_SELECTED_ITEM)) {
holder.updateSelectedTabIndicator(false)
}
}
selectionHolder?.let {
var selectedMaskView: View? = null
when (getItemViewType(position)) {
ViewType.GRID.layoutRes -> {
val gridBinding = TabTrayGridItemBinding.bind(holder.itemView)
selectedMaskView = gridBinding.checkboxInclude.selectedMask
}
ViewType.LIST.layoutRes -> {
val listBinding = TabTrayItemBinding.bind(holder.itemView)
selectedMaskView = listBinding.checkboxInclude.selectedMask
}
}
holder.showTabIsMultiSelectEnabled(selectedMaskView, it.selectedItems.contains(holder.tab))
}
}
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
selectedItemAdapterBinding.start()
}
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
selectedItemAdapterBinding.stop()
}
}