From f6f524f5a98b793ba7ad2afc23be0b9a23a681d8 Mon Sep 17 00:00:00 2001 From: Nite Date: Mon, 8 Aug 2022 14:01:43 +0000 Subject: [PATCH] Fixed updating button states in TrackCollectionFragment according to track states --- .../ultrasonic/adapters/TrackViewHolder.kt | 80 +++++++++---------- .../org/moire/ultrasonic/adapters/Utils.kt | 12 ++- .../fragment/TrackCollectionFragment.kt | 20 ++++- .../moire/ultrasonic/service/Downloader.kt | 28 ++++--- .../org/moire/ultrasonic/service/RxBus.kt | 2 +- .../main/res/drawable/stat_sys_download.xml | 32 -------- .../res/drawable/stat_sys_download_anim_1.xml | 3 +- .../res/drawable/stat_sys_download_anim_2.xml | 3 +- .../res/drawable/stat_sys_download_anim_3.xml | 3 +- .../res/drawable/stat_sys_download_anim_4.xml | 3 +- .../res/drawable/stat_sys_download_anim_5.xml | 3 +- .../res/drawable/stat_sys_download_anim_6.xml | 3 +- .../res/drawable/stat_sys_download_anim_7.xml | 3 +- 13 files changed, 96 insertions(+), 99 deletions(-) delete mode 100644 ultrasonic/src/main/res/drawable/stat_sys_download.xml 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 8a388701..4e4293f7 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/TrackViewHolder.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/TrackViewHolder.kt @@ -1,6 +1,5 @@ package org.moire.ultrasonic.adapters -import android.graphics.drawable.AnimationDrawable import android.graphics.drawable.Drawable import android.view.View import android.widget.Checkable @@ -94,8 +93,7 @@ class TrackViewHolder(val view: View) : RecyclerView.ViewHolder(view), Checkable setupStarButtons(song, useFiveStarRating) } - updateStatus(downloader.getDownloadState(song)) - updateProgress(0) + updateStatus(downloader.getDownloadState(song), null) if (useFiveStarRating) { setFiveStars(entry?.userRating ?: 0) @@ -116,8 +114,7 @@ class TrackViewHolder(val view: View) : RecyclerView.ViewHolder(view), Checkable rxBusSubscription!! += RxBus.trackDownloadStateObservable.subscribe { if (it.id != song.id) return@subscribe - updateStatus(it.state) - updateProgress(it.progress) + updateStatus(it.state, it.progress) } } @@ -207,52 +204,49 @@ class TrackViewHolder(val view: View) : RecyclerView.ViewHolder(view), Checkable } } - private fun updateStatus(status: DownloadStatus) { - if (status == cachedStatus) return - cachedStatus = status + private fun updateStatus(status: DownloadStatus, p: Int?) { + if (status != cachedStatus) { + cachedStatus = status - when (status) { - DownloadStatus.DONE -> { - statusImage = imageHelper.downloadedImage - progress.text = null - } - DownloadStatus.PINNED -> { - statusImage = imageHelper.pinImage - progress.text = null - } - DownloadStatus.FAILED, - DownloadStatus.CANCELLED -> { - statusImage = imageHelper.errorImage - progress.text = null - } - DownloadStatus.DOWNLOADING -> { - statusImage = imageHelper.downloadingImage - } - else -> { - statusImage = null + when (status) { + DownloadStatus.DONE -> { + statusImage = imageHelper.downloadedImage + progress.text = null + } + DownloadStatus.PINNED -> { + statusImage = imageHelper.pinImage + progress.text = null + } + DownloadStatus.FAILED, + DownloadStatus.CANCELLED -> { + statusImage = imageHelper.errorImage + progress.text = null + } + DownloadStatus.DOWNLOADING -> { + statusImage = imageHelper.downloadingImage[0] + } + else -> { + statusImage = null + } } } + if (cachedStatus == DownloadStatus.DOWNLOADING && p != null) { + progress.text = Util.formatPercentage(p) + statusImage = + imageHelper.downloadingImage[(imageHelper.downloadingImage.size / 100F * p).toInt()] + } else { + progress.text = null + } + updateImages() } - private fun updateProgress(p: Int) { - if (cachedStatus == DownloadStatus.DOWNLOADING) { - progress.text = Util.formatPercentage(p) - } else { - progress.text = null - } - } - private fun updateImages() { - progress.setCompoundDrawablesWithIntrinsicBounds( - null, null, statusImage, null - ) - - if (statusImage === imageHelper.downloadingImage) { - val frameAnimation = statusImage as AnimationDrawable? - frameAnimation?.setVisible(true, true) - frameAnimation?.start() + progress.post { + progress.setCompoundDrawablesWithIntrinsicBounds( + null, null, statusImage, null + ) } } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/Utils.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/Utils.kt index 97ce98a0..ce05cd34 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/Utils.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/adapters/Utils.kt @@ -39,7 +39,7 @@ object Utils { lateinit var errorImage: Drawable lateinit var pinImage: Drawable lateinit var downloadedImage: Drawable - lateinit var downloadingImage: Drawable + lateinit var downloadingImage: List lateinit var playingImage: Drawable var theme: String @@ -63,7 +63,15 @@ object Utils { downloadedImage = ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_0)!! errorImage = ContextCompat.getDrawable(context, R.drawable.ic_baseline_error)!! - downloadingImage = ContextCompat.getDrawable(context, R.drawable.stat_sys_download)!! + downloadingImage = listOf( + ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_1)!!, + ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_2)!!, + ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_3)!!, + ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_4)!!, + ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_5)!!, + ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_6)!!, + ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_7)!!, + ) playingImage = ContextCompat.getDrawable(context, R.drawable.ic_stat_play)!! } } 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 b4d9c021..332270f7 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionFragment.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/TrackCollectionFragment.kt @@ -21,6 +21,7 @@ import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import io.reactivex.rxjava3.disposables.CompositeDisposable import java.util.Collections import kotlinx.coroutines.launch import org.koin.android.ext.android.inject @@ -39,6 +40,8 @@ import org.moire.ultrasonic.model.TrackCollectionModel import org.moire.ultrasonic.service.DownloadStatus import org.moire.ultrasonic.service.Downloader import org.moire.ultrasonic.service.MediaPlayerController +import org.moire.ultrasonic.service.RxBus +import org.moire.ultrasonic.service.plusAssign import org.moire.ultrasonic.subsonic.NetworkAndStorageChecker import org.moire.ultrasonic.subsonic.ShareHandler import org.moire.ultrasonic.subsonic.VideoPlayer @@ -83,6 +86,7 @@ open class TrackCollectionFragment : MultiListFragment() { internal var cancellationToken: CancellationToken? = null override val listModel: TrackCollectionModel by viewModels() + private val rxBusSubscription: CompositeDisposable = CompositeDisposable() /** * The id of the main layout @@ -143,6 +147,14 @@ open class TrackCollectionFragment : MultiListFragment() { ) ) + // Change the buttons if the status of any selected track changes + rxBusSubscription += RxBus.trackDownloadStateObservable.subscribe { + if (it.progress != null) return@subscribe + val selectedSongs = getSelectedSongs() + if (!selectedSongs.any { song -> song.id == it.id }) return@subscribe + enableButtons(selectedSongs) + } + enableButtons() // Update the buttons when the selection has changed @@ -261,6 +273,7 @@ open class TrackCollectionFragment : MultiListFragment() { override fun onDestroyView() { cancellationToken!!.cancel() + rxBusSubscription.dispose() super.onDestroyView() } @@ -356,10 +369,12 @@ open class TrackCollectionFragment : MultiListFragment() { } } + @Suppress("ComplexMethod") internal open fun enableButtons(selection: List = getSelectedSongs()) { val enabled = selection.isNotEmpty() var unpinEnabled = false var deleteEnabled = false + var downloadEnabled = false val multipleSelection = viewAdapter.hasMultipleSelection() var pinnedCount = 0 @@ -373,6 +388,9 @@ open class TrackCollectionFragment : MultiListFragment() { pinnedCount++ unpinEnabled = true } + if (state == DownloadStatus.IDLE || state == DownloadStatus.FAILED) { + downloadEnabled = true + } } playNowButton?.isVisible = enabled @@ -380,7 +398,7 @@ open class TrackCollectionFragment : MultiListFragment() { playLastButton?.isVisible = enabled && multipleSelection pinButton?.isVisible = (enabled && !isOffline() && selection.size > pinnedCount) unpinButton?.isVisible = (enabled && unpinEnabled) - downloadButton?.isVisible = (enabled && !deleteEnabled && !isOffline()) + downloadButton?.isVisible = (enabled && downloadEnabled && !isOffline()) deleteButton?.isVisible = (enabled && deleteEnabled) } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/Downloader.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/Downloader.kt index 1a0454de..9bc39778 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/Downloader.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/Downloader.kt @@ -185,7 +185,7 @@ class Downloader( val existingItem = downloadQueue.firstOrNull { it.track.id == track.id } if (existingItem != null) { existingItem.priority = priority + 1 - return + continue } // Set correct priority (the lower the number, the higher the priority) @@ -267,7 +267,9 @@ class Downloader( fun downloadBackground(tracks: List, save: Boolean) { // By using the counter we ensure that the songs are added in the correct order for (track in tracks) { - if (downloadQueue.any { t -> t.track.id == track.id }) continue + if (downloadQueue.any { t -> t.track.id == track.id } || + activelyDownloading.any { t -> t.key.track.id == track.id } + ) continue val file = DownloadableTrack(track, save, 0, backgroundPriorityCounter++) downloadQueue.add(file) } @@ -281,7 +283,7 @@ class Downloader( Storage.delete(track.getPartialFile()) Storage.delete(track.getCompleteFile()) Storage.delete(track.getPinnedFile()) - postState(track, DownloadStatus.IDLE, 0) + postState(track, DownloadStatus.IDLE) Util.scanMedia(track.getPinnedFile()) } @@ -295,7 +297,7 @@ class Downloader( if (!Storage.isPathExists(pinnedFile)) return val file = Storage.getFromPath(track.getPinnedFile()) ?: return Storage.rename(file, track.getCompleteFile()) - postState(track, DownloadStatus.DONE, 100) + postState(track, DownloadStatus.DONE) } @Suppress("ReturnCount") @@ -318,7 +320,7 @@ class Downloader( const val REFRESH_INTERVAL = 100 } - private fun postState(track: Track, state: DownloadStatus, progress: Int) { + private fun postState(track: Track, state: DownloadStatus, progress: Int? = null) { RxBus.trackDownloadStatePublisher.onNext( RxBus.TrackDownloadState( track.id, @@ -340,7 +342,7 @@ class Downloader( try { if (Storage.isPathExists(item.pinnedFile)) { Timber.i("%s already exists. Skipping.", item.pinnedFile) - postState(item.track, DownloadStatus.PINNED, 100) + postState(item.track, DownloadStatus.PINNED) return } @@ -365,11 +367,11 @@ class Downloader( } catch (ignore: Exception) { Timber.w(ignore) } - postState(item.track, newStatus, 100) + postState(item.track, newStatus) return } - postState(item.track, DownloadStatus.DOWNLOADING, 0) + postState(item.track, DownloadStatus.DOWNLOADING) // Some devices seem to throw error on partial file which doesn't exist val needsDownloading: Boolean @@ -415,7 +417,7 @@ class Downloader( outputStream.close() if (isCancelled) { - postState(item.track, DownloadStatus.CANCELLED, 0) + postState(item.track, DownloadStatus.CANCELLED) throw RuntimeException( String.format( Locale.ROOT, "Download of '%s' was cancelled", @@ -436,14 +438,14 @@ class Downloader( item.partialFile, item.pinnedFile ) - postState(item.track, DownloadStatus.PINNED, 100) + postState(item.track, DownloadStatus.PINNED) Util.scanMedia(item.pinnedFile) } else { Storage.rename( item.partialFile, item.completeFile ) - postState(item.track, DownloadStatus.DONE, 100) + postState(item.track, DownloadStatus.DONE) } } catch (all: Exception) { outputStream.safeClose() @@ -451,12 +453,12 @@ class Downloader( Storage.delete(item.pinnedFile) if (!isCancelled) { if (item.tryCount < MAX_RETRIES) { - postState(item.track, DownloadStatus.RETRYING, 0) + postState(item.track, DownloadStatus.RETRYING) item.tryCount++ activelyDownloading.remove(item) downloadQueue.add(item) } else { - postState(item.track, DownloadStatus.FAILED, 0) + postState(item.track, DownloadStatus.FAILED) activelyDownloading.remove(item) downloadQueue.remove(item) failedList.add(item) diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/RxBus.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/RxBus.kt index 64334103..dd8e19f0 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/RxBus.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/RxBus.kt @@ -91,7 +91,7 @@ class RxBus { data class TrackDownloadState( val id: String, val state: DownloadStatus, - val progress: Int + val progress: Int? ) } diff --git a/ultrasonic/src/main/res/drawable/stat_sys_download.xml b/ultrasonic/src/main/res/drawable/stat_sys_download.xml deleted file mode 100644 index ba5754e5..00000000 --- a/ultrasonic/src/main/res/drawable/stat_sys_download.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - diff --git a/ultrasonic/src/main/res/drawable/stat_sys_download_anim_1.xml b/ultrasonic/src/main/res/drawable/stat_sys_download_anim_1.xml index 7cab81e6..34504676 100644 --- a/ultrasonic/src/main/res/drawable/stat_sys_download_anim_1.xml +++ b/ultrasonic/src/main/res/drawable/stat_sys_download_anim_1.xml @@ -8,6 +8,7 @@ android:fillColor="#FFF" android:pathData="M15,5V3H9v2"/> diff --git a/ultrasonic/src/main/res/drawable/stat_sys_download_anim_2.xml b/ultrasonic/src/main/res/drawable/stat_sys_download_anim_2.xml index ab4a8083..7c3b29d9 100644 --- a/ultrasonic/src/main/res/drawable/stat_sys_download_anim_2.xml +++ b/ultrasonic/src/main/res/drawable/stat_sys_download_anim_2.xml @@ -8,6 +8,7 @@ android:fillColor="#FFF" android:pathData="M15,7V3H9v4"/> diff --git a/ultrasonic/src/main/res/drawable/stat_sys_download_anim_3.xml b/ultrasonic/src/main/res/drawable/stat_sys_download_anim_3.xml index 427aa87f..2d55a557 100644 --- a/ultrasonic/src/main/res/drawable/stat_sys_download_anim_3.xml +++ b/ultrasonic/src/main/res/drawable/stat_sys_download_anim_3.xml @@ -8,6 +8,7 @@ android:fillColor="#FFF" android:pathData="M15,9V3H9v6"/> diff --git a/ultrasonic/src/main/res/drawable/stat_sys_download_anim_4.xml b/ultrasonic/src/main/res/drawable/stat_sys_download_anim_4.xml index d4fc28fb..8ab08780 100644 --- a/ultrasonic/src/main/res/drawable/stat_sys_download_anim_4.xml +++ b/ultrasonic/src/main/res/drawable/stat_sys_download_anim_4.xml @@ -8,6 +8,7 @@ android:fillColor="#FFF" android:pathData="M17,11 L19,9H15V3H9V9H5l2,2"/> diff --git a/ultrasonic/src/main/res/drawable/stat_sys_download_anim_5.xml b/ultrasonic/src/main/res/drawable/stat_sys_download_anim_5.xml index 809d1586..da7a3cce 100644 --- a/ultrasonic/src/main/res/drawable/stat_sys_download_anim_5.xml +++ b/ultrasonic/src/main/res/drawable/stat_sys_download_anim_5.xml @@ -8,6 +8,7 @@ android:fillColor="#FFF" android:pathData="M15,13 L19,9H15V3H9V9H5l4,4"/> diff --git a/ultrasonic/src/main/res/drawable/stat_sys_download_anim_6.xml b/ultrasonic/src/main/res/drawable/stat_sys_download_anim_6.xml index 97b14528..ce14d3c4 100644 --- a/ultrasonic/src/main/res/drawable/stat_sys_download_anim_6.xml +++ b/ultrasonic/src/main/res/drawable/stat_sys_download_anim_6.xml @@ -8,6 +8,7 @@ android:fillColor="#FFF" android:pathData="M13,15 L19,9H15V3H9V9H5l6,6"/> diff --git a/ultrasonic/src/main/res/drawable/stat_sys_download_anim_7.xml b/ultrasonic/src/main/res/drawable/stat_sys_download_anim_7.xml index b4becdde..9255455d 100644 --- a/ultrasonic/src/main/res/drawable/stat_sys_download_anim_7.xml +++ b/ultrasonic/src/main/res/drawable/stat_sys_download_anim_7.xml @@ -8,6 +8,7 @@ android:fillColor="#FFF" android:pathData="M19,9H15V3H9V9H5l7,7z"/>