mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-23 18:41:48 +01:00
Animating Download Button (I can't stop)
from downloading to download goes to: Fill in circle Fly in a check mark to replace the down arrow (looks like upstream at the moment....am I changing to be like upstream?) SIKE, it changes right back to the down arrow after a second ...why am I like this Also I removed the double download completed call to listeners or whatever oh and cleanup of dlqueue i guess
This commit is contained in:
parent
2c143155d6
commit
7f47c5fd4d
@ -494,7 +494,7 @@ class Downloader(
|
||||
// Delete successful downloads from queue
|
||||
if (download.status == Download.DOWNLOADED) {
|
||||
// remove downloaded chapter from queue
|
||||
queue.remove(download)
|
||||
queue.remove(download, false)
|
||||
}
|
||||
if (areAllDownloadsFinished()) {
|
||||
DownloadService.stop(context)
|
||||
|
@ -5,7 +5,6 @@ import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.download.DownloadStore
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import rx.Observable
|
||||
import rx.subjects.PublishSubject
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
|
||||
@ -32,7 +31,7 @@ class DownloadQueue(
|
||||
updatedRelay.call(Unit)
|
||||
}
|
||||
|
||||
fun remove(download: Download) {
|
||||
fun remove(download: Download, callListeners: Boolean = true) {
|
||||
val removed = queue.remove(download)
|
||||
store.remove(download)
|
||||
download.setStatusSubject(null)
|
||||
@ -40,7 +39,9 @@ class DownloadQueue(
|
||||
if (download.status == Download.DOWNLOADING || download.status == Download.QUEUE) {
|
||||
download.status = Download.NOT_DOWNLOADED
|
||||
}
|
||||
downloadListeners.forEach { it.updateDownload(download) }
|
||||
if (callListeners) {
|
||||
downloadListeners.forEach { it.updateDownload(download) }
|
||||
}
|
||||
if (removed) {
|
||||
updatedRelay.call(Unit)
|
||||
}
|
||||
@ -76,15 +77,6 @@ class DownloadQueue(
|
||||
updatedRelay.call(Unit)
|
||||
}
|
||||
|
||||
fun getActiveDownloads(): Observable<Download> =
|
||||
Observable.from(this).filter { download -> download.status == Download.DOWNLOADING }
|
||||
|
||||
fun getStatusObservable(): Observable<Download> = statusSubject.onBackpressureBuffer()
|
||||
|
||||
fun getUpdatedObservable(): Observable<List<Download>> = updatedRelay.onBackpressureBuffer()
|
||||
.startWith(Unit)
|
||||
.map { this }
|
||||
|
||||
private fun setPagesFor(download: Download) {
|
||||
if (download.status == Download.DOWNLOADING) {
|
||||
if (download.pages != null) {
|
||||
@ -93,12 +85,12 @@ class DownloadQueue(
|
||||
callListeners(download)
|
||||
}
|
||||
}
|
||||
downloadListeners.forEach { it.updateDownload(download) }
|
||||
callListeners(download)
|
||||
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
|
||||
setPagesSubject(download.pages, null)
|
||||
downloadListeners.forEach { it.updateDownload(download) }
|
||||
callListeners(download)
|
||||
} else {
|
||||
downloadListeners.forEach { it.updateDownload(download) }
|
||||
callListeners(download)
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,27 +98,6 @@ class DownloadQueue(
|
||||
downloadListeners.forEach { it.updateDownload(download) }
|
||||
}
|
||||
|
||||
fun getProgressObservable(): Observable<Download> {
|
||||
return statusSubject.onBackpressureBuffer()
|
||||
.startWith(getActiveDownloads())
|
||||
.flatMap { download ->
|
||||
if (download.status == Download.DOWNLOADING) {
|
||||
val pageStatusSubject = PublishSubject.create<Int>()
|
||||
setPagesSubject(download.pages, pageStatusSubject)
|
||||
downloadListeners.forEach { it.updateDownload(download) }
|
||||
return@flatMap pageStatusSubject
|
||||
.onBackpressureBuffer()
|
||||
.filter { it == Page.READY }
|
||||
.map { download }
|
||||
} else if (download.status == Download.DOWNLOADED || download.status == Download.ERROR) {
|
||||
setPagesSubject(download.pages, null)
|
||||
downloadListeners.forEach { it.updateDownload(download) }
|
||||
}
|
||||
Observable.just(download)
|
||||
}
|
||||
.filter { it.status == Download.DOWNLOADING }
|
||||
}
|
||||
|
||||
private fun setPagesSubject(pages: List<Page>?, subject: PublishSubject<Int>?) {
|
||||
if (pages != null) {
|
||||
for (page in pages) {
|
||||
|
@ -1,18 +1,21 @@
|
||||
package eu.kanade.tachiyomi.ui.download
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.util.AttributeSet
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.databinding.DownloadButtonBinding
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import eu.kanade.tachiyomi.util.view.gone
|
||||
import eu.kanade.tachiyomi.util.view.visible
|
||||
import eu.kanade.tachiyomi.widget.EndAnimatorListener
|
||||
|
||||
class DownloadButton @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
FrameLayout(context, attrs) {
|
||||
@ -55,6 +58,14 @@ class DownloadButton @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||
context,
|
||||
R.drawable.ic_check_24dp
|
||||
)?.mutate()
|
||||
private val filledAnim = AnimatedVectorDrawableCompat.create(
|
||||
context,
|
||||
R.drawable.anim_outline_to_filled
|
||||
)
|
||||
private val checkAnim = AnimatedVectorDrawableCompat.create(
|
||||
context,
|
||||
R.drawable.anim_dl_to_check_to_dl
|
||||
)
|
||||
private var isAnimating = false
|
||||
private var iconAnimation: ObjectAnimator? = null
|
||||
|
||||
@ -65,7 +76,7 @@ class DownloadButton @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||
binding = DownloadButtonBinding.bind(this)
|
||||
}
|
||||
|
||||
fun setDownloadStatus(state: Int, progress: Int = 0) {
|
||||
fun setDownloadStatus(state: Int, progress: Int = 0, animated: Boolean = false) {
|
||||
if (state != Download.DOWNLOADING) {
|
||||
iconAnimation?.cancel()
|
||||
binding.downloadIcon.alpha = 1f
|
||||
@ -124,9 +135,28 @@ class DownloadButton @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||
binding.downloadProgress.gone()
|
||||
binding.downloadBorder.visible()
|
||||
binding.downloadProgressIndeterminate.gone()
|
||||
binding.downloadBorder.setImageDrawable(filledCircle)
|
||||
binding.downloadBorder.drawable.setTint(downloadedColor)
|
||||
binding.downloadIcon.drawable.setTint(downloadedTextColor)
|
||||
if (animated) {
|
||||
binding.downloadBorder.setImageDrawable(filledAnim)
|
||||
binding.downloadIcon.setImageDrawable(checkAnim)
|
||||
filledAnim?.start()
|
||||
val alphaAnimation = ValueAnimator.ofArgb(disabledColor, downloadedTextColor)
|
||||
alphaAnimation.addUpdateListener { valueAnimator ->
|
||||
binding.downloadIcon.drawable.setTint(valueAnimator.animatedValue as Int)
|
||||
}
|
||||
alphaAnimation.addListener(
|
||||
EndAnimatorListener {
|
||||
binding.downloadIcon.drawable.setTint(downloadedTextColor)
|
||||
checkAnim?.start()
|
||||
}
|
||||
)
|
||||
alphaAnimation.duration = 150
|
||||
alphaAnimation.start()
|
||||
binding.downloadBorder.drawable.setTint(downloadedColor)
|
||||
} else {
|
||||
binding.downloadBorder.setImageDrawable(filledCircle)
|
||||
binding.downloadIcon.drawable.setTint(downloadedTextColor)
|
||||
}
|
||||
}
|
||||
Download.ERROR -> {
|
||||
binding.downloadProgress.gone()
|
||||
|
@ -523,7 +523,8 @@ class MangaDetailsController :
|
||||
getHolder(download.chapter)?.notifyStatus(
|
||||
download.status,
|
||||
presenter.isLockedFromSearch,
|
||||
download.progress
|
||||
download.progress,
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -152,12 +152,12 @@ class ChapterHolder(
|
||||
if (binding.frontView.translationX != 0f) itemView.post { adapter.notifyItemChanged(flexibleAdapterPosition) }
|
||||
}
|
||||
|
||||
fun notifyStatus(status: Int, locked: Boolean, progress: Int) = with(binding.downloadButton.downloadButton) {
|
||||
fun notifyStatus(status: Int, locked: Boolean, progress: Int, animated: Boolean = false) = with(binding.downloadButton.downloadButton) {
|
||||
if (locked) {
|
||||
gone()
|
||||
return
|
||||
}
|
||||
visibleIf(!localSource)
|
||||
setDownloadStatus(status, progress)
|
||||
setDownloadStatus(status, progress, animated)
|
||||
}
|
||||
}
|
||||
|
@ -138,8 +138,8 @@ class RecentMangaHolder(
|
||||
return item.mch.history.id != null
|
||||
}
|
||||
|
||||
fun notifyStatus(status: Int, progress: Int, isRead: Boolean) {
|
||||
binding.downloadButton.downloadButton.setDownloadStatus(status, progress)
|
||||
fun notifyStatus(status: Int, progress: Int, isRead: Boolean, animated: Boolean = false) {
|
||||
binding.downloadButton.downloadButton.setDownloadStatus(status, progress, animated)
|
||||
val isChapterRead =
|
||||
if (adapter.showDownloads == RecentMangaAdapter.ShowRecentsDLs.UnreadOrDownloaded) isRead else false
|
||||
binding.downloadButton.downloadButton.isVisible =
|
||||
|
@ -415,7 +415,7 @@ class RecentsController(bundle: Bundle? = null) :
|
||||
binding.downloadBottomSheet.dlBottomSheet.onUpdateDownloadedPages(download)
|
||||
val id = download.chapter.id ?: return
|
||||
val holder = binding.recycler.findViewHolderForItemId(id) as? RecentMangaHolder ?: return
|
||||
holder.notifyStatus(download.status, download.progress, download.chapter.read)
|
||||
holder.notifyStatus(download.status, download.progress, download.chapter.read, true)
|
||||
}
|
||||
|
||||
private fun refreshItem(chapterId: Long) {
|
||||
|
125
app/src/main/res/drawable/anim_dl_to_check_to_dl.xml
Normal file
125
app/src/main/res/drawable/anim_dl_to_check_to_dl.xml
Normal file
@ -0,0 +1,125 @@
|
||||
<animated-vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt">
|
||||
<aapt:attr name="android:drawable">
|
||||
<vector
|
||||
android:name="vector"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<group
|
||||
android:name="main_group"
|
||||
android:pivotX="12"
|
||||
android:pivotY="12">
|
||||
<path
|
||||
android:name="check_dl"
|
||||
android:pathData="M 21 7 L 9 19 L 3.5 13.5 L 4.91 12.09 L 9 16.17 L 19.59 5.59 L 21 7 Z"
|
||||
android:fillColor="#000"
|
||||
android:fillAlpha="0"
|
||||
android:strokeWidth="1"/>
|
||||
</group>
|
||||
<group android:name="start_group">
|
||||
<path
|
||||
android:name="start_dl"
|
||||
android:pathData="M 11 4 L 13 4 L 13 4 L 13 16 L 18.5 10.5 L 19.92 11.92 L 12 19.84 L 4.08 11.92 L 5.5 10.5 L 11 16 L 11 4 L 11 4"
|
||||
android:fillColor="#000000"/>
|
||||
<group
|
||||
android:name="check_group"
|
||||
android:translateY="12">
|
||||
<path
|
||||
android:name="start_check"
|
||||
android:pathData="M 19.59 5.59 L 21 7 L 21 7 L 10.479 17.521 L 10.479 17.521 L 9 19 L 9 19 L 3.5 13.5 L 4.91 12.09 L 9 16.17 L 19.325 5.855 L 19.59 5.59"
|
||||
android:fillColor="#000"
|
||||
android:fillAlpha="0"
|
||||
android:strokeWidth="1"/>
|
||||
</group>
|
||||
</group>
|
||||
</vector>
|
||||
</aapt:attr>
|
||||
<target android:name="check_dl">
|
||||
<aapt:attr name="android:animation">
|
||||
<set>
|
||||
<objectAnimator
|
||||
android:propertyName="pathData"
|
||||
android:startOffset="1250"
|
||||
android:duration="450"
|
||||
android:valueFrom="M 19.59 5.59 L 21 7 L 21 7 L 10.479 17.521 L 10.479 17.521 L 9 19 L 9 19 L 3.5 13.5 L 4.91 12.09 L 9 16.17 L 19.325 5.855 L 19.59 5.59"
|
||||
android:valueTo="M 11 4 L 13 4 L 13 4 L 13 16 L 18.5 10.5 L 19.92 11.92 L 12 19.84 L 4.08 11.92 L 5.5 10.5 L 11 16 L 11 4 L 11 4"
|
||||
android:valueType="pathType"
|
||||
android:interpolator="@android:interpolator/fast_out_slow_in"/>
|
||||
<objectAnimator
|
||||
android:propertyName="fillAlpha"
|
||||
android:duration="400"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="0"
|
||||
android:valueType="floatType"
|
||||
android:interpolator="@android:interpolator/fast_out_slow_in"/>
|
||||
<objectAnimator
|
||||
android:propertyName="fillAlpha"
|
||||
android:startOffset="400"
|
||||
android:duration="100"
|
||||
android:valueFrom="1"
|
||||
android:valueTo="1"
|
||||
android:valueType="floatType"
|
||||
android:interpolator="@android:interpolator/fast_out_slow_in"/>
|
||||
</set>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
<target android:name="main_group">
|
||||
<aapt:attr name="android:animation">
|
||||
<objectAnimator
|
||||
android:propertyName="rotation"
|
||||
android:startOffset="1250"
|
||||
android:duration="450"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="360"
|
||||
android:valueType="floatType"
|
||||
android:interpolator="@android:interpolator/fast_out_slow_in"/>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
<target android:name="start_group">
|
||||
<aapt:attr name="android:animation">
|
||||
<objectAnimator
|
||||
android:propertyName="translateY"
|
||||
android:duration="400"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="-12"
|
||||
android:valueType="floatType"
|
||||
android:interpolator="@android:interpolator/fast_out_slow_in"/>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
<target android:name="start_dl">
|
||||
<aapt:attr name="android:animation">
|
||||
<objectAnimator
|
||||
android:propertyName="fillAlpha"
|
||||
android:duration="250"
|
||||
android:valueFrom="1"
|
||||
android:valueTo="0"
|
||||
android:valueType="floatType"
|
||||
android:interpolator="@android:interpolator/fast_out_slow_in"/>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
<target android:name="start_check">
|
||||
<aapt:attr name="android:animation">
|
||||
<set>
|
||||
<objectAnimator
|
||||
android:propertyName="fillAlpha"
|
||||
android:startOffset="150"
|
||||
android:duration="250"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="1"
|
||||
android:valueType="floatType"
|
||||
android:interpolator="@android:interpolator/fast_out_slow_in"/>
|
||||
<objectAnimator
|
||||
android:propertyName="fillAlpha"
|
||||
android:startOffset="400"
|
||||
android:duration="100"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="0"
|
||||
android:valueType="floatType"
|
||||
android:interpolator="@android:interpolator/fast_out_slow_in"/>
|
||||
</set>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
</animated-vector>
|
29
app/src/main/res/drawable/anim_outline_to_filled.xml
Normal file
29
app/src/main/res/drawable/anim_outline_to_filled.xml
Normal file
@ -0,0 +1,29 @@
|
||||
<animated-vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt">
|
||||
<aapt:attr name="android:drawable">
|
||||
<vector
|
||||
android:name="vector"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:name="path"
|
||||
android:pathData="M 10 0 C 7.349 0 4.804 1.054 2.929 2.929 C 1.054 4.804 0 7.349 0 10 C 0 12.651 1.054 15.196 2.929 17.071 C 4.804 18.946 7.349 20 10 20 C 12.651 20 15.196 18.946 17.071 17.071 C 18.946 15.196 20 12.651 20 10 C 20 7.349 18.946 4.804 17.071 2.929 C 15.196 1.054 12.651 0 10 0 Z M 10 18 C 7.879 18 5.843 17.157 4.343 15.657 C 2.843 14.157 2 12.121 2 10 C 2 7.879 2.843 5.843 4.343 4.343 C 5.843 2.843 7.879 2 10 2 C 12.121 2 14.157 2.843 15.657 4.343 C 17.157 5.843 18 7.879 18 10 C 18 12.121 17.157 14.157 15.657 15.657 C 14.157 17.157 12.121 18 10 18"
|
||||
android:fillColor="#000"
|
||||
android:strokeWidth="1"/>
|
||||
</vector>
|
||||
</aapt:attr>
|
||||
<target android:name="path">
|
||||
<aapt:attr name="android:animation">
|
||||
<objectAnimator
|
||||
android:propertyName="pathData"
|
||||
android:duration="200"
|
||||
android:valueFrom="M 10 0 C 7.349 0 4.804 1.054 2.929 2.929 C 1.054 4.804 0 7.349 0 10 C 0 12.651 1.054 15.196 2.929 17.071 C 4.804 18.946 7.349 20 10 20 C 12.651 20 15.196 18.946 17.071 17.071 C 18.946 15.196 20 12.651 20 10 C 20 7.349 18.946 4.804 17.071 2.929 C 15.196 1.054 12.651 0 10 0 Z M 10 18 C 7.879 18 5.843 17.157 4.343 15.657 C 2.843 14.157 2 12.121 2 10 C 2 7.879 2.843 5.843 4.343 4.343 C 5.843 2.843 7.879 2 10 2 C 12.121 2 14.157 2.843 15.657 4.343 C 17.157 5.843 18 7.879 18 10 C 18 12.121 17.157 14.157 15.657 15.657 C 14.157 17.157 12.121 18 10 18"
|
||||
android:valueTo="M 10 0 C 7.349 0 4.804 1.054 2.929 2.929 C 1.054 4.804 0 7.349 0 10 C 0 12.651 1.054 15.196 2.929 17.071 C 4.804 18.946 7.349 20 10 20 C 12.651 20 15.196 18.946 17.071 17.071 C 18.946 15.196 20 12.651 20 10 C 20 7.349 18.946 4.804 17.071 2.929 C 15.196 1.054 12.651 0 10 0 Z M 10 10 C 10 10 10 10 10 10 C 10 10 10 10 10 10 C 10 10 10 10 10 10 C 10 10 10 10 10 10 C 10 10 10 10 10 10 C 10 10 10 10 10 10 C 10 10 10 10 10 10 C 10 10 10 10 10 10"
|
||||
android:valueType="pathType"
|
||||
android:interpolator="@android:interpolator/fast_out_slow_in"/>
|
||||
</aapt:attr>
|
||||
</target>
|
||||
</animated-vector>
|
Loading…
Reference in New Issue
Block a user