diff --git a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt index 71cfa040f..5d7a0d5de 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -257,10 +257,10 @@ class AlbumDetailFragment : } if (parent is Album && parent.id == unlikelyToBeNull(detailModel.currentAlbum.value).id) { - detailAdapter.highlightSong(song) + detailAdapter.activateSong(song) } else { // Clear the ViewHolders if the mode isn't ALL_SONGS - detailAdapter.highlightSong(null) + detailAdapter.activateSong(null) } } diff --git a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt index 8d0e9313a..953e9c537 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/ArtistDetailFragment.kt @@ -202,18 +202,18 @@ class ArtistDetailFragment : private fun updatePlayback(song: Song?, parent: MusicParent?) { if (parent is Artist && parent.id == unlikelyToBeNull(detailModel.currentArtist.value).id) { - detailAdapter.highlightSong(song) + detailAdapter.activateSong(song) } else { - // Clear the ViewHolders if the given song is not part of this artist. - detailAdapter.highlightSong(null) + // Ignore song playback not from the artist + detailAdapter.activateSong(null) } if (parent is Album && parent.artist.id == unlikelyToBeNull(detailModel.currentArtist.value).id) { - detailAdapter.highlightAlbum(parent) + detailAdapter.activateAlbum(parent) } else { - // Clear out the album viewholder if the parent is not an album. - detailAdapter.highlightAlbum(null) + // Ignore album playback not from the artist + detailAdapter.activateAlbum(null) } } } diff --git a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt index a0faab276..b3174070c 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt @@ -83,7 +83,7 @@ class GenreDetailFragment : binding.detailRecycler.apply { adapter = detailAdapter setSpanSizeLookup { pos -> - val item = detailModel.albumData.value[pos] + val item = detailModel.genreData.value[pos] item is Genre || item is Header || item is SortHeader } } @@ -195,9 +195,10 @@ class GenreDetailFragment : private fun updatePlayback(song: Song?, parent: MusicParent?) { if (parent is Genre && parent.id == unlikelyToBeNull(detailModel.currentGenre.value).id) { - detailAdapter.highlightSong(song) + detailAdapter.activateSong(song) } else { - detailAdapter.highlightSong(null) + // Ignore song playback not from the genre + detailAdapter.activateSong(null) } } } diff --git a/app/src/main/java/org/oxycblt/auxio/detail/recycler/AlbumDetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/recycler/AlbumDetailAdapter.kt index 7e14e2a3c..3e01dd638 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/recycler/AlbumDetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/recycler/AlbumDetailAdapter.kt @@ -64,25 +64,28 @@ class AlbumDetailAdapter(private val listener: Listener) : override fun onBindViewHolder( holder: RecyclerView.ViewHolder, position: Int, - payload: List + payloads: List ) { - if (payload.isEmpty()) { + super.onBindViewHolder(holder, position, payloads) + + if (payloads.isEmpty()) { when (val item = differ.currentList[position]) { is Album -> (holder as AlbumDetailViewHolder).bind(item, listener) is DiscHeader -> (holder as DiscHeaderViewHolder).bind(item) is Song -> (holder as AlbumSongViewHolder).bind(item, listener) } } - - super.onBindViewHolder(holder, position, payload) } - override fun shouldHighlightViewHolder(item: Item) = item is Song && item.id == currentSong?.id + override fun shouldActivateViewHolder(position: Int): Boolean { + val item = differ.currentList[position] + return item is Song && item.id == currentSong?.id + } - /** Update the [song] that this adapter should highlight */ - fun highlightSong(song: Song?) { + /** Update the [song] that this adapter should indicate playback */ + fun activateSong(song: Song?) { if (song == currentSong) return - highlightImpl(currentSong, song) + activateImpl(differ.currentList, currentSong, song) currentSong = song } diff --git a/app/src/main/java/org/oxycblt/auxio/detail/recycler/ArtistDetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/recycler/ArtistDetailAdapter.kt index 32da20b3e..c12dafa93 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/recycler/ArtistDetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/recycler/ArtistDetailAdapter.kt @@ -66,34 +66,36 @@ class ArtistDetailAdapter(private val listener: Listener) : override fun onBindViewHolder( holder: RecyclerView.ViewHolder, position: Int, - payload: List + payloads: List ) { - if (payload.isEmpty()) { + super.onBindViewHolder(holder, position, payloads) + + if (payloads.isEmpty()) { when (val item = differ.currentList[position]) { is Artist -> (holder as ArtistDetailViewHolder).bind(item, listener) is Album -> (holder as ArtistAlbumViewHolder).bind(item, listener) is Song -> (holder as ArtistSongViewHolder).bind(item, listener) } } - - super.onBindViewHolder(holder, position, payload) } - override fun shouldHighlightViewHolder(item: Item) = - (item is Album && item.id == currentAlbum?.id) || + override fun shouldActivateViewHolder(position: Int): Boolean { + val item = differ.currentList[position] + return (item is Album && item.id == currentAlbum?.id) || (item is Song && item.id == currentSong?.id) + } - /** Update the current [album] that this adapter should highlight */ - fun highlightAlbum(album: Album?) { + /** Update the [album] that this adapter should indicate playback */ + fun activateAlbum(album: Album?) { if (album == currentAlbum) return - highlightImpl(currentAlbum, album) + activateImpl(differ.currentList, currentAlbum, album) currentAlbum = album } - /** Update the [song] that this adapter should highlight */ - fun highlightSong(song: Song?) { + /** Update the [song] that this adapter should indicate playback */ + fun activateSong(song: Song?) { if (song == currentSong) return - highlightImpl(currentSong, song) + activateImpl(differ.currentList, currentSong, song) currentSong = song } diff --git a/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt index 76c6a5d54..d793a020a 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/recycler/DetailAdapter.kt @@ -26,6 +26,7 @@ import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.IntegerTable import org.oxycblt.auxio.databinding.ItemSortHeaderBinding import org.oxycblt.auxio.detail.SortHeader +import org.oxycblt.auxio.ui.recycler.ActivationAdapter import org.oxycblt.auxio.ui.recycler.Header import org.oxycblt.auxio.ui.recycler.HeaderViewHolder import org.oxycblt.auxio.ui.recycler.Item @@ -33,12 +34,11 @@ import org.oxycblt.auxio.ui.recycler.MenuItemListener import org.oxycblt.auxio.ui.recycler.SimpleItemCallback import org.oxycblt.auxio.util.context import org.oxycblt.auxio.util.inflater -import org.oxycblt.auxio.util.logW abstract class DetailAdapter( private val listener: L, diffCallback: DiffUtil.ItemCallback -) : RecyclerView.Adapter() { +) : ActivationAdapter() { @Suppress("LeakingThis") override fun getItemCount() = differ.currentList.size override fun getItemViewType(position: Int) = @@ -61,58 +61,27 @@ abstract class DetailAdapter( override fun onBindViewHolder( holder: RecyclerView.ViewHolder, position: Int, - payload: List + payloads: List ) { val item = differ.currentList[position] - if (payload.isEmpty()) { + if (payloads.isEmpty()) { when (item) { is Header -> (holder as HeaderViewHolder).bind(item) is SortHeader -> (holder as SortHeaderViewHolder).bind(item, listener) } } - holder.itemView.isActivated = shouldHighlightViewHolder(item) + super.onBindViewHolder(holder, position, payloads) } protected val differ = AsyncListDiffer(this, diffCallback) - protected abstract fun shouldHighlightViewHolder(item: Item): Boolean - - protected inline fun highlightImpl(oldItem: T?, newItem: T?) { - if (oldItem != null) { - val pos = differ.currentList.indexOfFirst { item -> item.id == oldItem.id && item is T } - - if (pos > -1) { - notifyItemChanged(pos, PAYLOAD_HIGHLIGHT_CHANGED) - } else { - logW("oldItem was not in adapter data") - } - } - - if (newItem != null) { - val pos = differ.currentList.indexOfFirst { item -> item is T && item.id == newItem.id } - - if (pos > -1) { - notifyItemChanged(pos, PAYLOAD_HIGHLIGHT_CHANGED) - } else { - logW("newItem was not in adapter data") - } - } - } - fun submitList(list: List) { differ.submitList(list) } companion object { - // This payload value serves two purposes: - // 1. It disables animations from notifyItemChanged, which looks bad when highlighting - // ViewHolders. - // 2. It instructs adapters to avoid re-binding information, and instead simply - // change the highlight state. - val PAYLOAD_HIGHLIGHT_CHANGED = Any() - val DIFFER = object : SimpleItemCallback() { override fun areItemsTheSame(oldItem: Item, newItem: Item): Boolean { diff --git a/app/src/main/java/org/oxycblt/auxio/detail/recycler/GenreDetailAdapter.kt b/app/src/main/java/org/oxycblt/auxio/detail/recycler/GenreDetailAdapter.kt index c02edf17f..462368c82 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/recycler/GenreDetailAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/recycler/GenreDetailAdapter.kt @@ -58,24 +58,27 @@ class GenreDetailAdapter(private val listener: Listener) : override fun onBindViewHolder( holder: RecyclerView.ViewHolder, position: Int, - payload: List + payloads: List ) { - if (payload.isEmpty()) { + super.onBindViewHolder(holder, position, payloads) + + if (payloads.isEmpty()) { when (val item = differ.currentList[position]) { is Genre -> (holder as GenreDetailViewHolder).bind(item, listener) is Song -> (holder as SongViewHolder).bind(item, listener) } } - - super.onBindViewHolder(holder, position, payload) } - override fun shouldHighlightViewHolder(item: Item) = item is Song && item.id == currentSong?.id + override fun shouldActivateViewHolder(position: Int): Boolean { + val item = differ.currentList[position] + return item is Song && item.id == currentSong?.id + } - /** Update the [song] that this adapter should highlight */ - fun highlightSong(song: Song?) { + /** Update the [song] that this adapter should indicate playback */ + fun activateSong(song: Song?) { if (song == currentSong) return - highlightImpl(currentSong, song) + activateImpl(differ.currentList, currentSong, song) currentSong = song } diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt index edac650da..f9e030a53 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/AlbumListFragment.kt @@ -21,14 +21,15 @@ import android.os.Bundle import android.text.format.DateUtils import android.view.View import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView import java.util.* import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentHomeListBinding import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Music +import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.ui.DisplayMode import org.oxycblt.auxio.ui.Sort +import org.oxycblt.auxio.ui.recycler.ActivationAdapter import org.oxycblt.auxio.ui.recycler.AlbumViewHolder import org.oxycblt.auxio.ui.recycler.Item import org.oxycblt.auxio.ui.recycler.MenuItemListener @@ -55,6 +56,7 @@ class AlbumListFragment : HomeListFragment() { } collectImmediately(homeModel.albums, homeAdapter::replaceList) + collectImmediately(playbackModel.parent, ::handleParent) } override fun getPopup(pos: Int): String? { @@ -107,21 +109,47 @@ class AlbumListFragment : HomeListFragment() { } } + private fun handleParent(parent: MusicParent?) { + if (parent is Album) { + homeAdapter.activateAlbum(parent) + } else { + // Ignore playback not from albums + homeAdapter.activateAlbum(null) + } + } + private class AlbumAdapter(private val listener: MenuItemListener) : - RecyclerView.Adapter() { + ActivationAdapter() { private val differ = SyncListDiffer(this, AlbumViewHolder.DIFFER) + private var currentAlbum: Album? = null override fun getItemCount() = differ.currentList.size override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = AlbumViewHolder.new(parent) - override fun onBindViewHolder(holder: AlbumViewHolder, position: Int) { - holder.bind(differ.currentList[position], listener) + override fun onBindViewHolder(holder: AlbumViewHolder, position: Int, payloads: List) { + super.onBindViewHolder(holder, position, payloads) + + if (payloads.isEmpty()) { + holder.bind(differ.currentList[position], listener) + } + } + + override fun shouldActivateViewHolder(position: Int): Boolean { + val item = differ.currentList[position] + return item.id == currentAlbum?.id } fun replaceList(newList: List) { differ.replaceList(newList) } + + /** Update the [album] that this adapter should indicate playback */ + fun activateAlbum(album: Album?) { + if (album == currentAlbum) return + activateImpl(differ.currentList, currentAlbum, album) + currentAlbum = album + } } } diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt index 1600f7358..27600d816 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/ArtistListFragment.kt @@ -20,13 +20,14 @@ package org.oxycblt.auxio.home.list import android.os.Bundle import android.view.View import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentHomeListBinding import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Music +import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.ui.DisplayMode import org.oxycblt.auxio.ui.Sort +import org.oxycblt.auxio.ui.recycler.ActivationAdapter import org.oxycblt.auxio.ui.recycler.ArtistViewHolder import org.oxycblt.auxio.ui.recycler.Item import org.oxycblt.auxio.ui.recycler.MenuItemListener @@ -50,6 +51,7 @@ class ArtistListFragment : HomeListFragment() { } collectImmediately(homeModel.artists, homeAdapter::replaceList) + collectImmediately(playbackModel.parent, ::handleParent) } override fun getPopup(pos: Int): String? { @@ -83,21 +85,51 @@ class ArtistListFragment : HomeListFragment() { } } + private fun handleParent(parent: MusicParent?) { + if (parent is Artist) { + homeAdapter.activateArtist(parent) + } else { + // Ignore playback not from artists + homeAdapter.activateArtist(null) + } + } + private class ArtistAdapter(private val listener: MenuItemListener) : - RecyclerView.Adapter() { + ActivationAdapter() { private val differ = SyncListDiffer(this, ArtistViewHolder.DIFFER) + private var currentArtist: Artist? = null override fun getItemCount() = differ.currentList.size override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ArtistViewHolder.new(parent) - override fun onBindViewHolder(holder: ArtistViewHolder, position: Int) { - holder.bind(differ.currentList[position], listener) + override fun onBindViewHolder( + holder: ArtistViewHolder, + position: Int, + payloads: List + ) { + super.onBindViewHolder(holder, position, payloads) + + if (payloads.isEmpty()) { + holder.bind(differ.currentList[position], listener) + } + } + + override fun shouldActivateViewHolder(position: Int): Boolean { + val item = differ.currentList[position] + return item.id == currentArtist?.id } fun replaceList(newList: List) { differ.replaceList(newList) } + + /** Update the [artist] that this adapter should indicate playback */ + fun activateArtist(artist: Artist?) { + if (artist == currentArtist) return + activateImpl(differ.currentList, currentArtist, artist) + currentArtist = artist + } } } diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt index 385fca8e4..3ff08fd65 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/GenreListFragment.kt @@ -20,13 +20,14 @@ package org.oxycblt.auxio.home.list import android.os.Bundle import android.view.View import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentHomeListBinding import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Music +import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.ui.DisplayMode import org.oxycblt.auxio.ui.Sort +import org.oxycblt.auxio.ui.recycler.ActivationAdapter import org.oxycblt.auxio.ui.recycler.GenreViewHolder import org.oxycblt.auxio.ui.recycler.Item import org.oxycblt.auxio.ui.recycler.MenuItemListener @@ -50,6 +51,7 @@ class GenreListFragment : HomeListFragment() { } collectImmediately(homeModel.genres, homeAdapter::replaceList) + collectImmediately(playbackModel.parent, ::handlePlayback) } override fun getPopup(pos: Int): String? { @@ -83,21 +85,47 @@ class GenreListFragment : HomeListFragment() { } } + private fun handlePlayback(parent: MusicParent?) { + if (parent is Genre) { + homeAdapter.activateGenre(parent) + } else { + // Ignore playback not from genres + homeAdapter.activateGenre(null) + } + } + private class GenreAdapter(private val listener: MenuItemListener) : - RecyclerView.Adapter() { + ActivationAdapter() { private val differ = SyncListDiffer(this, GenreViewHolder.DIFFER) + private var currentGenre: Genre? = null override fun getItemCount() = differ.currentList.size override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = GenreViewHolder.new(parent) - override fun onBindViewHolder(holder: GenreViewHolder, position: Int) { - holder.bind(differ.currentList[position], listener) + override fun onBindViewHolder(holder: GenreViewHolder, position: Int, payloads: List) { + super.onBindViewHolder(holder, position, payloads) + + if (payloads.isEmpty()) { + holder.bind(differ.currentList[position], listener) + } + } + + override fun shouldActivateViewHolder(position: Int): Boolean { + val item = differ.currentList[position] + return item.id == currentGenre?.id } fun replaceList(newList: List) { differ.replaceList(newList) } + + /** Update the [genre] that this adapter should indicate playback */ + fun activateGenre(genre: Genre?) { + if (genre == currentGenre) return + activateImpl(differ.currentList, currentGenre, genre) + currentGenre = genre + } } } diff --git a/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt index 95d634e13..a01b47ee9 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/list/SongListFragment.kt @@ -21,14 +21,15 @@ import android.os.Bundle import android.text.format.DateUtils import android.view.View import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView import java.util.Formatter import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentHomeListBinding +import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.settings.Settings import org.oxycblt.auxio.ui.DisplayMode import org.oxycblt.auxio.ui.Sort +import org.oxycblt.auxio.ui.recycler.ActivationAdapter import org.oxycblt.auxio.ui.recycler.Item import org.oxycblt.auxio.ui.recycler.MenuItemListener import org.oxycblt.auxio.ui.recycler.SongViewHolder @@ -57,6 +58,7 @@ class SongListFragment : HomeListFragment() { } collectImmediately(homeModel.songs, homeAdapter::replaceList) + collectImmediately(playbackModel.song, playbackModel.parent, ::handlePlayback) } override fun getPopup(pos: Int): String? { @@ -111,21 +113,47 @@ class SongListFragment : HomeListFragment() { } } + private fun handlePlayback(song: Song?, parent: MusicParent?) { + if (parent == null) { + homeAdapter.activateSong(song) + } else { + // Ignore playback that is not from all songs + homeAdapter.activateSong(null) + } + } + private class SongAdapter(private val listener: MenuItemListener) : - RecyclerView.Adapter() { + ActivationAdapter() { private val differ = SyncListDiffer(this, SongViewHolder.DIFFER) + private var currentSong: Song? = null override fun getItemCount() = differ.currentList.size override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = SongViewHolder.new(parent) - override fun onBindViewHolder(holder: SongViewHolder, position: Int) { - holder.bind(differ.currentList[position], listener) + override fun onBindViewHolder(holder: SongViewHolder, position: Int, payloads: List) { + super.onBindViewHolder(holder, position, payloads) + + if (payloads.isEmpty()) { + holder.bind(differ.currentList[position], listener) + } + } + + override fun shouldActivateViewHolder(position: Int): Boolean { + val item = differ.currentList[position] + return item.id == currentSong?.id } fun replaceList(newList: List) { differ.replaceList(newList) } + + /** Update the [song] that this adapter should indicate playback */ + fun activateSong(song: Song?) { + if (song == currentSong) return + activateImpl(differ.currentList, currentSong, song) + currentSong = song + } } } diff --git a/app/src/main/java/org/oxycblt/auxio/ui/recycler/RecyclerFramework.kt b/app/src/main/java/org/oxycblt/auxio/ui/recycler/RecyclerFramework.kt index 3d3843ea1..274e33bd2 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/recycler/RecyclerFramework.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/recycler/RecyclerFramework.kt @@ -23,6 +23,7 @@ import androidx.recyclerview.widget.AdapterListUpdateCallback import androidx.recyclerview.widget.AsyncListDiffer import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView +import org.oxycblt.auxio.util.logW /** * The base for all items in Auxio. Any datatype can derive this type and gain some behavior not @@ -171,3 +172,43 @@ abstract class SimpleItemCallback : DiffUtil.ItemCallback() { return oldItem.id == newItem.id } } + +abstract class ActivationAdapter : RecyclerView.Adapter() { + override fun onBindViewHolder(holder: VH, position: Int) = throw UnsupportedOperationException() + + override fun onBindViewHolder(holder: VH, position: Int, payloads: List) { + holder.itemView.isActivated = shouldActivateViewHolder(position) + } + + protected abstract fun shouldActivateViewHolder(position: Int): Boolean + + protected inline fun activateImpl( + currentList: List, + oldItem: T?, + newItem: T? + ) { + if (oldItem != null) { + val pos = currentList.indexOfFirst { item -> item.id == oldItem.id && item is T } + + if (pos > -1) { + notifyItemChanged(pos, PAYLOAD_ACTIVATION_CHANGED) + } else { + logW("oldItem was not in adapter data") + } + } + + if (newItem != null) { + val pos = currentList.indexOfFirst { item -> item is T && item.id == newItem.id } + + if (pos > -1) { + notifyItemChanged(pos, PAYLOAD_ACTIVATION_CHANGED) + } else { + logW("newItem was not in adapter data") + } + } + } + + companion object { + val PAYLOAD_ACTIVATION_CHANGED = Any() + } +} diff --git a/info/ARCHITECTURE.md b/info/ARCHITECTURE.md index d01342ee9..094af4a94 100644 --- a/info/ARCHITECTURE.md +++ b/info/ARCHITECTURE.md @@ -213,8 +213,7 @@ list similar to this: `Item being displayed | Header Item | Child Item | Child Item | Child Item...` Note that the actual dataset used is more complex once sorting and disc numbers is taken into -account. Item highlighting and certain shared ViewHolders are already managed by the `DetailAdapter` -super-class, which should be implemented by all adapters in the detail UI. +account. #### `.home` This package contains the components for the "home" UI in Auxio, or the UI that the user first sees