diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt index 8b53f8ed7..4a1b048f9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt @@ -34,6 +34,7 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.tachiyomi.data.download.DownloadService import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.databinding.MangaControllerBinding @@ -59,6 +60,7 @@ import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersSettingsSheet import eu.kanade.tachiyomi.ui.manga.chapter.DeleteChaptersDialog import eu.kanade.tachiyomi.ui.manga.chapter.DownloadCustomChaptersDialog import eu.kanade.tachiyomi.ui.manga.chapter.MangaChaptersHeaderAdapter +import eu.kanade.tachiyomi.ui.manga.chapter.base.BaseChaptersAdapter import eu.kanade.tachiyomi.ui.manga.info.MangaInfoHeaderAdapter import eu.kanade.tachiyomi.ui.manga.track.TrackController import eu.kanade.tachiyomi.ui.reader.ReaderActivity @@ -90,6 +92,7 @@ class MangaController : ActionMode.Callback, FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemLongClickListener, + BaseChaptersAdapter.OnChapterClickListener, ChangeMangaCoverDialog.Listener, ChangeMangaCategoriesDialog.Listener, DownloadCustomChaptersDialog.Listener, @@ -866,6 +869,22 @@ class MangaController : super.onDetach(view) } + override fun downloadChapter(position: Int) { + val item = chaptersAdapter?.getItem(position) ?: return + if (item.status == Download.State.ERROR) { + DownloadService.start(activity!!) + } else { + downloadChapters(listOf(item)) + } + chaptersAdapter?.updateItem(item) + } + + override fun deleteChapter(position: Int) { + val item = chaptersAdapter?.getItem(position) ?: return + deleteChapters(listOf(item)) + chaptersAdapter?.updateItem(item) + } + // SELECTION MODE ACTIONS private fun selectAll() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterDownloadView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterDownloadView.kt index 5b0ff95e8..755b71f12 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterDownloadView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterDownloadView.kt @@ -56,6 +56,4 @@ class ChapterDownloadView @JvmOverloads constructor(context: Context, attrs: Att binding.errorIcon.isVisible = state == Download.State.ERROR } - - // TODO: onClick actions } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt index a24ee4281..c0abbfd1f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt @@ -5,20 +5,24 @@ import android.text.SpannableStringBuilder import android.text.style.ForegroundColorSpan import android.view.View import androidx.core.view.isVisible -import eu.davidea.viewholders.FlexibleViewHolder import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.databinding.ChaptersItemBinding import eu.kanade.tachiyomi.source.LocalSource +import eu.kanade.tachiyomi.ui.manga.chapter.base.BaseChapterHolder import java.util.Date class ChapterHolder( view: View, private val adapter: ChaptersAdapter -) : FlexibleViewHolder(view, adapter) { +) : BaseChapterHolder(view, adapter) { private val binding = ChaptersItemBinding.bind(view) + init { + binding.download.setOnClickListener { onDownloadClick(it) } + } + fun bind(item: ChapterItem, manga: Manga) { val chapter = item.chapter diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterItem.kt index 4908422be..02713a0ff 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterItem.kt @@ -3,37 +3,16 @@ 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.AbstractHeaderItem import eu.davidea.flexibleadapter.items.IFlexible +import eu.davidea.viewholders.FlexibleViewHolder 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.chapter.base.BaseChapterItem -class ChapterItem(val chapter: Chapter, val manga: Manga) : - AbstractFlexibleItem(), - Chapter by chapter { - - private var _status: Download.State = Download.State.NOT_DOWNLOADED - - var status: Download.State - get() = download?.status ?: _status - set(value) { - _status = value - } - - val progress: Int - get() { - val pages = download?.pages ?: return 0 - return pages.map(Page::progress).average().toInt() - } - - @Transient - var download: Download? = null - - val isDownloaded: Boolean - get() = status == Download.State.DOWNLOADED +class ChapterItem(chapter: Chapter, val manga: Manga) : + BaseChapterItem>(chapter) { override fun getLayoutRes(): Int { return R.layout.chapters_item @@ -51,16 +30,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() - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersAdapter.kt index 4cc04d590..211729029 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersAdapter.kt @@ -1,10 +1,10 @@ package eu.kanade.tachiyomi.ui.manga.chapter import android.content.Context -import eu.davidea.flexibleadapter.FlexibleAdapter import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.ui.manga.MangaController +import eu.kanade.tachiyomi.ui.manga.chapter.base.BaseChaptersAdapter import eu.kanade.tachiyomi.util.system.getResourceColor import uy.kohesive.injekt.injectLazy import java.text.DateFormat @@ -14,7 +14,7 @@ import java.text.DecimalFormatSymbols class ChaptersAdapter( controller: MangaController, context: Context -) : FlexibleAdapter(null, controller, true) { +) : BaseChaptersAdapter(controller) { private val preferences: PreferencesHelper by injectLazy() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/base/BaseChapterHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/base/BaseChapterHolder.kt new file mode 100644 index 000000000..b7bd417d1 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/base/BaseChapterHolder.kt @@ -0,0 +1,38 @@ +package eu.kanade.tachiyomi.ui.manga.chapter.base + +import android.view.View +import eu.davidea.viewholders.FlexibleViewHolder +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.download.model.Download +import eu.kanade.tachiyomi.util.view.popupMenu + +open class BaseChapterHolder( + view: View, + private val adapter: BaseChaptersAdapter<*> +) : FlexibleViewHolder(view, adapter) { + + fun onDownloadClick(view: View) { + val item = adapter.getItem(bindingAdapterPosition) as? BaseChapterItem<*, *> ?: return + when (item.status) { + Download.State.NOT_DOWNLOADED, Download.State.ERROR -> { + adapter.clickListener.downloadChapter(bindingAdapterPosition) + } + else -> { + view.popupMenu( + R.menu.chapter_download, + initMenu = { + // Download.State.DOWNLOADED + findItem(R.id.delete_download).isVisible = item.status == Download.State.DOWNLOADED + + // Download.State.DOWNLOADING, Download.State.QUEUE + findItem(R.id.cancel_download).isVisible = item.status != Download.State.DOWNLOADED + }, + onMenuItemClick = { + adapter.clickListener.deleteChapter(bindingAdapterPosition) + true + } + ) + } + } + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/base/BaseChapterItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/base/BaseChapterItem.kt new file mode 100644 index 000000000..04aee7d55 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/base/BaseChapterItem.kt @@ -0,0 +1,47 @@ +package eu.kanade.tachiyomi.ui.manga.chapter.base + +import eu.davidea.flexibleadapter.items.AbstractHeaderItem +import eu.davidea.flexibleadapter.items.AbstractSectionableItem +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>( + val chapter: Chapter, + header: H? = null +) : + AbstractSectionableItem(header), + Chapter by chapter { + + private var _status: Download.State = Download.State.NOT_DOWNLOADED + + var status: Download.State + get() = download?.status ?: _status + set(value) { + _status = value + } + + val progress: Int + get() { + val pages = download?.pages ?: return 0 + return pages.map(Page::progress).average().toInt() + } + + @Transient + var download: Download? = null + + val isDownloaded: Boolean + get() = status == Download.State.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() + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/base/BaseChaptersAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/base/BaseChaptersAdapter.kt new file mode 100644 index 000000000..9beaef71f --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/base/BaseChaptersAdapter.kt @@ -0,0 +1,22 @@ +package eu.kanade.tachiyomi.ui.manga.chapter.base + +import eu.davidea.flexibleadapter.FlexibleAdapter +import eu.davidea.flexibleadapter.items.IFlexible + +abstract class BaseChaptersAdapter>( + controller: OnChapterClickListener +) : FlexibleAdapter(null, controller, true) { + + /** + * Listener for browse item clicks. + */ + val clickListener: OnChapterClickListener = controller + + /** + * Listener which should be called when user clicks the download icons. + */ + interface OnChapterClickListener { + fun downloadChapter(position: Int) + fun deleteChapter(position: Int) + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesAdapter.kt index 39d485bc7..764308246 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesAdapter.kt @@ -1,15 +1,15 @@ package eu.kanade.tachiyomi.ui.recent.updates import android.content.Context -import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.IFlexible import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.ui.manga.chapter.base.BaseChaptersAdapter import eu.kanade.tachiyomi.util.system.getResourceColor class UpdatesAdapter( val controller: UpdatesController, context: Context -) : FlexibleAdapter>(null, controller, true) { +) : BaseChaptersAdapter>(controller) { var readColor = context.getResourceColor(R.attr.colorOnSurface, 0.38f) var unreadColor = context.getResourceColor(R.attr.colorOnSurface) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesController.kt index e572393e6..a72a77ad9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesController.kt @@ -13,6 +13,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.SelectableAdapter import eu.davidea.flexibleadapter.items.IFlexible import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.download.DownloadService import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.library.LibraryUpdateService import eu.kanade.tachiyomi.data.notification.Notifications @@ -23,6 +24,7 @@ import eu.kanade.tachiyomi.ui.base.controller.RootController import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.manga.MangaController +import eu.kanade.tachiyomi.ui.manga.chapter.base.BaseChaptersAdapter import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.util.system.notificationManager import eu.kanade.tachiyomi.util.system.toast @@ -45,6 +47,7 @@ class UpdatesController : FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemLongClickListener, FlexibleAdapter.OnUpdateListener, + BaseChaptersAdapter.OnChapterClickListener, ConfirmDeleteChaptersDialog.Listener, UpdatesAdapter.OnCoverClickListener { @@ -291,6 +294,22 @@ class UpdatesController : Timber.e(error) } + override fun downloadChapter(position: Int) { + val item = adapter?.getItem(position) as? UpdatesItem ?: return + if (item.status == Download.State.ERROR) { + DownloadService.start(activity!!) + } else { + downloadChapters(listOf(item)) + } + adapter?.updateItem(item) + } + + override fun deleteChapter(position: Int) { + val item = adapter?.getItem(position) as? UpdatesItem ?: return + deleteChapters(listOf(item)) + adapter?.updateItem(item) + } + /** * Called when ActionMode created. * @param mode the ActionMode object diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesHolder.kt index 49194cae3..878affbb6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesHolder.kt @@ -6,12 +6,12 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.resource.bitmap.CenterCrop import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.bumptech.glide.request.RequestOptions -import eu.davidea.viewholders.FlexibleViewHolder import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.glide.GlideApp import eu.kanade.tachiyomi.data.glide.toMangaThumbnail import eu.kanade.tachiyomi.databinding.UpdatesItemBinding import eu.kanade.tachiyomi.source.LocalSource +import eu.kanade.tachiyomi.ui.manga.chapter.base.BaseChapterHolder /** * Holder that contains chapter item @@ -23,7 +23,7 @@ import eu.kanade.tachiyomi.source.LocalSource * @constructor creates a new recent chapter holder. */ class UpdatesHolder(private val view: View, private val adapter: UpdatesAdapter) : - FlexibleViewHolder(view, adapter) { + BaseChapterHolder(view, adapter) { private val binding = UpdatesItemBinding.bind(view) @@ -31,6 +31,8 @@ class UpdatesHolder(private val view: View, private val adapter: UpdatesAdapter) binding.mangaCover.setOnClickListener { adapter.coverClickListener.onCoverClick(bindingAdapterPosition) } + + binding.download.setOnClickListener { onDownloadClick(it) } } fun bind(item: UpdatesItem) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesItem.kt index 0a9d2fa8e..1f25244b5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesItem.kt @@ -3,37 +3,15 @@ package eu.kanade.tachiyomi.ui.recent.updates import android.view.View import androidx.recyclerview.widget.RecyclerView import eu.davidea.flexibleadapter.FlexibleAdapter -import eu.davidea.flexibleadapter.items.AbstractSectionableItem 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.chapter.base.BaseChapterItem import eu.kanade.tachiyomi.ui.recent.DateSectionItem -class UpdatesItem(val chapter: Chapter, val manga: Manga, header: DateSectionItem) : - AbstractSectionableItem(header) { - - private var _status: Download.State = Download.State.NOT_DOWNLOADED - - var status: Download.State - get() = download?.status ?: _status - set(value) { - _status = value - } - - val progress: Int - get() { - val pages = download?.pages ?: return 0 - return pages.map(Page::progress).average().toInt() - } - - @Transient - var download: Download? = null - - val isDownloaded: Boolean - get() = status == Download.State.DOWNLOADED +class UpdatesItem(chapter: Chapter, val manga: Manga, header: DateSectionItem) : + BaseChapterItem(chapter, header) { override fun getLayoutRes(): Int { return R.layout.updates_item @@ -51,16 +29,4 @@ class UpdatesItem(val chapter: Chapter, val manga: Manga, header: DateSectionIte ) { holder.bind(this) } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other is UpdatesItem) { - return chapter.id!! == other.chapter.id!! - } - return false - } - - override fun hashCode(): Int { - return chapter.id!!.hashCode() - } } diff --git a/app/src/main/res/layout/chapter_download_view.xml b/app/src/main/res/layout/chapter_download_view.xml index bbdd0c7d5..3fa128aa3 100644 --- a/app/src/main/res/layout/chapter_download_view.xml +++ b/app/src/main/res/layout/chapter_download_view.xml @@ -4,9 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="28dp" android:layout_height="28dp" - android:background="?selectableItemBackgroundBorderless" - android:clickable="true" - android:focusable="true"> + android:background="?selectableItemBackgroundBorderless"> + + + + + + +