diff --git a/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/AddFragment.kt b/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/AddFragment.kt deleted file mode 100644 index e92501c836..0000000000 --- a/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/AddFragment.kt +++ /dev/null @@ -1,315 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2011-2024 Uwe Trottmann - -package com.battlelancer.seriesguide.shows.search.discover - -import android.app.Activity -import android.content.Context -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.animation.AnimationUtils -import android.widget.ArrayAdapter -import android.widget.GridView -import androidx.appcompat.widget.TooltipCompat -import androidx.core.view.ViewCompat -import androidx.core.view.isGone -import androidx.core.view.isVisible -import androidx.fragment.app.Fragment -import com.battlelancer.seriesguide.databinding.ItemAddshowBinding -import com.battlelancer.seriesguide.enums.NetworkResult -import com.battlelancer.seriesguide.shows.tools.AddShowTask.OnShowAddedEvent -import com.battlelancer.seriesguide.shows.tools.ShowTools2.OnShowRemovedEvent -import com.battlelancer.seriesguide.ui.widgets.EmptyView -import com.battlelancer.seriesguide.util.ImageTools -import com.battlelancer.seriesguide.util.ViewTools.setContextAndLongClickListener -import org.greenrobot.eventbus.EventBus -import org.greenrobot.eventbus.Subscribe -import org.greenrobot.eventbus.ThreadMode - -/** - * Super class for fragments displaying a list of shows that can be added to the database. - */ -abstract class AddFragment : Fragment() { - - class OnAddingShowEvent( - /** - * Is -1 if adding all shows this lists. - */ - val showTmdbId: Int - ) { - /** - * Sets TMDB id to -1 to indicate all shows of this are added. - */ - internal constructor() : this(-1) - } - - protected var searchResults: List? = null - private set - protected lateinit var adapter: AddAdapter - - /** - * Implementers should inflate their own layout and provide views through getters. - */ - abstract override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View - - abstract val contentContainer: View - abstract val progressBar: View - abstract val resultsGridView: GridView - abstract val emptyView: EmptyView - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - setupEmptyView(emptyView) - // basic setup of grid view - resultsGridView.emptyView = emptyView - // enable app bar scrolling out of view - ViewCompat.setNestedScrollingEnabled(resultsGridView, true) - } - - override fun onStart() { - super.onStart() - EventBus.getDefault().register(this) - } - - override fun onStop() { - super.onStop() - EventBus.getDefault().unregister(this) - } - - protected abstract fun setupEmptyView(buttonEmptyView: EmptyView) - - /** - * Changes the empty message. - */ - protected fun setEmptyMessage(message: CharSequence) { - emptyView.setMessage(message) - } - - fun updateSearchResults(searchResults: List) { - this.searchResults = searchResults - adapter.clear() - adapter.addAll(searchResults) - resultsGridView.adapter = adapter - } - - /** - * Hides the content container and shows a progress bar. - */ - protected fun setProgressVisible(visible: Boolean, animate: Boolean) { - if (animate) { - val fadeOut = AnimationUtils.loadAnimation(activity, android.R.anim.fade_out) - val fadeIn = AnimationUtils.loadAnimation(activity, android.R.anim.fade_in) - contentContainer.startAnimation(if (visible) fadeOut else fadeIn) - progressBar.startAnimation(if (visible) fadeIn else fadeOut) - } - contentContainer.visibility = if (visible) View.GONE else View.VISIBLE - progressBar.visibility = if (visible) View.VISIBLE else View.GONE - } - - /** - * Called if the user triggers adding a single new show through the add dialog. The show is not - * actually added, yet. - * - * See [onEvent(OnShowAddedEvent)][onEvent]. - */ - @Subscribe(threadMode = ThreadMode.MAIN) - fun onEvent(event: OnAddingShowEvent) { - if (event.showTmdbId > 0) { - adapter.setStateForTmdbId(event.showTmdbId, SearchResult.STATE_ADDING) - } - } - - @Subscribe(threadMode = ThreadMode.MAIN) - fun onEvent(event: OnShowAddedEvent) { - if (event.successful) { - setShowAdded(event.showTmdbId) - } else if (event.showTmdbId > 0) { - setShowNotAdded(event.showTmdbId) - } else { - adapter.setAllPendingNotAdded() - } - } - - @Subscribe(threadMode = ThreadMode.MAIN) - fun onEvent(event: OnShowRemovedEvent) { - if (event.resultCode == NetworkResult.SUCCESS) { - setShowNotAdded(event.showTmdbId) - } - } - - private fun setShowAdded(showTmdbId: Int) { - adapter.setStateForTmdbId(showTmdbId, SearchResult.STATE_ADDED) - } - - private fun setShowNotAdded(showTmdbId: Int) { - adapter.setStateForTmdbId(showTmdbId, SearchResult.STATE_ADD) - } - - class AddAdapter( - activity: Activity, - objects: List, - private val itemClickListener: ItemClickListener, - private val showWatchlistActions: Boolean - ) : ArrayAdapter(activity, 0, objects) { - - interface ItemClickListener { - fun onItemClick(item: SearchResult) - fun onAddClick(item: SearchResult) - fun onMoreOptionsClick(view: View, show: SearchResult) - } - - private fun getItemForShowTmdbId(showTmdbId: Int): SearchResult? { - val count = count - for (i in 0 until count) { - val item = getItem(i) - if (item != null && item.tmdbId == showTmdbId) { - return item - } - } - return null - } - - fun setStateForTmdbId(showTmdbId: Int, state: Int) { - val item = getItemForShowTmdbId(showTmdbId) - if (item != null) { - item.state = state - notifyDataSetChanged() - } - } - - fun setAllPendingNotAdded() { - val count = count - for (i in 0 until count) { - val item = getItem(i) - if (item != null && item.state == SearchResult.STATE_ADDING) { - item.state = SearchResult.STATE_ADD - } - } - notifyDataSetChanged() - } - - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { - val view: View - val holder: ViewHolder - if (convertView == null) { - holder = ViewHolder.inflate(parent, itemClickListener) - .also { it.binding.root.tag = it } - view = holder.binding.root - } else { - holder = convertView.tag as ViewHolder - view = convertView - } - - val item = getItem(position) - holder.bindTo(item, context, showWatchlistActions) - - return view - } - - class ViewHolder( - val binding: ItemAddshowBinding, - private val itemClickListener: ItemClickListener - ) { - private var item: SearchResult? = null - - init { - binding.root.setOnClickListener { - item?.let { itemClickListener.onItemClick(it) } - } - binding.addIndicatorAddShow.setOnAddClickListener { - item?.let { itemClickListener.onAddClick(it) } - } - binding.buttonItemAddMoreOptions.also { - TooltipCompat.setTooltipText(it, it.contentDescription) - } - } - - private fun onMoreOptionsClick(anchor: View) { - item?.let { - itemClickListener.onMoreOptionsClick(anchor, it) - } - } - - fun bindTo(item: SearchResult?, context: Context, showWatchlistActions: Boolean) { - this.item = item - - if (item == null) { - binding.addIndicatorAddShow.isGone = true - binding.textViewAddTitle.text = null - binding.textViewAddDescription.text = null - binding.imageViewAddPoster.setImageDrawable(null) - } else { - val canBeAdded = item.state == SearchResult.STATE_ADD - // Even if not displaying more options button, if not added, always display add action on - // long press for accessibility. - binding.root.apply { - if (showWatchlistActions || canBeAdded) { - setContextAndLongClickListener { - onMoreOptionsClick(binding.root) - } - } else { - // Remove listener so there is no long press feedback - setContextAndLongClickListener(null) - } - } - // Only display more options button when displaying remove from watchlist action - binding.buttonItemAddMoreOptions.apply { - if (showWatchlistActions) { - setOnClickListener { - onMoreOptionsClick(binding.buttonItemAddMoreOptions) - } - isVisible = true - } else { - setOnClickListener(null) - isGone = true - } - } - - // add indicator - val showTitle = item.title - binding.addIndicatorAddShow.apply { - setState(item.state) - setNameOfAssociatedItem(showTitle) - isVisible = true - } - - // set text properties immediately - binding.textViewAddTitle.text = showTitle - binding.textViewAddDescription.text = item.overview - - // only local shows will have a poster path set - // try to fall back to the TMDB poster for all others - val posterUrl = ImageTools.posterUrlOrResolve( - item.posterPath, - item.tmdbId, - item.language, - context - ) - ImageTools.loadShowPosterUrlResizeCrop( - context, binding.imageViewAddPoster, - posterUrl - ) - } - } - - companion object { - fun inflate(parent: ViewGroup, itemClickListener: ItemClickListener) = - ViewHolder( - ItemAddshowBinding.inflate( - LayoutInflater.from(parent.context), - parent, - false - ), - itemClickListener - ) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/AddShowDialogFragment.kt b/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/AddShowDialogFragment.kt index f1ffb2050d..e262322fea 100644 --- a/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/AddShowDialogFragment.kt +++ b/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/AddShowDialogFragment.kt @@ -235,7 +235,7 @@ class AddShowDialogFragment : AppCompatDialogFragment() { // Not added, offer to add. binding.buttonPositive.setText(R.string.action_shows_add) binding.buttonPositive.setOnClickListener { - EventBus.getDefault().post(AddFragment.OnAddingShowEvent(showTmdbId)) + EventBus.getDefault().post(OnAddingShowEvent(showTmdbId)) addShowListener.onAddShow(SearchResult().also { it.tmdbId = showTmdbId it.title = show.title diff --git a/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/AddShowPopupMenu.kt b/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/AddShowPopupMenu.kt index 24f50324b1..edcf744c65 100644 --- a/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/AddShowPopupMenu.kt +++ b/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/AddShowPopupMenu.kt @@ -9,7 +9,6 @@ import android.view.MenuItem import android.view.View import androidx.appcompat.widget.PopupMenu import com.battlelancer.seriesguide.R -import com.battlelancer.seriesguide.shows.search.discover.AddFragment.OnAddingShowEvent import com.battlelancer.seriesguide.util.TaskManager import com.battlelancer.seriesguide.util.tasks.AddShowToWatchlistTask import com.battlelancer.seriesguide.util.tasks.RemoveShowFromWatchlistTask diff --git a/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/BaseAddShowsFragment.kt b/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/BaseAddShowsFragment.kt index fafd18a221..b977b57bb6 100644 --- a/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/BaseAddShowsFragment.kt +++ b/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/BaseAddShowsFragment.kt @@ -35,7 +35,7 @@ abstract class BaseAddShowsFragment : Fragment() { * actually added, yet. */ @Subscribe(threadMode = ThreadMode.MAIN) - fun onEventAddingShow(event: AddFragment.OnAddingShowEvent) { + fun onEventAddingShow(event: OnAddingShowEvent) { if (event.showTmdbId > 0) { setStateForTmdbId(event.showTmdbId, SearchResult.STATE_ADDING) } diff --git a/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/ItemAddShowClickListener.kt b/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/ItemAddShowClickListener.kt index 4f27b2f0bb..f778500737 100644 --- a/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/ItemAddShowClickListener.kt +++ b/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/ItemAddShowClickListener.kt @@ -44,7 +44,7 @@ open class ItemAddShowClickListener( } override fun onAddClick(item: SearchResult) { - EventBus.getDefault().post(AddFragment.OnAddingShowEvent(item.tmdbId)) + EventBus.getDefault().post(OnAddingShowEvent(item.tmdbId)) TaskManager.getInstance().performAddTask(context, item) } diff --git a/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/ItemAddShowViewHolder.kt b/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/ItemAddShowViewHolder.kt index 547a5eb18a..5ec1a1a207 100644 --- a/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/ItemAddShowViewHolder.kt +++ b/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/ItemAddShowViewHolder.kt @@ -74,10 +74,17 @@ class ItemAddShowViewHolder( } // image - ImageTools.loadShowPosterResizeCrop( - context, - binding.imageViewAddPoster, - item.posterPath + // If item is provided from Trakt source, it does not provide images, + // so need to resolve them. + val posterUrl = ImageTools.posterUrlOrResolve( + item.posterPath, + item.tmdbId, + item.language, + context + ) + ImageTools.loadShowPosterUrlResizeCrop( + context, binding.imageViewAddPoster, + posterUrl ) // context/long press listener and more options button diff --git a/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/OnAddingShowEvent.kt b/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/OnAddingShowEvent.kt new file mode 100644 index 0000000000..feb19d3d35 --- /dev/null +++ b/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/OnAddingShowEvent.kt @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Uwe Trottmann + +package com.battlelancer.seriesguide.shows.search.discover + +/** + * Event posted when a show is about to be added to the database. + */ +class OnAddingShowEvent( + /** + * Is -1 if adding all shows this lists. + */ + val showTmdbId: Int +) { + /** + * Sets TMDB id to -1 to indicate all shows of this are added. + */ + constructor() : this(-1) +} \ No newline at end of file diff --git a/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/TraktAddFragment.kt b/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/TraktAddFragment.kt index 429fd01bde..39f4fd09c8 100644 --- a/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/TraktAddFragment.kt +++ b/app/src/main/java/com/battlelancer/seriesguide/shows/search/discover/TraktAddFragment.kt @@ -3,6 +3,7 @@ package com.battlelancer.seriesguide.shows.search.discover +import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.Menu @@ -10,14 +11,20 @@ import android.view.MenuInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup +import android.view.animation.AnimationUtils +import android.widget.ArrayAdapter import android.widget.GridView import androidx.core.view.MenuProvider +import androidx.core.view.ViewCompat +import androidx.fragment.app.Fragment import androidx.lifecycle.Lifecycle import androidx.loader.app.LoaderManager import androidx.loader.content.Loader import com.battlelancer.seriesguide.R import com.battlelancer.seriesguide.databinding.FragmentAddshowTraktBinding -import com.battlelancer.seriesguide.ui.OverviewActivity +import com.battlelancer.seriesguide.enums.NetworkResult +import com.battlelancer.seriesguide.shows.tools.AddShowTask +import com.battlelancer.seriesguide.shows.tools.ShowTools2 import com.battlelancer.seriesguide.ui.widgets.EmptyView import com.battlelancer.seriesguide.util.TaskManager import com.battlelancer.seriesguide.util.ThemeUtils @@ -31,10 +38,24 @@ import java.util.LinkedList * Displays the watched shows, show collection or shows watchlist of the connected Trakt user for * the purpose of adding them. Shows on the watchlist can also be removed from the watchlist. */ -class TraktAddFragment : AddFragment() { +class TraktAddFragment : Fragment() { private var binding: FragmentAddshowTraktBinding? = null + private val contentContainer: View + get() = binding!!.containerAddContent + + private val progressBar: View + get() = binding!!.progressBarAdd + + private val resultsGridView: GridView + get() = binding!!.gridViewAdd + + private val emptyView: EmptyView + get() = binding!!.emptyViewAdd + private lateinit var listType: TraktAddLoader.Type + private var searchResults: List? = null + private lateinit var adapter: AddAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -50,21 +71,23 @@ class TraktAddFragment : AddFragment() { .also { binding = it } .root - override val contentContainer: View - get() = binding!!.containerAddContent - - override val progressBar: View - get() = binding!!.progressBarAdd - - override val resultsGridView: GridView - get() = binding!!.gridViewAdd - - override val emptyView: EmptyView - get() = binding!!.emptyViewAdd - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + emptyView.setButtonClickListener { + setProgressVisible(visible = true, animate = false) + LoaderManager.getInstance(this@TraktAddFragment) + .restartLoader( + ShowsTraktActivity.TRAKT_BASE_LOADER_ID + listType.ordinal, null, + traktAddCallbacks + ) + } + + // basic setup of grid view + resultsGridView.emptyView = emptyView + // enable app bar scrolling out of view + ViewCompat.setNestedScrollingEnabled(resultsGridView, true) + ThemeUtils.applyBottomPaddingForNavigationBar(resultsGridView) ThemeUtils.applyBottomMarginForNavigationBar(binding!!.textViewPoweredByAddShowTrakt) @@ -73,7 +96,7 @@ class TraktAddFragment : AddFragment() { // set up adapter adapter = AddAdapter( - requireActivity(), ArrayList(), itemClickListener, + requireContext(), ArrayList(), itemClickListener, listType == TraktAddLoader.Type.WATCHLIST ) @@ -92,26 +115,38 @@ class TraktAddFragment : AddFragment() { ) } - private val itemClickListener: AddAdapter.ItemClickListener = - object : AddAdapter.ItemClickListener { - override fun onItemClick(item: SearchResult) { - if (item.state != SearchResult.STATE_ADDING) { - if (item.state == SearchResult.STATE_ADDED) { - // already in library, open it - startActivity( - OverviewActivity.intentShowByTmdbId(requireContext(), item.tmdbId) - ) - } else { - // display more details in a dialog - AddShowDialogFragment.show(parentFragmentManager, item) - } - } - } + /** + * Hides the content container and shows a progress bar. + */ + private fun setProgressVisible(visible: Boolean, animate: Boolean) { + if (animate) { + val fadeOut = AnimationUtils.loadAnimation(activity, android.R.anim.fade_out) + val fadeIn = AnimationUtils.loadAnimation(activity, android.R.anim.fade_in) + contentContainer.startAnimation(if (visible) fadeOut else fadeIn) + progressBar.startAnimation(if (visible) fadeIn else fadeOut) + } + contentContainer.visibility = if (visible) View.GONE else View.VISIBLE + progressBar.visibility = if (visible) View.VISIBLE else View.GONE + } - override fun onAddClick(item: SearchResult) { - EventBus.getDefault().post(OnAddingShowEvent(item.tmdbId)) - TaskManager.getInstance().performAddTask(requireContext(), item) - } + override fun onStart() { + super.onStart() + EventBus.getDefault().register(this) + } + + override fun onStop() { + super.onStop() + EventBus.getDefault().unregister(this) + } + + override fun onDestroyView() { + super.onDestroyView() + binding = null + } + + private val itemClickListener + get() = object : + ItemAddShowClickListener(requireContext(), lifecycle, parentFragmentManager) { override fun onMoreOptionsClick(view: View, show: SearchResult) { AddShowPopupMenu(requireContext(), show, view).apply { @@ -154,11 +189,6 @@ class TraktAddFragment : AddFragment() { } } - override fun onDestroyView() { - super.onDestroyView() - binding = null - } - @Subscribe(threadMode = ThreadMode.MAIN) fun onEventMainThread(@Suppress("UNUSED_PARAMETER") event: ShowChangedEvent?) { if (listType == TraktAddLoader.Type.WATCHLIST) { @@ -171,17 +201,45 @@ class TraktAddFragment : AddFragment() { } } - override fun setupEmptyView(buttonEmptyView: EmptyView) { - buttonEmptyView.setButtonClickListener { - setProgressVisible(visible = true, animate = false) - LoaderManager.getInstance(this@TraktAddFragment) - .restartLoader( - ShowsTraktActivity.TRAKT_BASE_LOADER_ID + listType.ordinal, null, - traktAddCallbacks - ) + /** + * Called if the user triggers adding a single new show through the add dialog. The show is not + * actually added, yet. + * + * See [onEvent(OnShowAddedEvent)][onEvent]. + */ + @Subscribe(threadMode = ThreadMode.MAIN) + fun onEvent(event: OnAddingShowEvent) { + if (event.showTmdbId > 0) { + adapter.setStateForTmdbId(event.showTmdbId, SearchResult.STATE_ADDING) } } + @Subscribe(threadMode = ThreadMode.MAIN) + fun onEvent(event: AddShowTask.OnShowAddedEvent) { + if (event.successful) { + setShowAdded(event.showTmdbId) + } else if (event.showTmdbId > 0) { + setShowNotAdded(event.showTmdbId) + } else { + adapter.setAllPendingNotAdded() + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onEvent(event: ShowTools2.OnShowRemovedEvent) { + if (event.resultCode == NetworkResult.SUCCESS) { + setShowNotAdded(event.showTmdbId) + } + } + + private fun setShowAdded(showTmdbId: Int) { + adapter.setStateForTmdbId(showTmdbId, SearchResult.STATE_ADDED) + } + + private fun setShowNotAdded(showTmdbId: Int) { + adapter.setStateForTmdbId(showTmdbId, SearchResult.STATE_ADD) + } + private val traktAddCallbacks: LoaderManager.LoaderCallbacks = object : LoaderManager.LoaderCallbacks { override fun onCreateLoader(id: Int, args: Bundle?): Loader { @@ -192,9 +250,8 @@ class TraktAddFragment : AddFragment() { loader: Loader, data: TraktAddLoader.Result ) { - updateSearchResults(data.results) - setEmptyMessage(data.emptyText) - setProgressVisible(false, true) + updateSearchResults(data.results, data.emptyText) + setProgressVisible(visible = false, animate = true) } override fun onLoaderReset(loader: Loader) { @@ -202,6 +259,14 @@ class TraktAddFragment : AddFragment() { } } + private fun updateSearchResults(results: List, emptyText: CharSequence) { + this.searchResults = results + adapter.clear() + adapter.addAll(results) + resultsGridView.adapter = adapter + emptyView.setMessage(emptyText) + } + companion object { /** * Which Trakt list should be shown. Ordinal of one of [TraktAddLoader.Type]. @@ -218,4 +283,62 @@ class TraktAddFragment : AddFragment() { return f } } + + class AddAdapter( + context: Context, + objects: List, + private val itemClickListener: ItemAddShowViewHolder.ClickListener, + private val showWatchlistActions: Boolean + ) : ArrayAdapter(context, 0, objects) { + + private fun getItemForShowTmdbId(showTmdbId: Int): SearchResult? { + val count = count + for (i in 0 until count) { + val item = getItem(i) + if (item != null && item.tmdbId == showTmdbId) { + return item + } + } + return null + } + + fun setStateForTmdbId(showTmdbId: Int, state: Int) { + val item = getItemForShowTmdbId(showTmdbId) + if (item != null) { + item.state = state + notifyDataSetChanged() + } + } + + fun setAllPendingNotAdded() { + val count = count + for (i in 0 until count) { + val item = getItem(i) + if (item != null && item.state == SearchResult.STATE_ADDING) { + item.state = SearchResult.STATE_ADD + } + } + notifyDataSetChanged() + } + + override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { + val view: View + // Re-use ItemAddShowViewHolder, but not using the RecyclerView features + val holder: ItemAddShowViewHolder + if (convertView == null) { + holder = ItemAddShowViewHolder.create(parent, itemClickListener) + .also { it.itemView.tag = it } + view = holder.itemView + } else { + holder = convertView.tag as ItemAddShowViewHolder + view = convertView + } + + val item = getItem(position) + holder.bindTo(context, item, showWatchlistActions) + + return view + } + + } } \ No newline at end of file