Change the DiffUtil callback for bookmarks to use the generated equals() method instead of only checking the title and url fields. This prevents the BookmarkNode in our state from getting out of sync with the BookmarkNode the viewholder is bound to.master
parent
0aab7a806a
commit
6d8cfe1a50
|
@ -59,9 +59,20 @@ class BookmarkAdapter(val emptyView: View, val interactor: BookmarkViewInteracto
|
||||||
old[oldItemPosition].guid == new[newItemPosition].guid
|
old[oldItemPosition].guid == new[newItemPosition].guid
|
||||||
|
|
||||||
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
|
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
|
||||||
|
oldMode::class == newMode::class &&
|
||||||
old[oldItemPosition] in oldMode.selectedItems == new[newItemPosition] in newMode.selectedItems &&
|
old[oldItemPosition] in oldMode.selectedItems == new[newItemPosition] in newMode.selectedItems &&
|
||||||
old[oldItemPosition].title == new[newItemPosition].title &&
|
old[oldItemPosition] == new[newItemPosition]
|
||||||
old[oldItemPosition].url == new[newItemPosition].url
|
|
||||||
|
override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
|
||||||
|
val oldItem = old[oldItemPosition]
|
||||||
|
val newItem = new[newItemPosition]
|
||||||
|
return BookmarkPayload(
|
||||||
|
titleChanged = oldItem.title != newItem.title,
|
||||||
|
urlChanged = oldItem.url != newItem.url,
|
||||||
|
selectedChanged = oldItem in oldMode.selectedItems != newItem in newMode.selectedItems,
|
||||||
|
modeChanged = oldMode::class != newMode::class
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getOldListSize(): Int = old.size
|
override fun getOldListSize(): Int = old.size
|
||||||
override fun getNewListSize(): Int = new.size
|
override fun getNewListSize(): Int = new.size
|
||||||
|
@ -90,9 +101,36 @@ class BookmarkAdapter(val emptyView: View, val interactor: BookmarkViewInteracto
|
||||||
|
|
||||||
override fun getItemCount(): Int = tree.size
|
override fun getItemCount(): Int = tree.size
|
||||||
|
|
||||||
|
override fun onBindViewHolder(
|
||||||
|
holder: BookmarkNodeViewHolder,
|
||||||
|
position: Int,
|
||||||
|
payloads: MutableList<Any>
|
||||||
|
) {
|
||||||
|
if (payloads.isNotEmpty() && payloads[0] is BookmarkPayload) {
|
||||||
|
holder.bind(tree[position], mode, payloads[0] as BookmarkPayload)
|
||||||
|
} else {
|
||||||
|
super.onBindViewHolder(holder, position, payloads)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: BookmarkNodeViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: BookmarkNodeViewHolder, position: Int) {
|
||||||
holder.bind(tree[position], mode)
|
holder.bind(tree[position], mode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A RecyclerView Adapter payload class that contains information about changes to a [BookmarkNode].
|
||||||
|
*
|
||||||
|
* @property titleChanged true if there has been a change to [BookmarkNode.title].
|
||||||
|
* @property urlChanged true if there has been a change to [BookmarkNode.url].
|
||||||
|
* @property selectedChanged true if there has been a change in the BookmarkNode's selected state.
|
||||||
|
* @property modeChanged true if there has been a change in the state's mode type.
|
||||||
|
*/
|
||||||
|
data class BookmarkPayload(
|
||||||
|
val titleChanged: Boolean,
|
||||||
|
val urlChanged: Boolean,
|
||||||
|
val selectedChanged: Boolean,
|
||||||
|
val modeChanged: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
fun BookmarkNode.inRoots() = enumValues<BookmarkRoot>().any { it.id == guid }
|
fun BookmarkNode.inRoots() = enumValues<BookmarkRoot>().any { it.id == guid }
|
||||||
|
|
|
@ -139,7 +139,6 @@ class BookmarkView(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(state: BookmarkFragmentState) {
|
fun update(state: BookmarkFragmentState) {
|
||||||
val oldMode = mode
|
|
||||||
tree = state.tree
|
tree = state.tree
|
||||||
if (state.mode != mode) {
|
if (state.mode != mode) {
|
||||||
mode = state.mode
|
mode = state.mode
|
||||||
|
@ -149,9 +148,6 @@ class BookmarkView(
|
||||||
}
|
}
|
||||||
|
|
||||||
bookmarkAdapter.updateData(state.tree, mode)
|
bookmarkAdapter.updateData(state.tree, mode)
|
||||||
if (state.mode != oldMode) {
|
|
||||||
bookmarkAdapter.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
|
|
||||||
when (mode) {
|
when (mode) {
|
||||||
is BookmarkFragmentState.Mode.Normal -> {
|
is BookmarkFragmentState.Mode.Normal -> {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import org.mozilla.fenix.ext.showAndEnable
|
||||||
import org.mozilla.fenix.library.LibrarySiteItemView
|
import org.mozilla.fenix.library.LibrarySiteItemView
|
||||||
import org.mozilla.fenix.library.SelectionHolder
|
import org.mozilla.fenix.library.SelectionHolder
|
||||||
import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState
|
import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState
|
||||||
|
import org.mozilla.fenix.library.bookmarks.BookmarkPayload
|
||||||
import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor
|
import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor
|
||||||
import org.mozilla.fenix.library.bookmarks.inRoots
|
import org.mozilla.fenix.library.bookmarks.inRoots
|
||||||
|
|
||||||
|
@ -28,28 +29,39 @@ class BookmarkFolderViewHolder(
|
||||||
|
|
||||||
override var item: BookmarkNode? = null
|
override var item: BookmarkNode? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
containerView.displayAs(LibrarySiteItemView.ItemType.FOLDER)
|
||||||
|
}
|
||||||
|
|
||||||
override fun bind(
|
override fun bind(
|
||||||
item: BookmarkNode,
|
item: BookmarkNode,
|
||||||
mode: BookmarkFragmentState.Mode
|
mode: BookmarkFragmentState.Mode
|
||||||
) {
|
) {
|
||||||
this.item = item
|
bind(item, mode, BookmarkPayload(true, true, true, true))
|
||||||
|
}
|
||||||
|
|
||||||
containerView.displayAs(LibrarySiteItemView.ItemType.FOLDER)
|
override fun bind(item: BookmarkNode, mode: BookmarkFragmentState.Mode, payload: BookmarkPayload) {
|
||||||
|
this.item = item
|
||||||
|
|
||||||
setSelectionListeners(item, selectionHolder)
|
setSelectionListeners(item, selectionHolder)
|
||||||
|
|
||||||
if (!item.inRoots()) {
|
if (!item.inRoots()) {
|
||||||
setupMenu(item)
|
setupMenu(item)
|
||||||
if (mode is BookmarkFragmentState.Mode.Selecting) {
|
if (payload.modeChanged) {
|
||||||
containerView.overflowView.hideAndDisable()
|
if (mode is BookmarkFragmentState.Mode.Selecting) {
|
||||||
} else {
|
containerView.overflowView.hideAndDisable()
|
||||||
containerView.overflowView.showAndEnable()
|
} else {
|
||||||
|
containerView.overflowView.showAndEnable()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
containerView.overflowView.visibility = View.GONE
|
containerView.overflowView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
containerView.changeSelected(item in selectionHolder.selectedItems)
|
if (payload.selectedChanged) {
|
||||||
|
containerView.changeSelected(item in selectionHolder.selectedItems)
|
||||||
|
}
|
||||||
|
|
||||||
containerView.iconView.setImageDrawable(
|
containerView.iconView.setImageDrawable(
|
||||||
AppCompatResources.getDrawable(
|
AppCompatResources.getDrawable(
|
||||||
containerView.context,
|
containerView.context,
|
||||||
|
@ -63,6 +75,9 @@ class BookmarkFolderViewHolder(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
containerView.titleView.text = item.title
|
|
||||||
|
if (payload.titleChanged) {
|
||||||
|
containerView.titleView.text = item.title
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.mozilla.fenix.ext.showAndEnable
|
||||||
import org.mozilla.fenix.library.LibrarySiteItemView
|
import org.mozilla.fenix.library.LibrarySiteItemView
|
||||||
import org.mozilla.fenix.library.SelectionHolder
|
import org.mozilla.fenix.library.SelectionHolder
|
||||||
import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState
|
import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState
|
||||||
|
import org.mozilla.fenix.library.bookmarks.BookmarkPayload
|
||||||
import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor
|
import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,27 +24,46 @@ class BookmarkItemViewHolder(
|
||||||
|
|
||||||
override var item: BookmarkNode? = null
|
override var item: BookmarkNode? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
containerView.displayAs(LibrarySiteItemView.ItemType.SITE)
|
||||||
|
}
|
||||||
|
|
||||||
override fun bind(
|
override fun bind(
|
||||||
item: BookmarkNode,
|
item: BookmarkNode,
|
||||||
mode: BookmarkFragmentState.Mode
|
mode: BookmarkFragmentState.Mode
|
||||||
) {
|
) {
|
||||||
|
bind(item, mode, BookmarkPayload(true, true, true, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bind(item: BookmarkNode, mode: BookmarkFragmentState.Mode, payload: BookmarkPayload) {
|
||||||
this.item = item
|
this.item = item
|
||||||
|
|
||||||
containerView.displayAs(LibrarySiteItemView.ItemType.SITE)
|
|
||||||
|
|
||||||
if (mode is BookmarkFragmentState.Mode.Selecting) {
|
|
||||||
containerView.overflowView.hideAndDisable()
|
|
||||||
} else {
|
|
||||||
containerView.overflowView.showAndEnable()
|
|
||||||
}
|
|
||||||
setupMenu(item)
|
setupMenu(item)
|
||||||
containerView.titleView.text = if (item.title.isNullOrBlank()) item.url else item.title
|
|
||||||
containerView.urlView.text = item.url
|
if (payload.modeChanged) {
|
||||||
|
if (mode is BookmarkFragmentState.Mode.Selecting) {
|
||||||
|
containerView.overflowView.hideAndDisable()
|
||||||
|
} else {
|
||||||
|
containerView.overflowView.showAndEnable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload.selectedChanged) {
|
||||||
|
containerView.changeSelected(item in selectionHolder.selectedItems)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload.titleChanged) {
|
||||||
|
containerView.titleView.text = if (item.title.isNullOrBlank()) item.url else item.title
|
||||||
|
} else if (payload.urlChanged && item.title.isNullOrBlank()) {
|
||||||
|
containerView.titleView.text = item.url
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload.urlChanged) {
|
||||||
|
containerView.urlView.text = item.url
|
||||||
|
setColorsAndIcons(item.url)
|
||||||
|
}
|
||||||
|
|
||||||
setSelectionListeners(item, selectionHolder)
|
setSelectionListeners(item, selectionHolder)
|
||||||
|
|
||||||
containerView.changeSelected(item in selectionHolder.selectedItems)
|
|
||||||
setColorsAndIcons(item.url)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setColorsAndIcons(url: String?) {
|
private fun setColorsAndIcons(url: String?) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.mozilla.fenix.library.LibrarySiteItemView
|
||||||
import org.mozilla.fenix.library.SelectionHolder
|
import org.mozilla.fenix.library.SelectionHolder
|
||||||
import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState
|
import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState
|
||||||
import org.mozilla.fenix.library.bookmarks.BookmarkItemMenu
|
import org.mozilla.fenix.library.bookmarks.BookmarkItemMenu
|
||||||
|
import org.mozilla.fenix.library.bookmarks.BookmarkPayload
|
||||||
import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor
|
import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,6 +29,12 @@ abstract class BookmarkNodeViewHolder(
|
||||||
mode: BookmarkFragmentState.Mode
|
mode: BookmarkFragmentState.Mode
|
||||||
)
|
)
|
||||||
|
|
||||||
|
abstract fun bind(
|
||||||
|
item: BookmarkNode,
|
||||||
|
mode: BookmarkFragmentState.Mode,
|
||||||
|
payload: BookmarkPayload
|
||||||
|
)
|
||||||
|
|
||||||
protected fun setSelectionListeners(item: BookmarkNode, selectionHolder: SelectionHolder<BookmarkNode>) {
|
protected fun setSelectionListeners(item: BookmarkNode, selectionHolder: SelectionHolder<BookmarkNode>) {
|
||||||
containerView.setSelectionInteractor(item, selectionHolder, interactor)
|
containerView.setSelectionInteractor(item, selectionHolder, interactor)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ package org.mozilla.fenix.library.bookmarks.viewholders
|
||||||
import mozilla.components.concept.storage.BookmarkNode
|
import mozilla.components.concept.storage.BookmarkNode
|
||||||
import org.mozilla.fenix.library.LibrarySiteItemView
|
import org.mozilla.fenix.library.LibrarySiteItemView
|
||||||
import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState
|
import org.mozilla.fenix.library.bookmarks.BookmarkFragmentState
|
||||||
|
import org.mozilla.fenix.library.bookmarks.BookmarkPayload
|
||||||
import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor
|
import org.mozilla.fenix.library.bookmarks.BookmarkViewInteractor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,4 +28,12 @@ class BookmarkSeparatorViewHolder(
|
||||||
containerView.displayAs(LibrarySiteItemView.ItemType.SEPARATOR)
|
containerView.displayAs(LibrarySiteItemView.ItemType.SEPARATOR)
|
||||||
setupMenu(item)
|
setupMenu(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun bind(
|
||||||
|
item: BookmarkNode,
|
||||||
|
mode: BookmarkFragmentState.Mode,
|
||||||
|
payload: BookmarkPayload
|
||||||
|
) {
|
||||||
|
bind(item, mode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue