From d0e39efc50024469b3fc1ccfd69e9e9bcbf4bce9 Mon Sep 17 00:00:00 2001 From: tzugen Date: Sun, 14 Nov 2021 21:20:23 +0100 Subject: [PATCH] Migrate DownloadsFragment to new system --- .../fragment/BookmarksFragment.java | 4 +- .../org/moire/ultrasonic/util/AlbumHeader.kt | 2 +- .../adapters/MultiTypeDiffAdapter.kt | 61 ++++++-- .../ultrasonic/adapters/TrackViewBinder.kt | 44 +++--- .../ultrasonic/adapters/TrackViewHolder.kt | 15 +- .../ultrasonic/fragment/DownloadsFragment.kt | 35 ++--- .../ultrasonic/fragment/MultiListFragment.kt | 13 +- .../fragment/ServerSelectorFragment.kt | 1 - .../fragment/TrackCollectionFragment.kt | 147 +++++++----------- .../fragment/TrackCollectionModel.kt | 1 - .../moire/ultrasonic/service/DownloadFile.kt | 3 + ultrasonic/src/main/res/values-cs/strings.xml | 1 - ultrasonic/src/main/res/values-de/strings.xml | 3 +- ultrasonic/src/main/res/values-es/strings.xml | 1 - ultrasonic/src/main/res/values-fr/strings.xml | 1 - ultrasonic/src/main/res/values-hu/strings.xml | 1 - ultrasonic/src/main/res/values-it/strings.xml | 1 - ultrasonic/src/main/res/values-nl/strings.xml | 1 - ultrasonic/src/main/res/values-pl/strings.xml | 1 - .../src/main/res/values-pt-rBR/strings.xml | 1 - ultrasonic/src/main/res/values-pt/strings.xml | 1 - ultrasonic/src/main/res/values-ru/strings.xml | 1 - .../src/main/res/values-zh-rCN/strings.xml | 1 - ultrasonic/src/main/res/values/strings.xml | 23 ++- 24 files changed, 175 insertions(+), 188 deletions(-) diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/BookmarksFragment.java b/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/BookmarksFragment.java index 36897f5f..9375de80 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/BookmarksFragment.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/BookmarksFragment.java @@ -226,10 +226,10 @@ public class BookmarksFragment extends Fragment { } } - // Display toast: N tracks selected / N tracks unselected + // Display toast: N tracks selected if (toast) { - int toastResId = selected ? R.string.select_album_n_selected : R.string.select_album_n_unselected; + int toastResId = R.string.select_album_n_selected; Util.toast(getContext(), getString(toastResId, selectedCount)); } diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/util/AlbumHeader.kt b/ultrasonic/src/main/java/org/moire/ultrasonic/util/AlbumHeader.kt index 522e94ef..7b57bf29 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/util/AlbumHeader.kt +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/util/AlbumHeader.kt @@ -89,7 +89,7 @@ class AlbumHeader( get() = "HEADER" override val longId: Long - get() = id.hashCode().toLong() + get() = -1L override fun compareTo(other: Identifiable): Int { return this.longId.compareTo(other.longId) diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/MultiTypeDiffAdapter.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/MultiTypeDiffAdapter.kt index 7bb0e251..31de8366 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/MultiTypeDiffAdapter.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/MultiTypeDiffAdapter.kt @@ -1,24 +1,23 @@ package org.moire.ultrasonic.adapters import android.annotation.SuppressLint -import android.view.MotionEvent -import androidx.recyclerview.selection.ItemDetailsLookup -import androidx.recyclerview.selection.ItemKeyProvider -import androidx.recyclerview.selection.SelectionTracker +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import androidx.recyclerview.widget.AdapterListUpdateCallback import androidx.recyclerview.widget.AsyncDifferConfig import androidx.recyclerview.widget.AsyncListDiffer import androidx.recyclerview.widget.AsyncListDiffer.ListListener import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.RecyclerView import com.drakeet.multitype.MultiTypeAdapter import org.moire.ultrasonic.domain.Identifiable -import timber.log.Timber +import java.util.TreeSet class MultiTypeDiffAdapter : MultiTypeAdapter() { - val diffCallback = GenericDiffCallback() - var tracker: SelectionTracker? = null + internal var selectedSet: TreeSet = TreeSet() + internal var selectionRevision: MutableLiveData = MutableLiveData(0) + + private val diffCallback = GenericDiffCallback() init { setHasStableIds(true) @@ -28,10 +27,14 @@ class MultiTypeDiffAdapter : MultiTypeAdapter() { return getItem(position).longId } + private fun getItem(position: Int): T { + return mDiffer.currentList[position] + } + override var items: List get() = getCurrentList() set(value) { - throw Exception("You must use submitList() to add data to the MultiTypeDiffAdapter") + throw IllegalAccessException("You must use submitList() to add data to the MultiTypeDiffAdapter") } @@ -86,9 +89,7 @@ class MultiTypeDiffAdapter : MultiTypeAdapter() { mDiffer.submitList(list, commitCallback) } - protected fun getItem(position: Int): T { - return mDiffer.currentList[position] - } + override fun getItemCount(): Int { return mDiffer.currentList.size @@ -130,8 +131,42 @@ class MultiTypeDiffAdapter : MultiTypeAdapter() { // Void } + fun notifySelected(id: Long) { + selectedSet.add(id) + // Update revision counter + selectionRevision.postValue(selectionRevision.value!! + 1) + } + fun notifyUnselected(id: Long) { + selectedSet.remove(id) + + // Update revision counter + selectionRevision.postValue(selectionRevision.value!! + 1) + } + + fun setSelectionStatusOfAll(select: Boolean): Int { + // Clear current selection + selectedSet.clear() + + // Update revision counter + selectionRevision.postValue(selectionRevision.value!! + 1) + + // Nothing to reselect + if (!select) return 0 + + // Select them all + getCurrentList().mapNotNullTo(selectedSet, { entry -> + // Exclude any -1 ids, eg. headers and other UI elements + entry.longId.takeIf { it != -1L } + }) + + return selectedSet.count() + } + + fun isSelected(longId: Long): Boolean { + return selectedSet.contains(longId) + } companion object { @@ -150,8 +185,6 @@ class MultiTypeDiffAdapter : MultiTypeAdapter() { } - - } } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/TrackViewBinder.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/TrackViewBinder.kt index 1533f67c..d79fb10c 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/TrackViewBinder.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/TrackViewBinder.kt @@ -3,6 +3,7 @@ package org.moire.ultrasonic.adapters import android.content.Context import android.view.LayoutInflater import android.view.ViewGroup +import androidx.lifecycle.LifecycleOwner import com.drakeet.multitype.ItemViewBinder import org.koin.core.component.KoinComponent import org.koin.core.component.inject @@ -11,12 +12,13 @@ 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 timber.log.Timber class TrackViewBinder( - val selectedSet: MutableSet, val checkable: Boolean, val draggable: Boolean, - context: Context + context: Context, + val lifecycleOwner: LifecycleOwner ) : ItemViewBinder(), KoinComponent { @@ -35,12 +37,10 @@ class TrackViewBinder( val contextMenuLayout = R.menu.artist_context_menu private val downloader: Downloader by inject() - private val imageHelper: ImageHelper = ImageHelper(context) - override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): TrackViewHolder { - return TrackViewHolder(inflater.inflate(layout, parent, false), selectedSet) + return TrackViewHolder(inflater.inflate(layout, parent, false), adapter as MultiTypeDiffAdapter) } override fun onBindViewHolder(holder: TrackViewHolder, item: Identifiable) { @@ -64,23 +64,29 @@ class TrackViewBinder( holder.setSong( file = downloadFile, checkable = checkable, - draggable = draggable + draggable = draggable, + holder.adapter.isSelected(item.longId) ) + // Listen to changes in selection status and update ourselves + holder.adapter.selectionRevision.observe(lifecycleOwner, { + val newStatus = holder.adapter.isSelected(item.longId) + + if (newStatus != holder.check.isChecked) holder.check.isChecked = newStatus + }) + // Observe download status -// item.status.observe( -// lifecycleOwner, -// { -// holder.updateDownloadStatus(item) -// } -// ) -// -// item.progress.observe( -// lifecycleOwner, -// { -// holder.updateDownloadStatus(item) -// } -// ) + downloadFile.status.observe(lifecycleOwner, { + Timber.w("CAUGHT STATUS CHANGE") + holder.updateDownloadStatus(downloadFile) + } + ) + + downloadFile.progress.observe(lifecycleOwner, { + Timber.w("CAUGHT PROGRESS CHANGE") + holder.updateDownloadStatus(downloadFile) + } + ) } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/TrackViewHolder.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/TrackViewHolder.kt index 116a2852..7b8356ec 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/TrackViewHolder.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/TrackViewHolder.kt @@ -9,12 +9,14 @@ import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView import androidx.core.view.isVisible +import androidx.lifecycle.findViewTreeLifecycleOwner 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.Identifiable import org.moire.ultrasonic.domain.MusicDirectory import org.moire.ultrasonic.featureflags.Feature import org.moire.ultrasonic.featureflags.FeatureStorage @@ -29,8 +31,9 @@ import timber.log.Timber * Used to display songs and videos in a `ListView`. * TODO: Video List item */ -class TrackViewHolder(val view: View, val selectedSet: MutableSet) : +class TrackViewHolder(val view: View, var adapter: MultiTypeDiffAdapter) : RecyclerView.ViewHolder(view), Checkable, KoinComponent { + var check: CheckedTextView = view.findViewById(R.id.song_check) var rating: LinearLayout = view.findViewById(R.id.song_rating) private var fiveStar1: ImageView = view.findViewById(R.id.song_five_star_1) @@ -99,6 +102,7 @@ class TrackViewHolder(val view: View, val selectedSet: MutableSet) : } check.isVisible = (checkable && !song.isVideo) + check.isChecked = isSelected drag.isVisible = draggable if (ActiveServerProvider.isOffline()) { @@ -109,9 +113,6 @@ class TrackViewHolder(val view: View, val selectedSet: MutableSet) : } update() - - isChecked = isSelected - } private fun setupStarButtons(song: MusicDirectory.Entry) { @@ -219,7 +220,6 @@ class TrackViewHolder(val view: View, val selectedSet: MutableSet) : } fun updateDownloadStatus(downloadFile: DownloadFile) { - if (downloadFile.isWorkDone) { val newLeftImageType = if (downloadFile.isSaved) ImageType.Pin else ImageType.Downloaded @@ -274,10 +274,9 @@ class TrackViewHolder(val view: View, val selectedSet: MutableSet) : override fun setChecked(newStatus: Boolean) { if (newStatus) { - selectedSet.add(downloadFile!!.longId) - Timber.d("Selectedset %s", selectedSet.toString()) + adapter.notifySelected(downloadFile!!.longId) } else { - selectedSet.remove(downloadFile!!.longId) + adapter.notifyUnselected(downloadFile!!.longId) } check.isChecked = newStatus } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/DownloadsFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/DownloadsFragment.kt index 0af78788..209c268b 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/DownloadsFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/DownloadsFragment.kt @@ -3,6 +3,7 @@ package org.moire.ultrasonic.fragment import android.app.Application import android.os.Bundle import android.view.MenuItem +import android.view.View import androidx.fragment.app.viewModels import androidx.lifecycle.LiveData import org.koin.core.component.inject @@ -13,9 +14,8 @@ 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 java.util.TreeSet -class DownloadsFragment : MultiListFragment>() { +class DownloadsFragment : MultiListFragment() { /** * The ViewModel to use to get the data @@ -36,22 +36,6 @@ class DownloadsFragment : MultiListFragment by lazy { - val adapter = MultiTypeDiffAdapter() - adapter.register( - TrackViewBinder( - selectedSet = TreeSet(), - checkable = false, - draggable = false, - context = requireContext() - ) - ) - adapter - } - override fun onContextMenuItemSelected(menuItem: MenuItem, item: DownloadFile): Boolean { // Do nothing return true @@ -64,6 +48,21 @@ class DownloadsFragment : MultiListFragment : Fragment() { +abstract class MultiListFragment : Fragment() { internal val activeServerProvider: ActiveServerProvider by inject() internal val serverSettingsModel: ServerSettingsModel by viewModel() internal val imageLoaderProvider: ImageLoaderProvider by inject() @@ -47,7 +48,9 @@ abstract class MultiListFragment : Frag * The Adapter for the RecyclerView * Recommendation: Implement this as a lazy delegate */ - internal abstract val viewAdapter: TA + internal val viewAdapter: MultiTypeDiffAdapter by lazy { + MultiTypeDiffAdapter() + } /** * The ViewModel to use to get the data @@ -144,9 +147,9 @@ abstract class MultiListFragment : Frag liveDataItems = getLiveData(arguments) // Register an observer to update our UI when the data changes -// liveDataItems.observe(viewLifecycleOwner, { -// newItems -> viewAdapter.submitList(newItems) -// }) + liveDataItems.observe(viewLifecycleOwner, { + newItems -> viewAdapter.submitList(newItems) + }) // Setup the Music folder handling listModel.getMusicFolders().observe(viewLifecycleOwner, musicFolderObserver) diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ServerSelectorFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ServerSelectorFragment.kt index f06ed156..05d7b568 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ServerSelectorFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/ServerSelectorFragment.kt @@ -16,7 +16,6 @@ import kotlinx.coroutines.withContext import org.koin.android.ext.android.inject import org.koin.androidx.viewmodel.ext.android.viewModel import org.moire.ultrasonic.R -import org.moire.ultrasonic.adapters.ServerRowAdapter import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.fragment.EditServerFragment.Companion.EDIT_SERVER_INTENT_INDEX import org.moire.ultrasonic.service.MediaPlayerController diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionFragment.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionFragment.kt index 1cf42767..767b4299 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionFragment.kt @@ -34,7 +34,6 @@ 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 @@ -51,7 +50,6 @@ import org.moire.ultrasonic.util.Settings import org.moire.ultrasonic.util.Util import timber.log.Timber import java.util.Collections -import java.util.TreeSet /** * Displays a group of tracks, eg. the songs of an album, of a playlist etc. @@ -61,7 +59,7 @@ import java.util.TreeSet * TODO: Handle updates (playstatus, download status) */ class TrackCollectionFragment : - MultiListFragment>() { + MultiListFragment() { private var albumButtons: View? = null private var emptyView: TextView? = null @@ -86,8 +84,6 @@ class TrackCollectionFragment : override val listModel: TrackCollectionModel by viewModels() - private var selectedSet: TreeSet = TreeSet() - /** * The id of the main layout */ @@ -111,19 +107,6 @@ class TrackCollectionFragment : override val itemClickTarget: Int = R.id.trackCollectionFragment - override fun onCreate(savedInstanceState: Bundle?) { - Util.applyTheme(this.context) - super.onCreate(savedInstanceState) - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - return inflater.inflate(R.layout.track_list, container, false) - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) cancellationToken = CancellationToken() @@ -136,7 +119,7 @@ class TrackCollectionFragment : updateDisplay(true) } - listModel.currentList.observe(viewLifecycleOwner, defaultObserver) + listModel.currentList.observe(viewLifecycleOwner, updateInterfaceWithEntries) listModel.songsForGenre.observe(viewLifecycleOwner, songsForGenreObserver) // listView!!.setOnItemClickListener { parent, theView, position, _ -> @@ -185,9 +168,11 @@ class TrackCollectionFragment : selectButton!!.setOnClickListener { selectAllOrNone() } + playNowButton!!.setOnClickListener { playNow(false) } + playNextButton!!.setOnClickListener { downloadHandler.download( this@TrackCollectionFragment, append = true, @@ -195,18 +180,23 @@ class TrackCollectionFragment : songs = getSelectedSongs() ) } + playLastButton!!.setOnClickListener { playNow(true) } + pinButton!!.setOnClickListener { downloadBackground(true) } + unpinButton!!.setOnClickListener { unpin() } + downloadButton!!.setOnClickListener { downloadBackground(false) } + deleteButton!!.setOnClickListener { delete() } @@ -214,7 +204,6 @@ class TrackCollectionFragment : registerForContextMenu(listView!!) setHasOptionsMenu(true) - // Create a View Manager viewManager = LinearLayoutManager(this.context) @@ -225,7 +214,6 @@ class TrackCollectionFragment : adapter = viewAdapter } - viewAdapter.register( HeaderViewBinder( context = requireContext() @@ -234,16 +222,20 @@ class TrackCollectionFragment : viewAdapter.register( TrackViewBinder( - selectedSet = selectedSet, checkable = true, draggable = false, - context = requireContext() + context = requireContext(), + lifecycleOwner = viewLifecycleOwner ) ) - enableButtons() + // Update the buttons when the selection has changed + viewAdapter.selectionRevision.observe(viewLifecycleOwner, { + enableButtons() + }) + // Loads the data updateDisplay(false) } @@ -387,33 +379,24 @@ class TrackCollectionFragment : } } - private val viewHolders: List - get() { - val list: MutableList = mutableListOf() - for (i in 0 until listView!!.childCount) { - val vh = listView!!.findViewHolderForAdapterPosition(i) - if (vh is TrackViewHolder) { - list.add(vh) - } - } - return list - } - + /** + * Get the size of the underlying list + */ private val childCount: Int get() { + val count = viewAdapter.getCurrentList().count() if (listModel.showHeader) { - return listView!!.childCount - 1 + return count - 1 } else { - return listView!!.childCount + return count } } private fun playAll(shuffle: Boolean = false, append: Boolean = false) { var hasSubFolders = false - for (vh in viewHolders) { - val entry = vh.entry - if (entry != null && entry.isDirectory) { + for (item in viewAdapter.getCurrentList()) { + if (item is MusicDirectory.Entry && item.isDirectory) { hasSubFolders = true break } @@ -436,7 +419,6 @@ class TrackCollectionFragment : isArtist = isArtist ) } else { - selectAll(selected = true, toast = false) downloadHandler.download( fragment = this, append = append, @@ -444,49 +426,38 @@ class TrackCollectionFragment : autoPlay = !append, playNext = false, shuffle = shuffle, - songs = getSelectedSongs() + songs = getAllSongs() ) - selectAll(selected = false, toast = false) } } + @Suppress("UNCHECKED_CAST") + private fun getAllSongs(): List { + return viewAdapter.getCurrentList().filter { + it is MusicDirectory.Entry && !it.isDirectory + } as List + } + private fun selectAllOrNone() { - val someUnselected = selectedSet.size < childCount + val someUnselected = viewAdapter.selectedSet.size < childCount selectAll(someUnselected, true) - } private fun selectAll(selected: Boolean, toast: Boolean) { + var selectedCount = viewAdapter.selectedSet.size * -1 - var selectedCount = 0 + selectedCount += viewAdapter.setSelectionStatusOfAll(selected) - listView!! - - for (vh in viewHolders) { - val entry = vh.entry - - if (entry != null && !entry.isDirectory && !entry.isVideo) { - vh.isChecked = selected - selectedCount++ - } - } - - - // Display toast: N tracks selected / N tracks unselected + // Display toast: N tracks selected if (toast) { - val toastResId = if (selected) - R.string.select_album_n_selected - else - R.string.select_album_n_unselected - Util.toast(activity, getString(toastResId, selectedCount)) + val toastResId = R.string.select_album_n_selected + Util.toast(activity, getString(toastResId, selectedCount.coerceAtLeast(0))) } - enableButtons() } - private fun enableButtons() { - val selection = getSelectedSongs() + private fun enableButtons(selection: List = getSelectedSongs()) { val enabled = selection.isNotEmpty() var unpinEnabled = false var deleteEnabled = false @@ -517,8 +488,7 @@ class TrackCollectionFragment : var songs = getSelectedSongs() if (songs.isEmpty()) { - selectAll(selected = true, toast = false) - songs = getSelectedSongs() + songs = getAllSongs() } downloadBackground(save, songs) @@ -596,15 +566,12 @@ class TrackCollectionFragment : Navigation.findNavController(requireView()) .navigate(R.id.trackCollectionFragment, bundle) } - - //updateInterfaceWithEntries(musicDirectory) } - private val defaultObserver = Observer(this::updateInterfaceWithEntries) - private fun updateInterfaceWithEntries(newList: List) { + private val updateInterfaceWithEntries = Observer> { - val entryList: MutableList = newList.toMutableList() + val entryList: MutableList = it.toMutableList() if (listModel.currentListIsSortable && Settings.shouldSortByDisc) { Collections.sort(entryList, EntryByDiscAndTrackComparator()) @@ -683,6 +650,7 @@ class TrackCollectionFragment : playAllButtonVisible = !(isAlbumList || entryList.isEmpty()) && !allVideos shareButtonVisible = !isOffline() && songCount > 0 + // TODO!! // listView!!.removeHeaderView(emptyView!!) // if (entries.isEmpty()) { // emptyView!!.text = getString(R.string.select_album_empty) @@ -700,9 +668,9 @@ class TrackCollectionFragment : if (songCount > 0 && listModel.showHeader) { - var name = listModel.currentDirectory.value?.name + val name = listModel.currentDirectory.value?.name val intentAlbumName = requireArguments().getString(Constants.INTENT_EXTRA_NAME_NAME, "Name")!! - val albumHeader = AlbumHeader(newList, name?: intentAlbumName, songCount) + val albumHeader = AlbumHeader(it, name?: intentAlbumName, songCount) val mixedList: MutableList = mutableListOf(albumHeader) mixedList.addAll(entryList) viewAdapter.submitList(mixedList) @@ -724,26 +692,17 @@ class TrackCollectionFragment : } - private fun getSelectedSongs(): MutableList { - val songs: MutableList = mutableListOf() - - for (vh in viewHolders) { - if (vh.isChecked) { - songs.add(vh.entry!!) - } + private fun getSelectedSongs(): List { + // Walk through selected set and get the Entries based on the saved ids. + return viewAdapter.getCurrentList().mapNotNull { + if (it is MusicDirectory.Entry && viewAdapter.isSelected(it.longId)) + it + else + null } - - for (key in selectedSet) { - songs.add(viewAdapter.getCurrentList().findLast { - it.longId == key - } as MusicDirectory.Entry) - } - return songs } - override val viewAdapter: MultiTypeDiffAdapter by lazy { - MultiTypeDiffAdapter() - } + override fun setTitle(title: String?) { setTitle(this@TrackCollectionFragment, title) diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionModel.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionModel.kt index 0c547c20..bdee4fe7 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionModel.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionModel.kt @@ -34,7 +34,6 @@ class TrackCollectionModel(application: Application) : GenericListModel(applicat val currentDirectory: MutableLiveData = MutableLiveData() val currentList: MutableLiveData> = MutableLiveData() val songsForGenre: MutableLiveData = MutableLiveData() - private val downloader: Downloader by inject() suspend fun getMusicFolders(refresh: Boolean) { withContext(Dispatchers.IO) { diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/DownloadFile.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/DownloadFile.kt index 4f0260eb..3a1833f2 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/DownloadFile.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/DownloadFile.kt @@ -139,6 +139,8 @@ class DownloadFile( Util.delete(completeFile) Util.delete(saveFile) + status.postValue(DownloadStatus.IDLE) + Util.scanMedia(saveFile) } @@ -150,6 +152,7 @@ class DownloadFile( saveFile.name, completeFile.name ) } + status.postValue(DownloadStatus.DONE) } } diff --git a/ultrasonic/src/main/res/values-cs/strings.xml b/ultrasonic/src/main/res/values-cs/strings.xml index 071e0266..9a2f3de2 100644 --- a/ultrasonic/src/main/res/values-cs/strings.xml +++ b/ultrasonic/src/main/res/values-cs/strings.xml @@ -130,7 +130,6 @@ Hledat Média nenalezena %d skladeb označeno. - %d skladeb odznačeno. Varování: Připojení nedostupné. Chyba: SD karta nedostupná. Přehrát vše diff --git a/ultrasonic/src/main/res/values-de/strings.xml b/ultrasonic/src/main/res/values-de/strings.xml index 0182cf3e..a07f2a8c 100644 --- a/ultrasonic/src/main/res/values-de/strings.xml +++ b/ultrasonic/src/main/res/values-de/strings.xml @@ -128,8 +128,7 @@ Titel Suche Keine Medien gefunden - %d Titel ausgewählt. - %d Titel abgewählt. + %d Titel ausgewählt Warnung: kein Netz. Fehler: Keine SD Karte verfügbar. Alles wiedergeben diff --git a/ultrasonic/src/main/res/values-es/strings.xml b/ultrasonic/src/main/res/values-es/strings.xml index c176ee3f..275d4f08 100644 --- a/ultrasonic/src/main/res/values-es/strings.xml +++ b/ultrasonic/src/main/res/values-es/strings.xml @@ -145,7 +145,6 @@ Buscar No se han encontrado medios %d pista(s) seleccionada(s). - %d pista(s) deseleccionada(s). Atención: No hay red disponible. Error: No hay tarjeta SD disponible. Reproducir todo diff --git a/ultrasonic/src/main/res/values-fr/strings.xml b/ultrasonic/src/main/res/values-fr/strings.xml index 9b75c926..a05419da 100644 --- a/ultrasonic/src/main/res/values-fr/strings.xml +++ b/ultrasonic/src/main/res/values-fr/strings.xml @@ -142,7 +142,6 @@ Recherche Aucun titre trouvé %d pistes sélectionnées. - %d pistes non sélectionnés. Avertissement : Aucun réseau disponible. Erreur : Aucune carte SD disponible. Tout jouer diff --git a/ultrasonic/src/main/res/values-hu/strings.xml b/ultrasonic/src/main/res/values-hu/strings.xml index f1aa2a85..b2e6f44c 100644 --- a/ultrasonic/src/main/res/values-hu/strings.xml +++ b/ultrasonic/src/main/res/values-hu/strings.xml @@ -140,7 +140,6 @@ Keresés Nem található média! %d dal kijelölve. - %d dal visszavonva. Figyelem: Hálózat nem áll rendelkezésre! Hiba: SD kártya nem áll rendelkezésre! Összes lejátszása diff --git a/ultrasonic/src/main/res/values-it/strings.xml b/ultrasonic/src/main/res/values-it/strings.xml index a37ab73c..7a8f4486 100644 --- a/ultrasonic/src/main/res/values-it/strings.xml +++ b/ultrasonic/src/main/res/values-it/strings.xml @@ -126,7 +126,6 @@ Cerca Nessun media trovato %dtracce selezionate. - %d tracce non selezionate. Attenzione: nessuna rete disponibile. Errore: Nessuna memoria SD disponibile. Riproduci tutto diff --git a/ultrasonic/src/main/res/values-nl/strings.xml b/ultrasonic/src/main/res/values-nl/strings.xml index 0876e987..43a01e14 100644 --- a/ultrasonic/src/main/res/values-nl/strings.xml +++ b/ultrasonic/src/main/res/values-nl/strings.xml @@ -145,7 +145,6 @@ Zoeken Geen media gevonden %d nummers geselecteerd. - %d nummers gedeselecteerd. Waarschuwing: geen internetverbinding. Fout: geen SD-kaart beschikbaar. Alles afspelen diff --git a/ultrasonic/src/main/res/values-pl/strings.xml b/ultrasonic/src/main/res/values-pl/strings.xml index e794e991..3a2f4554 100644 --- a/ultrasonic/src/main/res/values-pl/strings.xml +++ b/ultrasonic/src/main/res/values-pl/strings.xml @@ -128,7 +128,6 @@ Wyszukiwanie Brak mediów Zaznaczono %d utworów. - Odznaczono %d utworów. Uwaga: sieć niedostępna. Błąd: Niedostępna karta SD. Odtwórz wszystkie diff --git a/ultrasonic/src/main/res/values-pt-rBR/strings.xml b/ultrasonic/src/main/res/values-pt-rBR/strings.xml index 41dd11fa..e35c4c44 100644 --- a/ultrasonic/src/main/res/values-pt-rBR/strings.xml +++ b/ultrasonic/src/main/res/values-pt-rBR/strings.xml @@ -142,7 +142,6 @@ Pesquisar Nenhuma mídia encontrada %d faixas selecionadas. - %d faixas desselecionadas. Aviso: Nenhuma rede disponível. Erro: Nenhum cartão SD disponível. Tocar Tudo diff --git a/ultrasonic/src/main/res/values-pt/strings.xml b/ultrasonic/src/main/res/values-pt/strings.xml index 3706c9ee..f883e96c 100644 --- a/ultrasonic/src/main/res/values-pt/strings.xml +++ b/ultrasonic/src/main/res/values-pt/strings.xml @@ -128,7 +128,6 @@ Pesquisar Nenhuma mídia encontrada %d faixas selecionadas. - %d faixas desselecionadas. Aviso: Nenhuma rede disponível. Erro: Nenhum cartão SD disponível. Tocar Tudo diff --git a/ultrasonic/src/main/res/values-ru/strings.xml b/ultrasonic/src/main/res/values-ru/strings.xml index 2c4091ea..2e9e7368 100644 --- a/ultrasonic/src/main/res/values-ru/strings.xml +++ b/ultrasonic/src/main/res/values-ru/strings.xml @@ -142,7 +142,6 @@ Поиск Медиа не найдена %d треки выбраны. - %d треки не выбраны. Предупреждение: сеть недоступна. Ошибка: нет SD-карты Воспроизвести все diff --git a/ultrasonic/src/main/res/values-zh-rCN/strings.xml b/ultrasonic/src/main/res/values-zh-rCN/strings.xml index 00860b89..ecdb7d9c 100644 --- a/ultrasonic/src/main/res/values-zh-rCN/strings.xml +++ b/ultrasonic/src/main/res/values-zh-rCN/strings.xml @@ -141,7 +141,6 @@ 搜索 找不到歌曲 已选择 %d 首曲目。 - 未选择 %d 首曲目。 警告:网络不可用 错误:没有SD卡 播放所有 diff --git a/ultrasonic/src/main/res/values/strings.xml b/ultrasonic/src/main/res/values/strings.xml index bbf382a2..5b7746e8 100644 --- a/ultrasonic/src/main/res/values/strings.xml +++ b/ultrasonic/src/main/res/values/strings.xml @@ -146,8 +146,7 @@ Songs Search No media found - %d tracks selected. - %d tracks unselected. + %d tracks selected Warning: No network available. Error: No SD card available. Play All @@ -454,24 +453,24 @@ %d songs - %d song selected to be pinned. - %d songs selected to be pinned. + %d song selected to be pinned + %d songs selected to be pinned - %d song selected to be downloaded. - %d songs selected to be downloaded. + %d song selected to be downloaded + %d songs selected to be downloaded - %d song selected to be unpinned. - %d songs selected to be unpinned. + %d song unpinned + %d songs unpinned - %d song added to the end of play queue. - %d songs added to the end of play queue. + %d song added to the end of play queue + %d songs added to the end of play queue - %d song inserted after current song. - %d songs inserted after current song. + %d song inserted after current song + %d songs inserted after current song %d day left of trial period