Add a HeaderView binder
This commit is contained in:
parent
5f716f5008
commit
e81b1ef8c2
|
@ -1,114 +0,0 @@
|
|||
package org.moire.ultrasonic.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.moire.ultrasonic.domain.MusicDirectory;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class AlbumHeader
|
||||
{
|
||||
private boolean isAllVideo;
|
||||
private long totalDuration;
|
||||
private Set<String> artists;
|
||||
private Set<String> grandParents;
|
||||
private Set<String> genres;
|
||||
private Set<Integer> years;
|
||||
|
||||
public boolean getIsAllVideo()
|
||||
{
|
||||
return isAllVideo;
|
||||
}
|
||||
|
||||
public long getTotalDuration()
|
||||
{
|
||||
return totalDuration;
|
||||
}
|
||||
|
||||
public Set<String> getArtists()
|
||||
{
|
||||
return artists;
|
||||
}
|
||||
|
||||
public Set<String> getGrandParents()
|
||||
{
|
||||
return this.grandParents;
|
||||
}
|
||||
|
||||
public Set<String> getGenres()
|
||||
{
|
||||
return this.genres;
|
||||
}
|
||||
|
||||
public Set<Integer> getYears()
|
||||
{
|
||||
return this.years;
|
||||
}
|
||||
|
||||
public AlbumHeader()
|
||||
{
|
||||
this.artists = new HashSet<String>();
|
||||
this.grandParents = new HashSet<String>();
|
||||
this.genres = new HashSet<String>();
|
||||
this.years = new HashSet<Integer>();
|
||||
|
||||
this.isAllVideo = true;
|
||||
this.totalDuration = 0;
|
||||
}
|
||||
|
||||
public static AlbumHeader processEntries(Context context, Iterable<MusicDirectory.Entry> entries)
|
||||
{
|
||||
AlbumHeader albumHeader = new AlbumHeader();
|
||||
|
||||
for (MusicDirectory.Entry entry : entries)
|
||||
{
|
||||
if (!entry.isVideo())
|
||||
{
|
||||
albumHeader.isAllVideo = false;
|
||||
}
|
||||
|
||||
if (!entry.isDirectory())
|
||||
{
|
||||
if (Settings.getShouldUseFolderForArtistName())
|
||||
{
|
||||
albumHeader.processGrandParents(entry);
|
||||
}
|
||||
|
||||
if (entry.getArtist() != null)
|
||||
{
|
||||
Integer duration = entry.getDuration();
|
||||
|
||||
if (duration != null)
|
||||
{
|
||||
albumHeader.totalDuration += duration;
|
||||
}
|
||||
|
||||
albumHeader.artists.add(entry.getArtist());
|
||||
}
|
||||
|
||||
if (entry.getGenre() != null)
|
||||
{
|
||||
albumHeader.genres.add(entry.getGenre());
|
||||
}
|
||||
|
||||
if (entry.getYear() != null)
|
||||
{
|
||||
albumHeader.years.add(entry.getYear());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return albumHeader;
|
||||
}
|
||||
|
||||
private void processGrandParents(MusicDirectory.Entry entry)
|
||||
{
|
||||
String grandParent = Util.getGrandparent(entry.getPath());
|
||||
|
||||
if (grandParent != null)
|
||||
{
|
||||
this.grandParents.add(grandParent);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package org.moire.ultrasonic.util
|
||||
|
||||
import org.moire.ultrasonic.domain.Identifiable
|
||||
import org.moire.ultrasonic.domain.MusicDirectory
|
||||
import org.moire.ultrasonic.util.Settings.shouldUseFolderForArtistName
|
||||
import org.moire.ultrasonic.util.Util.getGrandparent
|
||||
import java.util.HashSet
|
||||
|
||||
class AlbumHeader(
|
||||
var entries: List<MusicDirectory.Entry>,
|
||||
var name: String,
|
||||
songCount: Int
|
||||
): Identifiable {
|
||||
var isAllVideo: Boolean
|
||||
private set
|
||||
|
||||
var totalDuration: Long
|
||||
private set
|
||||
|
||||
var childCount = 0
|
||||
|
||||
private val _artists: MutableSet<String>
|
||||
private val _grandParents: MutableSet<String>
|
||||
private val _genres: MutableSet<String>
|
||||
private val _years: MutableSet<Int>
|
||||
|
||||
val artists: Set<String>
|
||||
get() = _artists
|
||||
|
||||
val grandParents: Set<String>
|
||||
get() = _grandParents
|
||||
|
||||
val genres: Set<String>
|
||||
get() = _genres
|
||||
|
||||
val years: Set<Int>
|
||||
get() = _years
|
||||
|
||||
private fun processGrandParents(entry: MusicDirectory.Entry) {
|
||||
val grandParent = getGrandparent(entry.path)
|
||||
if (grandParent != null) {
|
||||
_grandParents.add(grandParent)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NestedBlockDepth")
|
||||
private fun processEntries(list: List<MusicDirectory.Entry>) {
|
||||
entries = list
|
||||
childCount = entries.size
|
||||
for (entry in entries) {
|
||||
if (!entry.isVideo) {
|
||||
isAllVideo = false
|
||||
}
|
||||
if (!entry.isDirectory) {
|
||||
if (shouldUseFolderForArtistName) {
|
||||
processGrandParents(entry)
|
||||
}
|
||||
if (entry.artist != null) {
|
||||
val duration = entry.duration
|
||||
if (duration != null) {
|
||||
totalDuration += duration.toLong()
|
||||
}
|
||||
_artists.add(entry.artist!!)
|
||||
}
|
||||
if (entry.genre != null) {
|
||||
_genres.add(entry.genre!!)
|
||||
}
|
||||
if (entry.year != null) {
|
||||
_years.add(entry.year!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
_artists = HashSet()
|
||||
_grandParents = HashSet()
|
||||
_genres = HashSet()
|
||||
_years = HashSet()
|
||||
|
||||
isAllVideo = true
|
||||
totalDuration = 0
|
||||
|
||||
processEntries(entries)
|
||||
}
|
||||
|
||||
override val id: String
|
||||
get() = "HEADER"
|
||||
|
||||
override val longId: Long
|
||||
get() = id.hashCode().toLong()
|
||||
|
||||
override fun compareTo(other: Identifiable): Int {
|
||||
return this.longId.compareTo(other.longId)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package org.moire.ultrasonic.adapters
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.drakeet.multitype.ItemViewBinder
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.subsonic.ImageLoaderProvider
|
||||
import org.moire.ultrasonic.util.AlbumHeader
|
||||
import org.moire.ultrasonic.util.Util
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.Random
|
||||
|
||||
|
||||
/**
|
||||
* This Binder can bind a list of entries into a Header
|
||||
*/
|
||||
class HeaderViewBinder(
|
||||
context: Context
|
||||
) : ItemViewBinder<AlbumHeader, HeaderViewBinder.ViewHolder>(), KoinComponent {
|
||||
|
||||
private val weakContext: WeakReference<Context> = WeakReference(context)
|
||||
private val random: Random = Random()
|
||||
private val imageLoaderProvider: ImageLoaderProvider by inject()
|
||||
|
||||
// Set our layout files
|
||||
val layout = R.layout.select_album_header
|
||||
|
||||
override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): ViewHolder {
|
||||
return ViewHolder(inflater.inflate(layout, parent, false))
|
||||
}
|
||||
|
||||
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
val coverArtView: ImageView = itemView.findViewById(R.id.select_album_art)
|
||||
val titleView: TextView = itemView.findViewById(R.id.select_album_title)
|
||||
val artistView: TextView = itemView.findViewById(R.id.select_album_artist)
|
||||
val durationView: TextView = itemView.findViewById(R.id.select_album_duration)
|
||||
val songCountView: TextView = itemView.findViewById(R.id.select_album_song_count)
|
||||
val yearView: TextView = itemView.findViewById(R.id.select_album_year)
|
||||
val genreView: TextView = itemView.findViewById(R.id.select_album_genre)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, item: AlbumHeader) {
|
||||
|
||||
val context = weakContext.get() ?: return
|
||||
val resources = context.resources
|
||||
|
||||
|
||||
val artworkSelection = random.nextInt(item.childCount)
|
||||
|
||||
imageLoaderProvider.getImageLoader().loadImage(
|
||||
holder.coverArtView, item.entries[artworkSelection], false,
|
||||
Util.getAlbumImageSize(context)
|
||||
)
|
||||
|
||||
holder.titleView.text = item.name
|
||||
|
||||
|
||||
// Don't show a header if all entries are videos
|
||||
if (item.isAllVideo) {
|
||||
return
|
||||
}
|
||||
|
||||
val artist: String = when {
|
||||
item.artists.size == 1 -> item.artists.iterator().next()
|
||||
item.grandParents.size == 1 -> item.grandParents.iterator().next()
|
||||
else -> context.resources.getString(R.string.common_various_artists)
|
||||
}
|
||||
holder.artistView.text = artist
|
||||
|
||||
|
||||
val genre: String = if (item.genres.size == 1) {
|
||||
item.genres.iterator().next()
|
||||
} else {
|
||||
context.resources.getString(R.string.common_multiple_genres)
|
||||
}
|
||||
|
||||
holder.genreView.text = genre
|
||||
|
||||
|
||||
val year: String = if (item.years.size == 1) {
|
||||
item.years.iterator().next().toString()
|
||||
} else {
|
||||
resources.getString(R.string.common_multiple_years)
|
||||
}
|
||||
|
||||
holder.yearView.text = year
|
||||
|
||||
|
||||
val songs = resources.getQuantityString(
|
||||
R.plurals.select_album_n_songs, item.childCount,
|
||||
item.childCount
|
||||
)
|
||||
holder.songCountView.text = songs
|
||||
|
||||
val duration = Util.formatTotalDuration(item.totalDuration)
|
||||
holder.durationView.text = duration
|
||||
}
|
||||
}
|
|
@ -1,11 +1,8 @@
|
|||
package org.moire.ultrasonic.adapters
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Checkable
|
||||
import androidx.recyclerview.selection.SelectionTracker
|
||||
import com.drakeet.multitype.ItemViewBinder
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
@ -14,7 +11,6 @@ import org.moire.ultrasonic.domain.Identifiable
|
|||
import org.moire.ultrasonic.domain.MusicDirectory
|
||||
import org.moire.ultrasonic.service.DownloadFile
|
||||
import org.moire.ultrasonic.service.Downloader
|
||||
import org.moire.ultrasonic.util.Settings
|
||||
|
||||
class TrackViewBinder(
|
||||
val selectedSet: MutableSet<Long>,
|
||||
|
|
|
@ -1,44 +1,27 @@
|
|||
package org.moire.ultrasonic.fragment
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.koin.core.component.inject
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.adapters.GenericRowAdapter
|
||||
import org.moire.ultrasonic.adapters.MultiTypeDiffAdapter
|
||||
import org.moire.ultrasonic.adapters.TrackViewBinder
|
||||
import org.moire.ultrasonic.domain.Identifiable
|
||||
import org.moire.ultrasonic.service.DownloadFile
|
||||
import org.moire.ultrasonic.service.Downloader
|
||||
import org.moire.ultrasonic.util.Util
|
||||
import org.moire.ultrasonic.view.SongViewHolder
|
||||
import java.util.TreeSet
|
||||
|
||||
class DownloadsFragment : GenericListFragment<DownloadFile, DownloadRowAdapter>() {
|
||||
class DownloadsFragment : MultiListFragment<DownloadFile, MultiTypeDiffAdapter<Identifiable>>() {
|
||||
|
||||
/**
|
||||
* The ViewModel to use to get the data
|
||||
*/
|
||||
override val listModel: DownloadListModel by viewModels()
|
||||
|
||||
/**
|
||||
* The id of the main layout
|
||||
*/
|
||||
override val mainLayout: Int = R.layout.generic_list
|
||||
|
||||
/**
|
||||
* The id of the refresh view
|
||||
*/
|
||||
override val refreshListId: Int = R.id.generic_list_refresh
|
||||
|
||||
/**
|
||||
* The id of the RecyclerView
|
||||
*/
|
||||
override val recyclerViewId = R.id.generic_list_recycler
|
||||
|
||||
/**
|
||||
* The id of the target in the navigation graph where we should go,
|
||||
* after the user has clicked on an item
|
||||
|
@ -56,15 +39,17 @@ class DownloadsFragment : GenericListFragment<DownloadFile, DownloadRowAdapter>(
|
|||
/**
|
||||
* Provide the Adapter for the RecyclerView with a lazy delegate
|
||||
*/
|
||||
override val viewAdapter: DownloadRowAdapter by lazy {
|
||||
DownloadRowAdapter(
|
||||
liveDataItems.value ?: listOf(),
|
||||
{ entry -> onItemClick(entry) },
|
||||
{ menuItem, entry -> onContextMenuItemSelected(menuItem, entry) },
|
||||
onMusicFolderUpdate,
|
||||
requireContext(),
|
||||
viewLifecycleOwner
|
||||
override val viewAdapter: MultiTypeDiffAdapter<Identifiable> by lazy {
|
||||
val adapter = MultiTypeDiffAdapter<Identifiable>()
|
||||
adapter.register(
|
||||
TrackViewBinder(
|
||||
selectedSet = TreeSet(),
|
||||
checkable = false,
|
||||
draggable = false,
|
||||
context = requireContext()
|
||||
)
|
||||
)
|
||||
adapter
|
||||
}
|
||||
|
||||
override fun onContextMenuItemSelected(menuItem: MenuItem, item: DownloadFile): Boolean {
|
||||
|
@ -81,63 +66,6 @@ class DownloadsFragment : GenericListFragment<DownloadFile, DownloadRowAdapter>(
|
|||
}
|
||||
}
|
||||
|
||||
class DownloadRowAdapter(
|
||||
itemList: List<DownloadFile>,
|
||||
onItemClick: (DownloadFile) -> Unit,
|
||||
onContextMenuClick: (MenuItem, DownloadFile) -> Boolean,
|
||||
onMusicFolderUpdate: (String?) -> Unit,
|
||||
val context: Context,
|
||||
val lifecycleOwner: LifecycleOwner
|
||||
) : GenericRowAdapter<DownloadFile>(
|
||||
onItemClick,
|
||||
onContextMenuClick,
|
||||
onMusicFolderUpdate
|
||||
) {
|
||||
|
||||
init {
|
||||
super.submitList(itemList)
|
||||
}
|
||||
|
||||
|
||||
// Set our layout files
|
||||
override val layout = R.layout.song_list_item
|
||||
override val contextMenuLayout = R.menu.artist_context_menu
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is SongViewHolder) {
|
||||
val downloadFile = currentList[position]
|
||||
|
||||
holder.setSong(downloadFile, checkable = false, draggable = false)
|
||||
|
||||
// Observe download status
|
||||
downloadFile.status.observe(
|
||||
lifecycleOwner,
|
||||
{
|
||||
holder.updateDownloadStatus(downloadFile)
|
||||
}
|
||||
)
|
||||
|
||||
downloadFile.progress.observe(
|
||||
lifecycleOwner,
|
||||
{
|
||||
holder.updateDownloadStatus(downloadFile)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates an instance of our ViewHolder class
|
||||
*/
|
||||
override fun newViewHolder(view: View): RecyclerView.ViewHolder {
|
||||
return SongViewHolder(view, context)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class DownloadListModel(application: Application) : GenericListModel(application) {
|
||||
private val downloader by inject<Downloader>()
|
||||
|
|
|
@ -71,20 +71,20 @@ abstract class MultiListFragment<T : Identifiable, TA : MultiTypeAdapter> : Frag
|
|||
*/
|
||||
protected abstract val itemClickTarget: Int
|
||||
|
||||
/**
|
||||
* The id of the RecyclerView
|
||||
*/
|
||||
protected abstract val recyclerViewId: Int
|
||||
|
||||
/**
|
||||
* The id of the main layout
|
||||
*/
|
||||
abstract val mainLayout: Int
|
||||
open val mainLayout: Int = R.layout.generic_list
|
||||
|
||||
/**
|
||||
* The id of the refresh view
|
||||
*/
|
||||
abstract val refreshListId: Int
|
||||
open val refreshListId: Int = R.id.generic_list_refresh
|
||||
|
||||
/**
|
||||
* The id of the RecyclerView
|
||||
*/
|
||||
open val recyclerViewId = R.id.generic_list_recycler
|
||||
|
||||
/**
|
||||
* The observer to be called if the available music folders have changed
|
||||
|
|
|
@ -31,13 +31,13 @@ import kotlinx.coroutines.CoroutineExceptionHandler
|
|||
import kotlinx.coroutines.launch
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.adapters.HeaderViewBinder
|
||||
import org.moire.ultrasonic.adapters.MultiTypeDiffAdapter
|
||||
import org.moire.ultrasonic.adapters.TrackViewBinder
|
||||
import org.moire.ultrasonic.adapters.TrackViewHolder
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline
|
||||
import org.moire.ultrasonic.domain.Identifiable
|
||||
import org.moire.ultrasonic.domain.MusicDirectory
|
||||
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.getTitle
|
||||
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle
|
||||
import org.moire.ultrasonic.service.MediaPlayerController
|
||||
import org.moire.ultrasonic.subsonic.NetworkAndStorageChecker
|
||||
|
@ -51,17 +51,18 @@ import org.moire.ultrasonic.util.Settings
|
|||
import org.moire.ultrasonic.util.Util
|
||||
import timber.log.Timber
|
||||
import java.util.Collections
|
||||
import java.util.Random
|
||||
import java.util.TreeSet
|
||||
|
||||
/**
|
||||
* Displays a group of tracks, eg. the songs of an album, of a playlist etc.
|
||||
* TODO: Refactor this fragment and model to extend the GenericListFragment
|
||||
* TODO: Move Clickhandler into ViewBinders
|
||||
* TODO: Migrate Album/artistsRow
|
||||
* TODO: Wrong count (selectall)
|
||||
* TODO: Handle updates (playstatus, download status)
|
||||
*/
|
||||
class TrackCollectionFragment :
|
||||
MultiListFragment<MusicDirectory.Entry, MultiTypeDiffAdapter<Identifiable>>() {
|
||||
|
||||
private var header: View? = null
|
||||
private var albumButtons: View? = null
|
||||
private var emptyView: TextView? = null
|
||||
private var selectButton: ImageView? = null
|
||||
|
@ -84,7 +85,6 @@ class TrackCollectionFragment :
|
|||
private var cancellationToken: CancellationToken? = null
|
||||
|
||||
override val listModel: TrackCollectionModel by viewModels()
|
||||
private val random: Random = Random()
|
||||
|
||||
private var selectedSet: TreeSet<Long> = TreeSet()
|
||||
|
||||
|
@ -136,11 +136,6 @@ class TrackCollectionFragment :
|
|||
updateDisplay(true)
|
||||
}
|
||||
|
||||
header = LayoutInflater.from(context).inflate(
|
||||
R.layout.select_album_header, listView,
|
||||
false
|
||||
)
|
||||
|
||||
listModel.currentList.observe(viewLifecycleOwner, defaultObserver)
|
||||
listModel.songsForGenre.observe(viewLifecycleOwner, songsForGenreObserver)
|
||||
|
||||
|
@ -231,17 +226,25 @@ class TrackCollectionFragment :
|
|||
}
|
||||
|
||||
|
||||
viewAdapter.register(
|
||||
HeaderViewBinder(
|
||||
context = requireContext()
|
||||
)
|
||||
)
|
||||
|
||||
viewAdapter.register(
|
||||
TrackViewBinder(
|
||||
selectedSet = selectedSet,
|
||||
checkable = true,
|
||||
draggable = false,
|
||||
context = context!!
|
||||
context = requireContext()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
enableButtons()
|
||||
|
||||
// Loads the data
|
||||
updateDisplay(false)
|
||||
}
|
||||
|
||||
|
@ -253,6 +256,7 @@ class TrackCollectionFragment :
|
|||
}
|
||||
|
||||
private fun updateDisplay(refresh: Boolean) {
|
||||
// FIXME: Use refresh
|
||||
getLiveData(requireArguments())
|
||||
}
|
||||
|
||||
|
@ -383,12 +387,32 @@ class TrackCollectionFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private val viewHolders: List<TrackViewHolder>
|
||||
get() {
|
||||
val list: MutableList<TrackViewHolder> = mutableListOf()
|
||||
for (i in 0 until listView!!.childCount) {
|
||||
val vh = listView!!.findViewHolderForAdapterPosition(i)
|
||||
if (vh is TrackViewHolder) {
|
||||
list.add(vh)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
private val childCount: Int
|
||||
get() {
|
||||
if (listModel.showHeader) {
|
||||
return listView!!.childCount - 1
|
||||
} else {
|
||||
return listView!!.childCount
|
||||
}
|
||||
}
|
||||
|
||||
private fun playAll(shuffle: Boolean = false, append: Boolean = false) {
|
||||
var hasSubFolders = false
|
||||
|
||||
for (i in 0 until listView!!.childCount) {
|
||||
val vh = listView!!.findViewHolderForAdapterPosition(i) as TrackViewHolder?
|
||||
val entry = vh?.entry
|
||||
for (vh in viewHolders) {
|
||||
val entry = vh.entry
|
||||
if (entry != null && entry.isDirectory) {
|
||||
hasSubFolders = true
|
||||
break
|
||||
|
@ -427,20 +451,19 @@ class TrackCollectionFragment :
|
|||
}
|
||||
|
||||
private fun selectAllOrNone() {
|
||||
val someUnselected = selectedSet.size < listView!!.childCount
|
||||
val someUnselected = selectedSet.size < childCount
|
||||
|
||||
selectAll(someUnselected, true)
|
||||
|
||||
}
|
||||
|
||||
private fun selectAll(selected: Boolean, toast: Boolean) {
|
||||
val count = listView!!.childCount
|
||||
|
||||
var selectedCount = 0
|
||||
|
||||
listView!!
|
||||
|
||||
for (i in 0 until count) {
|
||||
val vh = listView!!.findViewHolderForAdapterPosition(i) as TrackViewHolder
|
||||
for (vh in viewHolders) {
|
||||
val entry = vh.entry
|
||||
|
||||
if (entry != null && !entry.isDirectory && !entry.isVideo) {
|
||||
|
@ -579,16 +602,19 @@ class TrackCollectionFragment :
|
|||
|
||||
private val defaultObserver = Observer(this::updateInterfaceWithEntries)
|
||||
|
||||
private fun updateInterfaceWithEntries(list: List<MusicDirectory.Entry>) {
|
||||
private fun updateInterfaceWithEntries(newList: List<MusicDirectory.Entry>) {
|
||||
|
||||
val entryList: MutableList<MusicDirectory.Entry> = newList.toMutableList()
|
||||
|
||||
if (listModel.currentListIsSortable && Settings.shouldSortByDisc) {
|
||||
Collections.sort(list, EntryByDiscAndTrackComparator())
|
||||
Collections.sort(entryList, EntryByDiscAndTrackComparator())
|
||||
}
|
||||
|
||||
|
||||
var allVideos = true
|
||||
var songCount = 0
|
||||
|
||||
for (entry in list) {
|
||||
for (entry in entryList) {
|
||||
if (!entry.isVideo) {
|
||||
allVideos = false
|
||||
}
|
||||
|
@ -600,18 +626,6 @@ class TrackCollectionFragment :
|
|||
val listSize = requireArguments().getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0)
|
||||
|
||||
if (songCount > 0) {
|
||||
// if (listModel.showHeader) {
|
||||
// val intentAlbumName = requireArguments().getString(Constants.INTENT_EXTRA_NAME_NAME)
|
||||
// val directoryName = musicDirectory.name
|
||||
// val header = createHeader(
|
||||
// entries, intentAlbumName ?: directoryName,
|
||||
// songCount
|
||||
// )
|
||||
//// if (header != null && listView!!.headerViewsCount == 0) {
|
||||
//// listView!!.addHeaderView(header, null, false)
|
||||
//// }
|
||||
// }
|
||||
|
||||
pinButton!!.visibility = View.VISIBLE
|
||||
unpinButton!!.visibility = View.VISIBLE
|
||||
downloadButton!!.visibility = View.VISIBLE
|
||||
|
@ -653,7 +667,7 @@ class TrackCollectionFragment :
|
|||
playNextButton!!.visibility = View.GONE
|
||||
playLastButton!!.visibility = View.GONE
|
||||
|
||||
if (listSize == 0 || list.size < listSize) {
|
||||
if (listSize == 0 || entryList.size < listSize) {
|
||||
albumButtons!!.visibility = View.GONE
|
||||
} else {
|
||||
moreButton!!.visibility = View.VISIBLE
|
||||
|
@ -666,7 +680,7 @@ class TrackCollectionFragment :
|
|||
Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE
|
||||
)
|
||||
|
||||
playAllButtonVisible = !(isAlbumList || list.isEmpty()) && !allVideos
|
||||
playAllButtonVisible = !(isAlbumList || entryList.isEmpty()) && !allVideos
|
||||
shareButtonVisible = !isOffline() && songCount > 0
|
||||
|
||||
// listView!!.removeHeaderView(emptyView!!)
|
||||
|
@ -684,7 +698,18 @@ class TrackCollectionFragment :
|
|||
shareButton!!.isVisible = shareButtonVisible
|
||||
}
|
||||
|
||||
viewAdapter.submitList(list)
|
||||
|
||||
if (songCount > 0 && listModel.showHeader) {
|
||||
var name = listModel.currentDirectory.value?.name
|
||||
val intentAlbumName = requireArguments().getString(Constants.INTENT_EXTRA_NAME_NAME, "Name")!!
|
||||
val albumHeader = AlbumHeader(newList, name?: intentAlbumName, songCount)
|
||||
val mixedList: MutableList<Identifiable> = mutableListOf(albumHeader)
|
||||
mixedList.addAll(entryList)
|
||||
viewAdapter.submitList(mixedList)
|
||||
} else {
|
||||
viewAdapter.submitList(entryList)
|
||||
}
|
||||
|
||||
|
||||
val playAll = requireArguments().getBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false)
|
||||
if (playAll && songCount > 0) {
|
||||
|
@ -699,77 +724,10 @@ class TrackCollectionFragment :
|
|||
|
||||
}
|
||||
|
||||
private fun createHeader(
|
||||
entries: List<MusicDirectory.Entry>,
|
||||
name: CharSequence?,
|
||||
songCount: Int
|
||||
): View? {
|
||||
val coverArtView = header!!.findViewById<View>(R.id.select_album_art) as ImageView
|
||||
val artworkSelection = random.nextInt(entries.size)
|
||||
imageLoaderProvider.getImageLoader().loadImage(
|
||||
coverArtView, entries[artworkSelection], false,
|
||||
Util.getAlbumImageSize(context)
|
||||
)
|
||||
|
||||
val albumHeader = AlbumHeader.processEntries(context, entries)
|
||||
|
||||
val titleView = header!!.findViewById<View>(R.id.select_album_title) as TextView
|
||||
titleView.text = name ?: getTitle(this@TrackCollectionFragment) // getActionBarSubtitle());
|
||||
|
||||
// Don't show a header if all entries are videos
|
||||
if (albumHeader.isAllVideo) {
|
||||
return null
|
||||
}
|
||||
|
||||
val artistView = header!!.findViewById<TextView>(R.id.select_album_artist)
|
||||
|
||||
val artist: String = when {
|
||||
albumHeader.artists.size == 1 -> albumHeader.artists.iterator().next()
|
||||
albumHeader.grandParents.size == 1 -> albumHeader.grandParents.iterator().next()
|
||||
else -> resources.getString(R.string.common_various_artists)
|
||||
}
|
||||
|
||||
artistView.text = artist
|
||||
|
||||
val genreView = header!!.findViewById<TextView>(R.id.select_album_genre)
|
||||
|
||||
val genre: String = if (albumHeader.genres.size == 1)
|
||||
albumHeader.genres.iterator().next()
|
||||
else
|
||||
resources.getString(R.string.common_multiple_genres)
|
||||
|
||||
genreView.text = genre
|
||||
|
||||
val yearView = header!!.findViewById<TextView>(R.id.select_album_year)
|
||||
|
||||
val year: String = if (albumHeader.years.size == 1)
|
||||
albumHeader.years.iterator().next().toString()
|
||||
else
|
||||
resources.getString(R.string.common_multiple_years)
|
||||
|
||||
yearView.text = year
|
||||
|
||||
val songCountView = header!!.findViewById<TextView>(R.id.select_album_song_count)
|
||||
val songs = resources.getQuantityString(
|
||||
R.plurals.select_album_n_songs, songCount,
|
||||
songCount
|
||||
)
|
||||
songCountView.text = songs
|
||||
|
||||
val duration = Util.formatTotalDuration(albumHeader.totalDuration)
|
||||
|
||||
val durationView = header!!.findViewById<TextView>(R.id.select_album_duration)
|
||||
durationView.text = duration
|
||||
|
||||
return header
|
||||
}
|
||||
|
||||
private fun getSelectedSongs(): MutableList<MusicDirectory.Entry> {
|
||||
val songs: MutableList<MusicDirectory.Entry> = mutableListOf()
|
||||
|
||||
for (i in 0 until listView!!.childCount) {
|
||||
val vh = listView!!.findViewHolderForAdapterPosition(i) as TrackViewHolder? ?: continue
|
||||
|
||||
for (vh in viewHolders) {
|
||||
if (vh.isChecked) {
|
||||
songs.add(vh.entry!!)
|
||||
}
|
||||
|
|
|
@ -871,7 +871,7 @@ object Util {
|
|||
|
||||
val descriptionBuilder = MediaDescriptionCompat.Builder()
|
||||
val desc = readableEntryDescription(song)
|
||||
var title = ""
|
||||
val title: String
|
||||
|
||||
if (groupNameId != null)
|
||||
descriptionBuilder.setExtras(
|
||||
|
|
|
@ -1,316 +1,316 @@
|
|||
package org.moire.ultrasonic.view
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.AnimationDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.view.View
|
||||
import android.widget.Checkable
|
||||
import android.widget.CheckedTextView
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.get
|
||||
import org.koin.core.component.inject
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider
|
||||
import org.moire.ultrasonic.domain.MusicDirectory
|
||||
import org.moire.ultrasonic.featureflags.Feature
|
||||
import org.moire.ultrasonic.featureflags.FeatureStorage
|
||||
import org.moire.ultrasonic.fragment.DownloadRowAdapter
|
||||
import org.moire.ultrasonic.service.DownloadFile
|
||||
import org.moire.ultrasonic.service.MediaPlayerController
|
||||
import org.moire.ultrasonic.service.MusicServiceFactory
|
||||
import org.moire.ultrasonic.util.Settings
|
||||
import org.moire.ultrasonic.util.Util
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Used to display songs and videos in a `ListView`.
|
||||
* TODO: Video List item
|
||||
*/
|
||||
class SongViewHolder(view: View, context: Context) : RecyclerView.ViewHolder(view), Checkable, KoinComponent {
|
||||
var check: CheckedTextView = view.findViewById(R.id.song_check)
|
||||
var rating: LinearLayout = view.findViewById(R.id.song_rating)
|
||||
var fiveStar1: ImageView = view.findViewById(R.id.song_five_star_1)
|
||||
var fiveStar2: ImageView = view.findViewById(R.id.song_five_star_2)
|
||||
var fiveStar3: ImageView = view.findViewById(R.id.song_five_star_3)
|
||||
var fiveStar4: ImageView = view.findViewById(R.id.song_five_star_4)
|
||||
var fiveStar5: ImageView = view.findViewById(R.id.song_five_star_5)
|
||||
var star: ImageView = view.findViewById(R.id.song_star)
|
||||
var drag: ImageView = view.findViewById(R.id.song_drag)
|
||||
var track: TextView = view.findViewById(R.id.song_track)
|
||||
var title: TextView = view.findViewById(R.id.song_title)
|
||||
var artist: TextView = view.findViewById(R.id.song_artist)
|
||||
var duration: TextView = view.findViewById(R.id.song_duration)
|
||||
var status: TextView = view.findViewById(R.id.song_status)
|
||||
|
||||
var entry: MusicDirectory.Entry? = null
|
||||
private set
|
||||
var downloadFile: DownloadFile? = null
|
||||
private set
|
||||
|
||||
private var isMaximized = false
|
||||
private var leftImage: Drawable? = null
|
||||
private var previousLeftImageType: ImageType? = null
|
||||
private var previousRightImageType: ImageType? = null
|
||||
private var leftImageType: ImageType? = null
|
||||
private var playing = false
|
||||
|
||||
private val features: FeatureStorage = get()
|
||||
private val useFiveStarRating: Boolean = features.isFeatureEnabled(Feature.FIVE_STAR_RATING)
|
||||
private val mediaPlayerController: MediaPlayerController by inject()
|
||||
|
||||
fun setSong(file: DownloadFile, checkable: Boolean, draggable: Boolean) {
|
||||
val song = file.song
|
||||
downloadFile = file
|
||||
entry = song
|
||||
|
||||
val entryDescription = Util.readableEntryDescription(song)
|
||||
|
||||
artist.text = entryDescription.artist
|
||||
title.text = entryDescription.title
|
||||
duration.text = entryDescription.duration
|
||||
|
||||
|
||||
if (Settings.shouldShowTrackNumber && song.track != null && song.track!! > 0) {
|
||||
track.text = entryDescription.trackNumber
|
||||
} else {
|
||||
track.isVisible = false
|
||||
}
|
||||
|
||||
check.isVisible = (checkable && !song.isVideo)
|
||||
drag.isVisible = draggable
|
||||
|
||||
if (ActiveServerProvider.isOffline()) {
|
||||
star.isVisible = false
|
||||
rating.isVisible = false
|
||||
} else {
|
||||
setupStarButtons(song)
|
||||
}
|
||||
update()
|
||||
}
|
||||
|
||||
private fun setupStarButtons(song: MusicDirectory.Entry) {
|
||||
if (useFiveStarRating) {
|
||||
star.isVisible = false
|
||||
val rating = if (song.userRating == null) 0 else song.userRating!!
|
||||
fiveStar1.setImageDrawable(
|
||||
if (rating > 0) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
)
|
||||
fiveStar2.setImageDrawable(
|
||||
if (rating > 1) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
)
|
||||
fiveStar3.setImageDrawable(
|
||||
if (rating > 2) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
)
|
||||
fiveStar4.setImageDrawable(
|
||||
if (rating > 3) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
)
|
||||
fiveStar5.setImageDrawable(
|
||||
if (rating > 4) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
)
|
||||
} else {
|
||||
rating.isVisible = false
|
||||
star.setImageDrawable(
|
||||
if (song.starred) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
)
|
||||
|
||||
star.setOnClickListener {
|
||||
val isStarred = song.starred
|
||||
val id = song.id
|
||||
|
||||
if (!isStarred) {
|
||||
star.setImageDrawable(DownloadRowAdapter.starDrawable)
|
||||
song.starred = true
|
||||
} else {
|
||||
star.setImageDrawable(DownloadRowAdapter.starHollowDrawable)
|
||||
song.starred = false
|
||||
}
|
||||
Thread {
|
||||
val musicService = MusicServiceFactory.getMusicService()
|
||||
try {
|
||||
if (!isStarred) {
|
||||
musicService.star(id, null, null)
|
||||
} else {
|
||||
musicService.unstar(id, null, null)
|
||||
}
|
||||
} catch (all: Exception) {
|
||||
Timber.e(all)
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Synchronized
|
||||
// TDOD: Should be removed
|
||||
fun update() {
|
||||
val song = entry ?: return
|
||||
|
||||
updateDownloadStatus(downloadFile!!)
|
||||
|
||||
if (entry?.starred != true) {
|
||||
if (star.drawable !== DownloadRowAdapter.starHollowDrawable) {
|
||||
star.setImageDrawable(DownloadRowAdapter.starHollowDrawable)
|
||||
}
|
||||
} else {
|
||||
if (star.drawable !== DownloadRowAdapter.starDrawable) {
|
||||
star.setImageDrawable(DownloadRowAdapter.starDrawable)
|
||||
}
|
||||
}
|
||||
|
||||
val rating = entry?.userRating ?: 0
|
||||
fiveStar1.setImageDrawable(
|
||||
if (rating > 0) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
)
|
||||
fiveStar2.setImageDrawable(
|
||||
if (rating > 1) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
)
|
||||
fiveStar3.setImageDrawable(
|
||||
if (rating > 2) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
)
|
||||
fiveStar4.setImageDrawable(
|
||||
if (rating > 3) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
)
|
||||
fiveStar5.setImageDrawable(
|
||||
if (rating > 4) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
)
|
||||
|
||||
val playing = mediaPlayerController.currentPlaying === downloadFile
|
||||
|
||||
if (playing) {
|
||||
if (!this.playing) {
|
||||
this.playing = true
|
||||
title.setCompoundDrawablesWithIntrinsicBounds(
|
||||
DownloadRowAdapter.playingImage, null, null, null
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (this.playing) {
|
||||
this.playing = false
|
||||
title.setCompoundDrawablesWithIntrinsicBounds(
|
||||
0, 0, 0, 0
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateDownloadStatus(downloadFile: DownloadFile) {
|
||||
|
||||
if (downloadFile.isWorkDone) {
|
||||
val newLeftImageType =
|
||||
if (downloadFile.isSaved) ImageType.Pin else ImageType.Downloaded
|
||||
|
||||
if (leftImageType != newLeftImageType) {
|
||||
leftImage = if (downloadFile.isSaved) {
|
||||
DownloadRowAdapter.pinImage
|
||||
} else {
|
||||
DownloadRowAdapter.downloadedImage
|
||||
}
|
||||
leftImageType = newLeftImageType
|
||||
}
|
||||
} else {
|
||||
leftImageType = ImageType.None
|
||||
leftImage = null
|
||||
}
|
||||
|
||||
val rightImageType: ImageType
|
||||
val rightImage: Drawable?
|
||||
|
||||
if (downloadFile.isDownloading && !downloadFile.isDownloadCancelled) {
|
||||
status.text = Util.formatPercentage(downloadFile.progress.value!!)
|
||||
|
||||
rightImageType = ImageType.Downloading
|
||||
rightImage = DownloadRowAdapter.downloadingImage
|
||||
} else {
|
||||
rightImageType = ImageType.None
|
||||
rightImage = null
|
||||
|
||||
val statusText = status.text
|
||||
if (!statusText.isNullOrEmpty()) status.text = null
|
||||
}
|
||||
|
||||
if (previousLeftImageType != leftImageType || previousRightImageType != rightImageType) {
|
||||
previousLeftImageType = leftImageType
|
||||
previousRightImageType = rightImageType
|
||||
|
||||
status.setCompoundDrawablesWithIntrinsicBounds(
|
||||
leftImage, null, rightImage, null
|
||||
)
|
||||
|
||||
if (rightImage === DownloadRowAdapter.downloadingImage) {
|
||||
// FIXME
|
||||
val frameAnimation = rightImage as AnimationDrawable?
|
||||
|
||||
frameAnimation?.setVisible(true, true)
|
||||
frameAnimation?.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fun updateDownloadStatus2(
|
||||
// downloadFile: DownloadFile,
|
||||
// ) {
|
||||
//package org.moire.ultrasonic.view
|
||||
//
|
||||
// var image: Drawable? = null
|
||||
//import android.content.Context
|
||||
//import android.graphics.drawable.AnimationDrawable
|
||||
//import android.graphics.drawable.Drawable
|
||||
//import android.view.View
|
||||
//import android.widget.Checkable
|
||||
//import android.widget.CheckedTextView
|
||||
//import android.widget.ImageView
|
||||
//import android.widget.LinearLayout
|
||||
//import android.widget.TextView
|
||||
//import androidx.core.view.isVisible
|
||||
//import androidx.recyclerview.widget.RecyclerView
|
||||
//import org.koin.core.component.KoinComponent
|
||||
//import org.koin.core.component.get
|
||||
//import org.koin.core.component.inject
|
||||
//import org.moire.ultrasonic.R
|
||||
//import org.moire.ultrasonic.data.ActiveServerProvider
|
||||
//import org.moire.ultrasonic.domain.MusicDirectory
|
||||
//import org.moire.ultrasonic.featureflags.Feature
|
||||
//import org.moire.ultrasonic.featureflags.FeatureStorage
|
||||
//import org.moire.ultrasonic.fragment.DownloadRowAdapter
|
||||
//import org.moire.ultrasonic.service.DownloadFile
|
||||
//import org.moire.ultrasonic.service.MediaPlayerController
|
||||
//import org.moire.ultrasonic.service.MusicServiceFactory
|
||||
//import org.moire.ultrasonic.util.Settings
|
||||
//import org.moire.ultrasonic.util.Util
|
||||
//import timber.log.Timber
|
||||
//
|
||||
// when (downloadFile.status.value) {
|
||||
// DownloadStatus.DONE -> {
|
||||
// image = if (downloadFile.isSaved) DownloadRowAdapter.pinImage else DownloadRowAdapter.downloadedImage
|
||||
// status.text = null
|
||||
// }
|
||||
// DownloadStatus.DOWNLOADING -> {
|
||||
// status.text = Util.formatPercentage(downloadFile.progress.value!!)
|
||||
// image = DownloadRowAdapter.downloadingImage
|
||||
// }
|
||||
// else -> {
|
||||
// status.text = null
|
||||
// }
|
||||
///**
|
||||
// * Used to display songs and videos in a `ListView`.
|
||||
// * TODO: Video List item
|
||||
// */
|
||||
//class SongViewHolder(view: View, context: Context) : RecyclerView.ViewHolder(view), Checkable, KoinComponent {
|
||||
// var check: CheckedTextView = view.findViewById(R.id.song_check)
|
||||
// var rating: LinearLayout = view.findViewById(R.id.song_rating)
|
||||
// var fiveStar1: ImageView = view.findViewById(R.id.song_five_star_1)
|
||||
// var fiveStar2: ImageView = view.findViewById(R.id.song_five_star_2)
|
||||
// var fiveStar3: ImageView = view.findViewById(R.id.song_five_star_3)
|
||||
// var fiveStar4: ImageView = view.findViewById(R.id.song_five_star_4)
|
||||
// var fiveStar5: ImageView = view.findViewById(R.id.song_five_star_5)
|
||||
// var star: ImageView = view.findViewById(R.id.song_star)
|
||||
// var drag: ImageView = view.findViewById(R.id.song_drag)
|
||||
// var track: TextView = view.findViewById(R.id.song_track)
|
||||
// var title: TextView = view.findViewById(R.id.song_title)
|
||||
// var artist: TextView = view.findViewById(R.id.song_artist)
|
||||
// var duration: TextView = view.findViewById(R.id.song_duration)
|
||||
// var status: TextView = view.findViewById(R.id.song_status)
|
||||
//
|
||||
// var entry: MusicDirectory.Entry? = null
|
||||
// private set
|
||||
// var downloadFile: DownloadFile? = null
|
||||
// private set
|
||||
//
|
||||
// private var isMaximized = false
|
||||
// private var leftImage: Drawable? = null
|
||||
// private var previousLeftImageType: ImageType? = null
|
||||
// private var previousRightImageType: ImageType? = null
|
||||
// private var leftImageType: ImageType? = null
|
||||
// private var playing = false
|
||||
//
|
||||
// private val features: FeatureStorage = get()
|
||||
// private val useFiveStarRating: Boolean = features.isFeatureEnabled(Feature.FIVE_STAR_RATING)
|
||||
// private val mediaPlayerController: MediaPlayerController by inject()
|
||||
//
|
||||
// fun setSong(file: DownloadFile, checkable: Boolean, draggable: Boolean) {
|
||||
// val song = file.song
|
||||
// downloadFile = file
|
||||
// entry = song
|
||||
//
|
||||
// val entryDescription = Util.readableEntryDescription(song)
|
||||
//
|
||||
// artist.text = entryDescription.artist
|
||||
// title.text = entryDescription.title
|
||||
// duration.text = entryDescription.duration
|
||||
//
|
||||
//
|
||||
// if (Settings.shouldShowTrackNumber && song.track != null && song.track!! > 0) {
|
||||
// track.text = entryDescription.trackNumber
|
||||
// } else {
|
||||
// track.isVisible = false
|
||||
// }
|
||||
//
|
||||
// // TODO: Migrate the image animation stuff from SongView into this class
|
||||
// check.isVisible = (checkable && !song.isVideo)
|
||||
// drag.isVisible = draggable
|
||||
//
|
||||
// if (image != null) {
|
||||
// status.setCompoundDrawablesWithIntrinsicBounds(
|
||||
// image, null, null, null
|
||||
// if (ActiveServerProvider.isOffline()) {
|
||||
// star.isVisible = false
|
||||
// rating.isVisible = false
|
||||
// } else {
|
||||
// setupStarButtons(song)
|
||||
// }
|
||||
// update()
|
||||
// }
|
||||
//
|
||||
// private fun setupStarButtons(song: MusicDirectory.Entry) {
|
||||
// if (useFiveStarRating) {
|
||||
// star.isVisible = false
|
||||
// val rating = if (song.userRating == null) 0 else song.userRating!!
|
||||
// fiveStar1.setImageDrawable(
|
||||
// if (rating > 0) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
// )
|
||||
// fiveStar2.setImageDrawable(
|
||||
// if (rating > 1) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
// )
|
||||
// fiveStar3.setImageDrawable(
|
||||
// if (rating > 2) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
// )
|
||||
// fiveStar4.setImageDrawable(
|
||||
// if (rating > 3) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
// )
|
||||
// fiveStar5.setImageDrawable(
|
||||
// if (rating > 4) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
// )
|
||||
// } else {
|
||||
// rating.isVisible = false
|
||||
// star.setImageDrawable(
|
||||
// if (song.starred) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// if (image === DownloadRowAdapter.downloadingImage) {
|
||||
// // FIXME
|
||||
//// val frameAnimation = image as AnimationDrawable
|
||||
////
|
||||
//// frameAnimation.setVisible(true, true)
|
||||
//// frameAnimation.start()
|
||||
// star.setOnClickListener {
|
||||
// val isStarred = song.starred
|
||||
// val id = song.id
|
||||
//
|
||||
// if (!isStarred) {
|
||||
// star.setImageDrawable(DownloadRowAdapter.starDrawable)
|
||||
// song.starred = true
|
||||
// } else {
|
||||
// star.setImageDrawable(DownloadRowAdapter.starHollowDrawable)
|
||||
// song.starred = false
|
||||
// }
|
||||
// Thread {
|
||||
// val musicService = MusicServiceFactory.getMusicService()
|
||||
// try {
|
||||
// if (!isStarred) {
|
||||
// musicService.star(id, null, null)
|
||||
// } else {
|
||||
// musicService.unstar(id, null, null)
|
||||
// }
|
||||
// } catch (all: Exception) {
|
||||
// Timber.e(all)
|
||||
// }
|
||||
// }.start()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
override fun setChecked(newStatus: Boolean) {
|
||||
check.isChecked = newStatus
|
||||
}
|
||||
|
||||
override fun isChecked(): Boolean {
|
||||
return check.isChecked
|
||||
}
|
||||
|
||||
override fun toggle() {
|
||||
check.toggle()
|
||||
}
|
||||
|
||||
fun maximizeOrMinimize() {
|
||||
isMaximized = !isMaximized
|
||||
|
||||
title.isSingleLine = !isMaximized
|
||||
artist.isSingleLine = !isMaximized
|
||||
}
|
||||
|
||||
enum class ImageType {
|
||||
None, Pin, Downloaded, Downloading
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//
|
||||
//
|
||||
// @Synchronized
|
||||
// // TDOD: Should be removed
|
||||
// fun update() {
|
||||
// val song = entry ?: return
|
||||
//
|
||||
// updateDownloadStatus(downloadFile!!)
|
||||
//
|
||||
// if (entry?.starred != true) {
|
||||
// if (star.drawable !== DownloadRowAdapter.starHollowDrawable) {
|
||||
// star.setImageDrawable(DownloadRowAdapter.starHollowDrawable)
|
||||
// }
|
||||
// } else {
|
||||
// if (star.drawable !== DownloadRowAdapter.starDrawable) {
|
||||
// star.setImageDrawable(DownloadRowAdapter.starDrawable)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// val rating = entry?.userRating ?: 0
|
||||
// fiveStar1.setImageDrawable(
|
||||
// if (rating > 0) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
// )
|
||||
// fiveStar2.setImageDrawable(
|
||||
// if (rating > 1) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
// )
|
||||
// fiveStar3.setImageDrawable(
|
||||
// if (rating > 2) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
// )
|
||||
// fiveStar4.setImageDrawable(
|
||||
// if (rating > 3) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
// )
|
||||
// fiveStar5.setImageDrawable(
|
||||
// if (rating > 4) DownloadRowAdapter.starDrawable else DownloadRowAdapter.starHollowDrawable
|
||||
// )
|
||||
//
|
||||
// val playing = mediaPlayerController.currentPlaying === downloadFile
|
||||
//
|
||||
// if (playing) {
|
||||
// if (!this.playing) {
|
||||
// this.playing = true
|
||||
// title.setCompoundDrawablesWithIntrinsicBounds(
|
||||
// DownloadRowAdapter.playingImage, null, null, null
|
||||
// )
|
||||
// }
|
||||
// } else {
|
||||
// if (this.playing) {
|
||||
// this.playing = false
|
||||
// title.setCompoundDrawablesWithIntrinsicBounds(
|
||||
// 0, 0, 0, 0
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fun updateDownloadStatus(downloadFile: DownloadFile) {
|
||||
//
|
||||
// if (downloadFile.isWorkDone) {
|
||||
// val newLeftImageType =
|
||||
// if (downloadFile.isSaved) ImageType.Pin else ImageType.Downloaded
|
||||
//
|
||||
// if (leftImageType != newLeftImageType) {
|
||||
// leftImage = if (downloadFile.isSaved) {
|
||||
// DownloadRowAdapter.pinImage
|
||||
// } else {
|
||||
// DownloadRowAdapter.downloadedImage
|
||||
// }
|
||||
// leftImageType = newLeftImageType
|
||||
// }
|
||||
// } else {
|
||||
// leftImageType = ImageType.None
|
||||
// leftImage = null
|
||||
// }
|
||||
//
|
||||
// val rightImageType: ImageType
|
||||
// val rightImage: Drawable?
|
||||
//
|
||||
// if (downloadFile.isDownloading && !downloadFile.isDownloadCancelled) {
|
||||
// status.text = Util.formatPercentage(downloadFile.progress.value!!)
|
||||
//
|
||||
// rightImageType = ImageType.Downloading
|
||||
// rightImage = DownloadRowAdapter.downloadingImage
|
||||
// } else {
|
||||
// rightImageType = ImageType.None
|
||||
// rightImage = null
|
||||
//
|
||||
// val statusText = status.text
|
||||
// if (!statusText.isNullOrEmpty()) status.text = null
|
||||
// }
|
||||
//
|
||||
// if (previousLeftImageType != leftImageType || previousRightImageType != rightImageType) {
|
||||
// previousLeftImageType = leftImageType
|
||||
// previousRightImageType = rightImageType
|
||||
//
|
||||
// status.setCompoundDrawablesWithIntrinsicBounds(
|
||||
// leftImage, null, rightImage, null
|
||||
// )
|
||||
//
|
||||
// if (rightImage === DownloadRowAdapter.downloadingImage) {
|
||||
// // FIXME
|
||||
// val frameAnimation = rightImage as AnimationDrawable?
|
||||
//
|
||||
// frameAnimation?.setVisible(true, true)
|
||||
// frameAnimation?.start()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//// fun updateDownloadStatus2(
|
||||
//// downloadFile: DownloadFile,
|
||||
//// ) {
|
||||
////
|
||||
//// var image: Drawable? = null
|
||||
////
|
||||
//// when (downloadFile.status.value) {
|
||||
//// DownloadStatus.DONE -> {
|
||||
//// image = if (downloadFile.isSaved) DownloadRowAdapter.pinImage else DownloadRowAdapter.downloadedImage
|
||||
//// status.text = null
|
||||
//// }
|
||||
//// DownloadStatus.DOWNLOADING -> {
|
||||
//// status.text = Util.formatPercentage(downloadFile.progress.value!!)
|
||||
//// image = DownloadRowAdapter.downloadingImage
|
||||
//// }
|
||||
//// else -> {
|
||||
//// status.text = null
|
||||
//// }
|
||||
//// }
|
||||
////
|
||||
//// // TODO: Migrate the image animation stuff from SongView into this class
|
||||
////
|
||||
//// if (image != null) {
|
||||
//// status.setCompoundDrawablesWithIntrinsicBounds(
|
||||
//// image, null, null, null
|
||||
//// )
|
||||
//// }
|
||||
////
|
||||
//// if (image === DownloadRowAdapter.downloadingImage) {
|
||||
//// // FIXME
|
||||
////// val frameAnimation = image as AnimationDrawable
|
||||
//////
|
||||
////// frameAnimation.setVisible(true, true)
|
||||
////// frameAnimation.start()
|
||||
//// }
|
||||
//// }
|
||||
//
|
||||
// override fun setChecked(newStatus: Boolean) {
|
||||
// check.isChecked = newStatus
|
||||
// }
|
||||
//
|
||||
// override fun isChecked(): Boolean {
|
||||
// return check.isChecked
|
||||
// }
|
||||
//
|
||||
// override fun toggle() {
|
||||
// check.toggle()
|
||||
// }
|
||||
//
|
||||
// fun maximizeOrMinimize() {
|
||||
// isMaximized = !isMaximized
|
||||
//
|
||||
// title.isSingleLine = !isMaximized
|
||||
// artist.isSingleLine = !isMaximized
|
||||
// }
|
||||
//
|
||||
// enum class ImageType {
|
||||
// None, Pin, Downloaded, Downloading
|
||||
// }
|
||||
//
|
||||
//
|
||||
//}
|
Loading…
Reference in New Issue