Refactoring ChapterItem to make the download button more reusable

This commit is contained in:
Jay 2020-03-28 15:07:21 -04:00
parent d82b6fbe04
commit 0d658d4b05
11 changed files with 128 additions and 168 deletions

View File

@ -61,6 +61,9 @@ import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets
import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.updatePadding
import java.util.Date
import java.util.concurrent.TimeUnit
import kotlin.math.abs
import kotlinx.android.synthetic.main.main_activity.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
@ -68,9 +71,6 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
import java.util.Date
import java.util.concurrent.TimeUnit
import kotlin.math.abs
open class MainActivity : BaseActivity(), DownloadServiceListener {

View File

@ -2,14 +2,12 @@ package eu.kanade.tachiyomi.ui.manga
import android.content.Context
import android.view.View
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.ItemTouchHelper
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.manga.chapter.BaseChapterAdapter
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
import eu.kanade.tachiyomi.util.system.getResourceColor
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
@ -18,7 +16,7 @@ import uy.kohesive.injekt.injectLazy
class MangaDetailsAdapter(
val controller: MangaDetailsController,
context: Context
) : FlexibleAdapter<IFlexible<*>>(null, controller, true) {
) : BaseChapterAdapter<IFlexible<*>>(controller) {
val preferences: PreferencesHelper by injectLazy()
@ -44,11 +42,6 @@ class MangaDetailsAdapter(
return items.indexOf(item)
}
fun unlock() {
val activity = controller.activity as? FragmentActivity ?: return
SecureActivityDelegate.promptLockIfNeeded(activity)
}
fun performFilter() {
val s = getFilter(String::class.java)
if (s.isNullOrBlank()) {
@ -84,9 +77,4 @@ class MangaDetailsAdapter(
fun zoomImageFromThumb(thumbView: View)
fun showTrackingSheet()
}
interface DownloadInterface {
fun downloadChapter(position: Int)
fun startDownloadNow(position: Int)
}
}

View File

@ -0,0 +1,16 @@
package eu.kanade.tachiyomi.ui.manga.chapter
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible
open class BaseChapterAdapter<T : IFlexible<*>>(
obj: DownloadInterface
) : FlexibleAdapter<T>(null, obj, true) {
val baseDelegate = obj
interface DownloadInterface {
fun downloadChapter(position: Int)
fun startDownloadNow(position: Int)
}
}

View File

@ -0,0 +1,52 @@
package eu.kanade.tachiyomi.ui.manga.chapter
import android.view.View
import androidx.appcompat.widget.PopupMenu
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import kotlinx.android.synthetic.main.download_button.*
open class BaseChapterHolder(
view: View,
private val adapter: BaseChapterAdapter<*>
) : BaseFlexibleViewHolder(view, adapter) {
init {
download_button.setOnClickListener { downloadOrRemoveMenu() }
}
private fun downloadOrRemoveMenu() {
val chapter = adapter.getItem(adapterPosition) as? BaseChapterItem ?: return
if (chapter.status == Download.NOT_DOWNLOADED || chapter.status == Download.ERROR) {
adapter.baseDelegate.downloadChapter(adapterPosition)
} else {
download_button.post {
// Create a PopupMenu, giving it the clicked view for an anchor
val popup = PopupMenu(download_button.context, download_button)
// Inflate our menu resource into the PopupMenu's Menu
popup.menuInflater.inflate(R.menu.chapter_download, popup.menu)
popup.menu.findItem(R.id.action_start).isVisible = chapter.status == Download.QUEUE
// Hide download and show delete if the chapter is downloaded
if (chapter.status != Download.DOWNLOADED) popup.menu.findItem(R.id.action_delete).title = download_button.context.getString(
R.string.action_cancel
)
// Set a listener so we are notified if a menu item is clicked
popup.setOnMenuItemClickListener { item ->
when (item.itemId) {
R.id.action_delete -> adapter.baseDelegate.downloadChapter(adapterPosition)
R.id.action_start -> adapter.baseDelegate.startDownloadNow(adapterPosition)
}
true
}
// Finally show the PopupMenu
popup.show()
}
}
}
}

View File

@ -0,0 +1,40 @@
package eu.kanade.tachiyomi.ui.manga.chapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.source.model.Page
abstract class BaseChapterItem<T : BaseChapterHolder>(val chapter: Chapter) :
AbstractFlexibleItem<T>(),
Chapter by chapter {
private var _status: Int = 0
val progress: Int
get() {
val pages = download?.pages ?: return 0
return pages.map(Page::progress).average().toInt()
}
var status: Int
get() = download?.status ?: _status
set(value) { _status = value }
@Transient var download: Download? = null
val isDownloaded: Boolean
get() = status == Download.DOWNLOADED
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other is BaseChapterItem<*>) {
return chapter.id!! == other.chapter.id!!
}
return false
}
override fun hashCode(): Int {
return chapter.id!!.hashCode()
}
}

View File

@ -2,13 +2,11 @@ package eu.kanade.tachiyomi.ui.manga.chapter
import android.text.format.DateUtils
import android.view.View
import androidx.appcompat.widget.PopupMenu
import androidx.core.content.ContextCompat
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import eu.kanade.tachiyomi.ui.manga.MangaDetailsAdapter
import eu.kanade.tachiyomi.util.view.gone
import eu.kanade.tachiyomi.util.view.visibleIf
@ -17,53 +15,18 @@ import kotlinx.android.synthetic.main.chapters_item.*
import kotlinx.android.synthetic.main.download_button.*
class ChapterHolder(
private val view: View,
view: View,
private val adapter: MangaDetailsAdapter
) : BaseFlexibleViewHolder(view, adapter) {
) : BaseChapterHolder(view, adapter) {
private var localSource = false
init {
download_button.setOnClickListener { downloadOrRemoveMenu() }
download_button.setOnLongClickListener {
adapter.delegate.startDownloadRange(adapterPosition)
true
}
}
private fun downloadOrRemoveMenu() {
val chapter = adapter.getItem(adapterPosition) as? ChapterItem ?: return
if (chapter.status == Download.NOT_DOWNLOADED || chapter.status == Download.ERROR) {
adapter.delegate.downloadChapter(adapterPosition)
} else {
download_button.post {
// Create a PopupMenu, giving it the clicked view for an anchor
val popup = PopupMenu(download_button.context, download_button)
// Inflate our menu resource into the PopupMenu's Menu
popup.menuInflater.inflate(R.menu.chapter_download, popup.menu)
popup.menu.findItem(R.id.action_start).isVisible = chapter.status == Download.QUEUE
// Hide download and show delete if the chapter is downloaded
if (chapter.status != Download.DOWNLOADED) popup.menu.findItem(R.id.action_delete).title = download_button.context.getString(
R.string.action_cancel
)
// Set a listener so we are notified if a menu item is clicked
popup.setOnMenuItemClickListener { item ->
when (item.itemId) {
R.id.action_delete -> adapter.delegate.downloadChapter(adapterPosition)
R.id.action_start -> adapter.delegate.startDownloadNow(adapterPosition)
}
true
}
// Finally show the PopupMenu
popup.show()
}
}
}
fun bind(item: ChapterItem, manga: Manga) {
val chapter = item.chapter
val isLocked = item.isLocked

View File

@ -3,37 +3,17 @@ package eu.kanade.tachiyomi.ui.manga.chapter
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.ui.manga.MangaDetailsAdapter
class ChapterItem(val chapter: Chapter, val manga: Manga) :
AbstractFlexibleItem<ChapterHolder>(),
Chapter by chapter {
class ChapterItem(chapter: Chapter, val manga: Manga) :
BaseChapterItem<ChapterHolder>(chapter) {
private var _status: Int = 0
val progress: Int
get() {
val pages = download?.pages ?: return 0
return pages.map(Page::progress).average().toInt()
}
var isLocked = false
var status: Int
get() = download?.status ?: _status
set(value) { _status = value }
@Transient var download: Download? = null
val isDownloaded: Boolean
get() = status == Download.DOWNLOADED
override fun getLayoutRes(): Int {
return R.layout.chapters_item
}
@ -58,16 +38,4 @@ class ChapterItem(val chapter: Chapter, val manga: Manga) :
) {
holder.bind(this, manga)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other is ChapterItem) {
return chapter.id!! == other.chapter.id!!
}
return false
}
override fun hashCode(): Int {
return chapter.id!!.hashCode()
}
}

View File

@ -2,20 +2,19 @@ package eu.kanade.tachiyomi.ui.recents
import android.widget.ImageView
import androidx.recyclerview.widget.ItemTouchHelper
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.ui.manga.MangaDetailsAdapter
import eu.kanade.tachiyomi.ui.manga.chapter.BaseChapterAdapter
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
class RecentMangaAdapter(val delegate: RecentsInterface) :
FlexibleAdapter<IFlexible<RecentMangaHolder>>(null, delegate, true) {
BaseChapterAdapter<IFlexible<RecentMangaHolder>>(delegate) {
val decimalFormat = DecimalFormat("#.###", DecimalFormatSymbols()
.apply { decimalSeparator = '.' })
interface RecentsInterface : RecentMangaInterface, MangaDetailsAdapter.DownloadInterface
interface RecentsInterface : RecentMangaInterface, DownloadInterface
interface RecentMangaInterface {
fun onCoverClick(position: Int)

View File

@ -2,11 +2,10 @@ package eu.kanade.tachiyomi.ui.recents
import android.text.format.DateUtils
import android.view.View
import androidx.appcompat.widget.PopupMenu
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import eu.kanade.tachiyomi.ui.manga.chapter.BaseChapterHolder
import eu.kanade.tachiyomi.util.view.visibleIf
import java.util.Date
import kotlinx.android.synthetic.main.download_button.*
@ -15,45 +14,10 @@ import kotlinx.android.synthetic.main.recent_manga_item.*
class RecentMangaHolder(
view: View,
val adapter: RecentMangaAdapter
) : BaseFlexibleViewHolder(view, adapter) {
) : BaseChapterHolder(view, adapter) {
init {
cover_thumbnail.setOnClickListener { adapter.delegate.onCoverClick(adapterPosition) }
download_button.setOnClickListener { downloadOrRemoveMenu() }
}
private fun downloadOrRemoveMenu() {
val chapter = adapter.getItem(adapterPosition) as? RecentMangaItem ?: return
if (chapter.status == Download.NOT_DOWNLOADED || chapter.status == Download.ERROR) {
adapter.delegate.downloadChapter(adapterPosition)
} else {
download_button.post {
// Create a PopupMenu, giving it the clicked view for an anchor
val popup = PopupMenu(download_button.context, download_button)
// Inflate our menu resource into the PopupMenu's Menu
popup.menuInflater.inflate(R.menu.chapter_download, popup.menu)
popup.menu.findItem(R.id.action_start).isVisible = chapter.status == Download.QUEUE
// Hide download and show delete if the chapter is downloaded
if (chapter.status != Download.DOWNLOADED) popup.menu.findItem(R.id.action_delete).title = download_button.context.getString(
R.string.action_cancel
)
// Set a listener so we are notified if a menu item is clicked
popup.setOnMenuItemClickListener { item ->
when (item.itemId) {
R.id.action_delete -> adapter.delegate.downloadChapter(adapterPosition)
R.id.action_start -> adapter.delegate.startDownloadNow(adapterPosition)
}
true
}
// Finally show the PopupMenu
popup.show()
}
}
}
fun bind(item: RecentMangaItem) {
@ -102,9 +66,8 @@ class RecentMangaHolder(
)
}
fun notifyStatus(status: Int, progress: Int) = with(download_button) {
setDownloadStatus(status, progress)
}
fun notifyStatus(status: Int, progress: Int) =
download_button.setDownloadStatus(status, progress)
override fun getFrontView(): View {
return front_view

View File

@ -3,31 +3,14 @@ package eu.kanade.tachiyomi.ui.recents
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.ui.manga.chapter.BaseChapterItem
class RecentMangaItem(val mch: MangaChapterHistory, val chapter: Chapter) :
AbstractFlexibleItem<RecentMangaHolder>
() {
private var _status: Int = 0
val progress: Int
get() {
val pages = download?.pages ?: return 0
return pages.map(Page::progress).average().toInt()
}
var status: Int
get() = download?.status ?: _status
set(value) { _status = value }
@Transient var download: Download? = null
class RecentMangaItem(val mch: MangaChapterHistory, chapter: Chapter) :
BaseChapterItem<RecentMangaHolder>(chapter) {
override fun getLayoutRes(): Int {
return R.layout.recent_manga_item
@ -46,18 +29,6 @@ class RecentMangaItem(val mch: MangaChapterHistory, val chapter: Chapter) :
position: Int,
payloads: MutableList<Any?>?
) {
holder.bind(this)
}
override fun equals(other: Any?): Boolean {
if (other is RecentMangaItem) {
return chapter.id == other.chapter.id
}
return false
}
override fun hashCode(): Int {
return chapter.id!!.hashCode()
}
}

View File

@ -134,7 +134,7 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
}
}
fun refreshItem(chapterId: Long) {
private fun refreshItem(chapterId: Long) {
for (i in 0 until adapter.itemCount) {
val holder = recycler.findViewHolderForAdapterPosition(i) as? RecentsHolder ?: continue
holder.refreshChapter(chapterId)