mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-09 19:55:11 +01:00
Recents can now be filtered for only history or updates
This commit is contained in:
parent
cb6de21804
commit
6533689539
@ -245,7 +245,7 @@ class PreferencesHelper(val context: Context) {
|
|||||||
|
|
||||||
fun extensionUpdatesCount() = rxPrefs.getInteger("ext_updates_count", 0)
|
fun extensionUpdatesCount() = rxPrefs.getInteger("ext_updates_count", 0)
|
||||||
|
|
||||||
fun groupRecents() = rxPrefs.getBoolean("group_recents", true)
|
fun recentsViewType() = rxPrefs.getInteger("recents_view_type", 0)
|
||||||
|
|
||||||
fun lastExtCheck() = rxPrefs.getLong("last_ext_check", 0)
|
fun lastExtCheck() = rxPrefs.getLong("last_ext_check", 0)
|
||||||
|
|
||||||
|
@ -145,7 +145,8 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
|||||||
}) return@setOnNavigationItemSelectedListener false
|
}) return@setOnNavigationItemSelectedListener false
|
||||||
}
|
}
|
||||||
continueSwitchingTabs = false
|
continueSwitchingTabs = false
|
||||||
preferences.lastTab().set(item.itemId)
|
if (item.itemId != R.id.nav_browse)
|
||||||
|
preferences.lastTab().set(item.itemId)
|
||||||
val currentRoot = router.backstack.firstOrNull()
|
val currentRoot = router.backstack.firstOrNull()
|
||||||
if (currentRoot?.tag()?.toIntOrNull() != id) {
|
if (currentRoot?.tag()?.toIntOrNull() != id) {
|
||||||
setRoot(when (id) {
|
setRoot(when (id) {
|
||||||
@ -311,12 +312,12 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
|||||||
private fun setExtensionsBadge() {
|
private fun setExtensionsBadge() {
|
||||||
val updates = preferences.extensionUpdatesCount().getOrDefault()
|
val updates = preferences.extensionUpdatesCount().getOrDefault()
|
||||||
if (updates > 0) {
|
if (updates > 0) {
|
||||||
val badge = bottom_nav.getOrCreateBadge(R.id.nav_catalogues)
|
val badge = bottom_nav.getOrCreateBadge(R.id.nav_browse)
|
||||||
badge.number = updates
|
badge.number = updates
|
||||||
badge.backgroundColor = getResourceColor(R.attr.badgeColor)
|
badge.backgroundColor = getResourceColor(R.attr.badgeColor)
|
||||||
badge.badgeTextColor = Color.WHITE
|
badge.badgeTextColor = Color.WHITE
|
||||||
} else {
|
} else {
|
||||||
bottom_nav.removeBadge(R.id.nav_catalogues)
|
bottom_nav.removeBadge(R.id.nav_browse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,9 +368,9 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
|
|||||||
}
|
}
|
||||||
router.pushController(controller.withFadeTransaction())
|
router.pushController(controller.withFadeTransaction())
|
||||||
}
|
}
|
||||||
SHORTCUT_CATALOGUES -> bottom_nav.selectedItemId = R.id.nav_catalogues
|
SHORTCUT_CATALOGUES -> bottom_nav.selectedItemId = R.id.nav_browse
|
||||||
SHORTCUT_EXTENSIONS -> {
|
SHORTCUT_EXTENSIONS -> {
|
||||||
bottom_nav.selectedItemId = R.id.nav_catalogues
|
bottom_nav.selectedItemId = R.id.nav_browse
|
||||||
router.popToRoot()
|
router.popToRoot()
|
||||||
bottom_nav.post {
|
bottom_nav.post {
|
||||||
val controller =
|
val controller =
|
||||||
|
@ -11,7 +11,8 @@ import eu.davidea.viewholders.FlexibleViewHolder
|
|||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
class DateItem(val date: Date) : AbstractHeaderItem<DateItem.Holder>() {
|
class DateItem(val date: Date, val addedString: Boolean = false) : AbstractHeaderItem<DateItem
|
||||||
|
.Holder>() {
|
||||||
|
|
||||||
override fun getLayoutRes(): Int {
|
override fun getLayoutRes(): Int {
|
||||||
return R.layout.recent_chapters_section_item
|
return R.layout.recent_chapters_section_item
|
||||||
@ -44,7 +45,9 @@ class DateItem(val date: Date) : AbstractHeaderItem<DateItem.Holder>() {
|
|||||||
val section_text: TextView = view.findViewById(R.id.section_text)
|
val section_text: TextView = view.findViewById(R.id.section_text)
|
||||||
|
|
||||||
fun bind(item: DateItem) {
|
fun bind(item: DateItem) {
|
||||||
section_text.text = DateUtils.getRelativeTimeSpanString(item.date.time, now, DateUtils.DAY_IN_MILLIS)
|
val dateString = DateUtils.getRelativeTimeSpanString(item.date.time, now, DateUtils.DAY_IN_MILLIS)
|
||||||
|
section_text.text =
|
||||||
|
if (item.addedString) itemView.context.getString(R.string.added_, dateString) else dateString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import com.afollestad.materialdialogs.checkbox.checkBoxPrompt
|
|||||||
import com.afollestad.materialdialogs.checkbox.isCheckPromptChecked
|
import com.afollestad.materialdialogs.checkbox.isCheckPromptChecked
|
||||||
import com.bluelinelabs.conductor.Controller
|
import com.bluelinelabs.conductor.Controller
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||||
import eu.kanade.tachiyomi.data.database.models.History
|
import eu.kanade.tachiyomi.data.database.models.History
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||||
@ -18,21 +19,28 @@ class RemoveHistoryDialog<T>(bundle: Bundle? = null) : DialogController(bundle)
|
|||||||
|
|
||||||
private var history: History? = null
|
private var history: History? = null
|
||||||
|
|
||||||
constructor(target: T, manga: Manga, history: History) : this() {
|
private var chapter: Chapter? = null
|
||||||
|
|
||||||
|
constructor(target: T, manga: Manga, history: History, chapter: Chapter? = null) : this() {
|
||||||
this.manga = manga
|
this.manga = manga
|
||||||
this.history = history
|
this.history = history
|
||||||
|
this.chapter = chapter
|
||||||
targetController = target
|
targetController = target
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||||
val activity = activity!!
|
val activity = activity!!
|
||||||
|
|
||||||
return MaterialDialog(activity).title(R.string.remove)
|
return MaterialDialog(activity).title(R.string.reset_chapter_question).message(
|
||||||
.message(R.string.this_will_remove_the_read_date_question).checkBoxPrompt(
|
text = if (chapter?.name != null) activity.getString(
|
||||||
|
R.string.this_will_remove_the_read_date_for_x_question, chapter?.name ?: ""
|
||||||
|
)
|
||||||
|
else activity.getString(R.string.this_will_remove_the_read_date_question)
|
||||||
|
).checkBoxPrompt(
|
||||||
text = activity.getString(
|
text = activity.getString(
|
||||||
R.string.reset_all_chapters_for_this_, manga!!.mangaType(activity)
|
R.string.reset_all_chapters_for_this_, manga!!.mangaType(activity)
|
||||||
)
|
)
|
||||||
) {}.negativeButton(android.R.string.cancel).positiveButton(R.string.remove) {
|
) {}.negativeButton(android.R.string.cancel).positiveButton(R.string.reset) {
|
||||||
onPositive(it.isCheckPromptChecked())
|
onPositive(it.isCheckPromptChecked())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.data.download.model.Download
|
|||||||
import eu.kanade.tachiyomi.data.glide.GlideApp
|
import eu.kanade.tachiyomi.data.glide.GlideApp
|
||||||
import eu.kanade.tachiyomi.source.LocalSource
|
import eu.kanade.tachiyomi.source.LocalSource
|
||||||
import eu.kanade.tachiyomi.ui.manga.chapter.BaseChapterHolder
|
import eu.kanade.tachiyomi.ui.manga.chapter.BaseChapterHolder
|
||||||
|
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||||
import eu.kanade.tachiyomi.util.view.visibleIf
|
import eu.kanade.tachiyomi.util.view.visibleIf
|
||||||
import kotlinx.android.synthetic.main.download_button.*
|
import kotlinx.android.synthetic.main.download_button.*
|
||||||
import kotlinx.android.synthetic.main.recent_manga_item.*
|
import kotlinx.android.synthetic.main.recent_manga_item.*
|
||||||
@ -37,9 +38,21 @@ class RecentMangaHolder(
|
|||||||
|
|
||||||
fun bind(item: RecentMangaItem) {
|
fun bind(item: RecentMangaItem) {
|
||||||
download_button.visibleIf(item.mch.manga.source != LocalSource.ID)
|
download_button.visibleIf(item.mch.manga.source != LocalSource.ID)
|
||||||
subtitle.text = item.mch.manga.title
|
title.apply {
|
||||||
val isSearch = adapter.delegate.isSearching()
|
text = item.chapter.name
|
||||||
title.text = item.chapter.name
|
setTextColor(when {
|
||||||
|
item.chapter.bookmark -> context.getResourceColor(R.attr.colorAccent)
|
||||||
|
item.chapter.read -> context.getResourceColor(android.R.attr.textColorHint)
|
||||||
|
else -> context.getResourceColor(android.R.attr.textColorPrimary)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
subtitle.apply {
|
||||||
|
text = item.mch.manga.title
|
||||||
|
setTextColor(when {
|
||||||
|
item.chapter.read -> context.getResourceColor(android.R.attr.textColorHint)
|
||||||
|
else -> context.getResourceColor(android.R.attr.textColorPrimary)
|
||||||
|
})
|
||||||
|
}
|
||||||
val notValidNum = item.mch.chapter.chapter_number <= 0
|
val notValidNum = item.mch.chapter.chapter_number <= 0
|
||||||
body.text = when {
|
body.text = when {
|
||||||
item.mch.chapter.id == null -> body.context.getString(
|
item.mch.chapter.id == null -> body.context.getString(
|
||||||
@ -77,13 +90,18 @@ class RecentMangaHolder(
|
|||||||
GlideApp.with(itemView.context).load(item.mch.manga).diskCacheStrategy(DiskCacheStrategy
|
GlideApp.with(itemView.context).load(item.mch.manga).diskCacheStrategy(DiskCacheStrategy
|
||||||
.AUTOMATIC)
|
.AUTOMATIC)
|
||||||
.signature(ObjectKey(MangaImpl.getLastCoverFetch(item.mch.manga.id!!).toString())).into(cover_thumbnail)
|
.signature(ObjectKey(MangaImpl.getLastCoverFetch(item.mch.manga.id!!).toString())).into(cover_thumbnail)
|
||||||
// adapter.delegate.setCover(item.mch.manga, cover_thumbnail)
|
|
||||||
notifyStatus(
|
notifyStatus(
|
||||||
if (adapter.isSelected(adapterPosition)) Download.CHECKED else item.status,
|
if (adapter.isSelected(adapterPosition)) Download.CHECKED else item.status,
|
||||||
item.progress
|
item.progress
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onLongClick(view: View?): Boolean {
|
||||||
|
super.onLongClick(view)
|
||||||
|
val item = adapter.getItem(adapterPosition) as? RecentMangaItem ?: return false
|
||||||
|
return item.mch.history.id != null
|
||||||
|
}
|
||||||
|
|
||||||
fun notifyStatus(status: Int, progress: Int) =
|
fun notifyStatus(status: Int, progress: Int) =
|
||||||
download_button.setDownloadStatus(status, progress)
|
download_button.setDownloadStatus(status, progress)
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.recents
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
|
import eu.davidea.flexibleadapter.items.AbstractHeaderItem
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||||
@ -13,10 +14,9 @@ import eu.kanade.tachiyomi.ui.manga.chapter.BaseChapterItem
|
|||||||
class RecentMangaItem(
|
class RecentMangaItem(
|
||||||
val mch: MangaChapterHistory = MangaChapterHistory.createBlank(),
|
val mch: MangaChapterHistory = MangaChapterHistory.createBlank(),
|
||||||
chapter: Chapter = ChapterImpl(),
|
chapter: Chapter = ChapterImpl(),
|
||||||
header:
|
header: AbstractHeaderItem<*>?
|
||||||
RecentMangaHeaderItem?
|
|
||||||
) :
|
) :
|
||||||
BaseChapterItem<RecentMangaHolder, RecentMangaHeaderItem>(chapter, header) {
|
BaseChapterItem<RecentMangaHolder, AbstractHeaderItem<*>>(chapter, header) {
|
||||||
|
|
||||||
override fun getLayoutRes(): Int {
|
override fun getLayoutRes(): Int {
|
||||||
return if (mch.manga.id == null) R.layout.recents_footer_item
|
return if (mch.manga.id == null) R.layout.recents_footer_item
|
||||||
@ -37,14 +37,15 @@ class RecentMangaItem(
|
|||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (other is RecentMangaItem) {
|
if (other is RecentMangaItem) {
|
||||||
return if (mch.manga.id == null) header?.recentsType == other.header?.recentsType
|
return if (mch.manga.id == null) (header as? RecentMangaHeaderItem)?.recentsType ==
|
||||||
|
(other.header as? RecentMangaHeaderItem)?.recentsType
|
||||||
else chapter.id == other.chapter.id
|
else chapter.id == other.chapter.id
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
return if (mch.manga.id == null) -(header?.recentsType ?: 0).hashCode()
|
return if (mch.manga.id == null) -((header as? RecentMangaHeaderItem)?.recentsType ?: 0).hashCode()
|
||||||
else (chapter.id ?: 0L).hashCode()
|
else (chapter.id ?: 0L).hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ class RecentMangaItem(
|
|||||||
position: Int,
|
position: Int,
|
||||||
payloads: MutableList<Any?>?
|
payloads: MutableList<Any?>?
|
||||||
) {
|
) {
|
||||||
if (mch.manga.id == null) holder.bind(header?.recentsType ?: 0)
|
if (mch.manga.id == null) holder.bind((header as? RecentMangaHeaderItem)?.recentsType ?: 0)
|
||||||
else holder.bind(this)
|
else holder.bind(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import android.view.MenuInflater
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
@ -20,6 +21,8 @@ import com.google.android.material.snackbar.BaseTransientBottomBar
|
|||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.History
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadService
|
import eu.kanade.tachiyomi.data.download.DownloadService
|
||||||
import eu.kanade.tachiyomi.data.download.model.Download
|
import eu.kanade.tachiyomi.data.download.model.Download
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
|
||||||
@ -32,7 +35,9 @@ import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
|
|||||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||||
import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersController
|
import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersController
|
||||||
import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController
|
import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController
|
||||||
|
import eu.kanade.tachiyomi.ui.recently_read.RemoveHistoryDialog
|
||||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||||
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController
|
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController
|
||||||
import eu.kanade.tachiyomi.util.view.scrollViewWith
|
import eu.kanade.tachiyomi.util.view.scrollViewWith
|
||||||
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
|
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
|
||||||
@ -54,9 +59,11 @@ import kotlin.math.max
|
|||||||
class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
||||||
RecentMangaAdapter.RecentsInterface,
|
RecentMangaAdapter.RecentsInterface,
|
||||||
FlexibleAdapter.OnItemClickListener,
|
FlexibleAdapter.OnItemClickListener,
|
||||||
|
FlexibleAdapter.OnItemLongClickListener,
|
||||||
FlexibleAdapter.OnItemMoveListener,
|
FlexibleAdapter.OnItemMoveListener,
|
||||||
RootSearchInterface,
|
RootSearchInterface,
|
||||||
BottomSheetController {
|
BottomSheetController,
|
||||||
|
RemoveHistoryDialog.Listener {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
@ -112,7 +119,10 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
}
|
}
|
||||||
|
|
||||||
presenter.onCreate()
|
presenter.onCreate()
|
||||||
if (presenter.recentItems.isNotEmpty()) adapter.updateDataSet(presenter.recentItems)
|
if (presenter.recentItems.isNotEmpty()) {
|
||||||
|
adapter.updateDataSet(presenter.recentItems)
|
||||||
|
adapter.addScrollableHeader(presenter.generalHeader)
|
||||||
|
}
|
||||||
|
|
||||||
dl_bottom_sheet.onCreate(this)
|
dl_bottom_sheet.onCreate(this)
|
||||||
|
|
||||||
@ -173,6 +183,7 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
fun reEnableSwipe() {
|
fun reEnableSwipe() {
|
||||||
swipe_refresh.isRefreshing = false
|
swipe_refresh.isRefreshing = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemMove(fromPosition: Int, toPosition: Int) { }
|
override fun onItemMove(fromPosition: Int, toPosition: Int) { }
|
||||||
|
|
||||||
override fun shouldMoveItem(fromPosition: Int, toPosition: Int) = true
|
override fun shouldMoveItem(fromPosition: Int, toPosition: Int) = true
|
||||||
@ -217,6 +228,9 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
fun showLists(recents: List<RecentMangaItem>) {
|
fun showLists(recents: List<RecentMangaItem>) {
|
||||||
swipe_refresh.isRefreshing = LibraryUpdateService.isRunning()
|
swipe_refresh.isRefreshing = LibraryUpdateService.isRunning()
|
||||||
adapter.updateDataSet(recents)
|
adapter.updateDataSet(recents)
|
||||||
|
adapter.removeAllScrollableHeaders()
|
||||||
|
if (presenter.viewType > 0)
|
||||||
|
adapter.addScrollableHeader(presenter.generalHeader)
|
||||||
if (lastChapterId != null) {
|
if (lastChapterId != null) {
|
||||||
refreshItem(lastChapterId ?: 0L)
|
refreshItem(lastChapterId ?: 0L)
|
||||||
lastChapterId = null
|
lastChapterId = null
|
||||||
@ -286,6 +300,25 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onItemLongClick(position: Int) {
|
||||||
|
val item = adapter.getItem(position) as? RecentMangaItem ?: return
|
||||||
|
val manga = item.mch.manga
|
||||||
|
val history = item.mch.history
|
||||||
|
val chapter = item.mch.chapter
|
||||||
|
if (history.id != null)
|
||||||
|
RemoveHistoryDialog(this, manga, history, chapter).showDialog(router)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeHistory(manga: Manga, history: History, all: Boolean) {
|
||||||
|
if (all) {
|
||||||
|
// Reset last read of chapter to 0L
|
||||||
|
presenter.removeAllFromHistory(manga.id!!)
|
||||||
|
} else {
|
||||||
|
// Remove all chapters belonging to manga from library
|
||||||
|
presenter.removeFromHistory(history)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun markAsRead(position: Int) {
|
override fun markAsRead(position: Int) {
|
||||||
val item = adapter.getItem(position) as? RecentMangaItem ?: return
|
val item = adapter.getItem(position) as? RecentMangaItem ?: return
|
||||||
val chapter = item.chapter
|
val chapter = item.chapter
|
||||||
@ -323,10 +356,13 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
} else {
|
} else {
|
||||||
inflater.inflate(R.menu.recents, menu)
|
inflater.inflate(R.menu.recents, menu)
|
||||||
|
|
||||||
val viewItem = menu.findItem(R.id.action_view)
|
when (presenter.viewType) {
|
||||||
val endless = presenter.groupRecents
|
0 -> menu.findItem(R.id.action_group_all)
|
||||||
viewItem.setTitle(if (endless) R.string.group_recents else R.string.ungroup_recents)
|
1 -> menu.findItem(R.id.action_ungroup_all)
|
||||||
viewItem.setIcon(if (endless) R.drawable.ic_view_stream_24dp else R.drawable.ic_view_headline_24dp)
|
2 -> menu.findItem(R.id.action_only_history)
|
||||||
|
3 -> menu.findItem(R.id.action_only_updates)
|
||||||
|
else -> null
|
||||||
|
}?.isChecked = true
|
||||||
|
|
||||||
val searchItem = menu.findItem(R.id.action_search)
|
val searchItem = menu.findItem(R.id.action_search)
|
||||||
val searchView = searchItem.actionView as SearchView
|
val searchView = searchItem.actionView as SearchView
|
||||||
@ -385,8 +421,16 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
if (showingDownloads)
|
if (showingDownloads)
|
||||||
return dl_bottom_sheet.onOptionsItemSelected(item)
|
return dl_bottom_sheet.onOptionsItemSelected(item)
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.action_view -> {
|
R.id.action_group_all, R.id.action_ungroup_all, R.id.action_only_history,
|
||||||
presenter.toggleGroupRecents()
|
R.id.action_only_updates -> {
|
||||||
|
presenter.toggleGroupRecents(when (item.itemId) {
|
||||||
|
R.id.action_ungroup_all -> 1
|
||||||
|
R.id.action_only_history -> 2
|
||||||
|
R.id.action_only_updates -> 3
|
||||||
|
else -> 0
|
||||||
|
})
|
||||||
|
if (item.itemId == R.id.action_only_history)
|
||||||
|
activity?.toast(R.string.press_and_hold_to_reset_history, Toast.LENGTH_LONG)
|
||||||
activity?.invalidateOptionsMenu()
|
activity?.invalidateOptionsMenu()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package eu.kanade.tachiyomi.ui.recents
|
|||||||
|
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.History
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.HistoryImpl
|
||||||
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
||||||
@ -13,6 +15,7 @@ import eu.kanade.tachiyomi.data.library.LibraryUpdateService
|
|||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
|
import eu.kanade.tachiyomi.ui.recent_updates.DateItem
|
||||||
import eu.kanade.tachiyomi.util.system.executeOnIO
|
import eu.kanade.tachiyomi.util.system.executeOnIO
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -24,6 +27,7 @@ import uy.kohesive.injekt.Injekt
|
|||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
import java.util.TreeMap
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
@ -41,10 +45,10 @@ class RecentsPresenter(
|
|||||||
var query = ""
|
var query = ""
|
||||||
private val newAdditionsHeader = RecentMangaHeaderItem(RecentMangaHeaderItem.NEWLY_ADDED)
|
private val newAdditionsHeader = RecentMangaHeaderItem(RecentMangaHeaderItem.NEWLY_ADDED)
|
||||||
private val newChaptersHeader = RecentMangaHeaderItem(RecentMangaHeaderItem.NEW_CHAPTERS)
|
private val newChaptersHeader = RecentMangaHeaderItem(RecentMangaHeaderItem.NEW_CHAPTERS)
|
||||||
private val endlessHeader = RecentMangaHeaderItem(-1)
|
val generalHeader = RecentMangaHeaderItem(-1)
|
||||||
private val continueReadingHeader = RecentMangaHeaderItem(RecentMangaHeaderItem
|
private val continueReadingHeader = RecentMangaHeaderItem(RecentMangaHeaderItem
|
||||||
.CONTINUE_READING)
|
.CONTINUE_READING)
|
||||||
var groupRecents = preferences.groupRecents().getOrDefault()
|
var viewType: Int = preferences.recentsViewType().getOrDefault()
|
||||||
|
|
||||||
fun onCreate() {
|
fun onCreate() {
|
||||||
downloadManager.addListener(this)
|
downloadManager.addListener(this)
|
||||||
@ -60,12 +64,13 @@ class RecentsPresenter(
|
|||||||
fun getRecents() {
|
fun getRecents() {
|
||||||
val oldQuery = query
|
val oldQuery = query
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val isEndless = groupRecents && query.isEmpty()
|
val isUngrouped = viewType > 0 && query.isEmpty()
|
||||||
|
// groupRecents && query.isEmpty()
|
||||||
val cal = Calendar.getInstance().apply {
|
val cal = Calendar.getInstance().apply {
|
||||||
time = Date()
|
time = Date()
|
||||||
when {
|
when {
|
||||||
query.isNotEmpty() -> add(Calendar.YEAR, -50)
|
query.isNotEmpty() -> add(Calendar.YEAR, -50)
|
||||||
isEndless -> add(Calendar.MONTH, -1)
|
isUngrouped -> add(Calendar.MONTH, -1)
|
||||||
else -> add(Calendar.MONTH, -1)
|
else -> add(Calendar.MONTH, -1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,7 +79,7 @@ class RecentsPresenter(
|
|||||||
time = Date()
|
time = Date()
|
||||||
when {
|
when {
|
||||||
query.isNotEmpty() -> add(Calendar.YEAR, -50)
|
query.isNotEmpty() -> add(Calendar.YEAR, -50)
|
||||||
isEndless -> add(Calendar.MONTH, -1)
|
isUngrouped -> add(Calendar.MONTH, -1)
|
||||||
else -> add(Calendar.WEEK_OF_YEAR, -1)
|
else -> add(Calendar.WEEK_OF_YEAR, -1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,19 +88,30 @@ class RecentsPresenter(
|
|||||||
time = Date()
|
time = Date()
|
||||||
when {
|
when {
|
||||||
query.isNotEmpty() -> add(Calendar.YEAR, -50)
|
query.isNotEmpty() -> add(Calendar.YEAR, -50)
|
||||||
isEndless -> add(Calendar.MONTH, -1)
|
isUngrouped -> add(Calendar.MONTH, -1)
|
||||||
else -> add(Calendar.DAY_OF_YEAR, -1)
|
else -> add(Calendar.DAY_OF_YEAR, -1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val cReading =
|
val cReading = if (viewType != 3)
|
||||||
if (query.isEmpty()) db.getRecentsWithUnread(cal.time, query, isEndless).executeOnIO()
|
if (query.isEmpty() && viewType != 2)
|
||||||
else db.getRecentMangaLimit(cal.time, 8, query).executeOnIO()
|
db.getRecentsWithUnread(cal.time, query, isUngrouped).executeOnIO()
|
||||||
val rUpdates = db.getUpdatedManga(calWeek.time, query, isEndless).executeOnIO()
|
else db.getRecentMangaLimit(
|
||||||
|
cal.time,
|
||||||
|
if (viewType == 2) 200 else 8,
|
||||||
|
query).executeOnIO() else emptyList()
|
||||||
|
val rUpdates = when {
|
||||||
|
viewType == 3 -> db.getRecentChapters(calWeek.time).executeOnIO().map {
|
||||||
|
MangaChapterHistory(it.manga, it.chapter, HistoryImpl())
|
||||||
|
}
|
||||||
|
viewType != 2 -> db.getUpdatedManga(calWeek.time, query, isUngrouped).executeOnIO()
|
||||||
|
else -> emptyList()
|
||||||
|
}
|
||||||
rUpdates.forEach {
|
rUpdates.forEach {
|
||||||
it.history.last_read = it.chapter.date_fetch
|
it.history.last_read = it.chapter.date_fetch
|
||||||
}
|
}
|
||||||
val nAdditions = db.getRecentlyAdded(calDay.time, query, isEndless).executeOnIO()
|
val nAdditions = if (viewType < 2)
|
||||||
|
db.getRecentlyAdded(calDay.time, query, isUngrouped).executeOnIO() else emptyList()
|
||||||
nAdditions.forEach {
|
nAdditions.forEach {
|
||||||
it.history.last_read = it.manga.date_added
|
it.history.last_read = it.manga.date_added
|
||||||
}
|
}
|
||||||
@ -103,19 +119,21 @@ class RecentsPresenter(
|
|||||||
val mangaList = (cReading + rUpdates + nAdditions).sortedByDescending {
|
val mangaList = (cReading + rUpdates + nAdditions).sortedByDescending {
|
||||||
it.history.last_read
|
it.history.last_read
|
||||||
}.distinctBy {
|
}.distinctBy {
|
||||||
if (query.isEmpty()) it.manga.id else it.chapter.id
|
if (query.isEmpty() && viewType != 3) it.manga.id else it.chapter.id
|
||||||
}
|
}
|
||||||
val pairs = mangaList.mapNotNull {
|
val pairs = mangaList.mapNotNull {
|
||||||
val chapter = if (it.chapter.read || it.chapter.id == null) getNextChapter(it.manga)
|
val chapter = when {
|
||||||
else if (it.history.id == null) getFirstUpdatedChapter(it.manga, it.chapter)
|
viewType == 3 -> it.chapter
|
||||||
else it.chapter
|
it.chapter.read || it.chapter.id == null -> getNextChapter(it.manga)
|
||||||
if (chapter == null) if (query.isNotEmpty() && it.chapter.id != null) Pair(
|
it.history.id == null -> getFirstUpdatedChapter(it.manga, it.chapter)
|
||||||
it, it.chapter
|
else -> it.chapter
|
||||||
)
|
}
|
||||||
|
if (chapter == null) if ((query.isNotEmpty() || viewType > 1) &&
|
||||||
|
it.chapter.id != null) Pair(it, it.chapter)
|
||||||
else null
|
else null
|
||||||
else Pair(it, chapter)
|
else Pair(it, chapter)
|
||||||
}
|
}
|
||||||
if (query.isEmpty() && !groupRecents) {
|
if (query.isEmpty() && !isUngrouped) {
|
||||||
val nChaptersItems =
|
val nChaptersItems =
|
||||||
pairs.filter { it.first.history.id == null && it.first.chapter.id != null }
|
pairs.filter { it.first.history.id == null && it.first.chapter.id != null }
|
||||||
.sortedWith(Comparator<Pair<MangaChapterHistory, Chapter>> { f1, f2 ->
|
.sortedWith(Comparator<Pair<MangaChapterHistory, Chapter>> { f1, f2 ->
|
||||||
@ -148,9 +166,20 @@ class RecentsPresenter(
|
|||||||
it.firstOrNull()?.mch?.history?.last_read ?: 0L
|
it.firstOrNull()?.mch?.history?.last_read ?: 0L
|
||||||
}.flatten()
|
}.flatten()
|
||||||
} else {
|
} else {
|
||||||
val header = if (isEndless) endlessHeader else null
|
recentItems =
|
||||||
recentItems = pairs.map { RecentMangaItem(it.first, it.second, header) }
|
if (viewType == 3) {
|
||||||
if (isEndless && recentItems.isEmpty()) {
|
val map = TreeMap<Date, MutableList<Pair<MangaChapterHistory, Chapter>>> {
|
||||||
|
d1, d2 -> d2
|
||||||
|
.compareTo(d1) }
|
||||||
|
val byDay =
|
||||||
|
pairs.groupByTo(map, { getMapKey(it.first.history.last_read) })
|
||||||
|
byDay.flatMap {
|
||||||
|
val dateItem = DateItem(it.key, true)
|
||||||
|
it.value.map { item ->
|
||||||
|
RecentMangaItem(item.first, item.second, dateItem) }
|
||||||
|
}
|
||||||
|
} else pairs.map { RecentMangaItem(it.first, it.second, null) }
|
||||||
|
if (isUngrouped && recentItems.isEmpty()) {
|
||||||
recentItems = listOf(
|
recentItems = listOf(
|
||||||
RecentMangaItem(header = newChaptersHeader),
|
RecentMangaItem(header = newChaptersHeader),
|
||||||
RecentMangaItem(header = continueReadingHeader))
|
RecentMangaItem(header = continueReadingHeader))
|
||||||
@ -183,9 +212,9 @@ class RecentsPresenter(
|
|||||||
scope.cancel()
|
scope.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleGroupRecents() {
|
fun toggleGroupRecents(pref: Int) {
|
||||||
preferences.groupRecents().set(!groupRecents)
|
preferences.recentsViewType().set(pref)
|
||||||
groupRecents = !groupRecents
|
viewType = pref
|
||||||
getRecents()
|
getRecents()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,6 +265,22 @@ class RecentsPresenter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get date as time key
|
||||||
|
*
|
||||||
|
* @param date desired date
|
||||||
|
* @return date as time key
|
||||||
|
*/
|
||||||
|
private fun getMapKey(date: Long): Date {
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
cal.time = Date(date)
|
||||||
|
cal[Calendar.HOUR_OF_DAY] = 0
|
||||||
|
cal[Calendar.MINUTE] = 0
|
||||||
|
cal[Calendar.SECOND] = 0
|
||||||
|
cal[Calendar.MILLISECOND] = 0
|
||||||
|
return cal.time
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Downloads the given list of chapters with the manager.
|
* Downloads the given list of chapters with the manager.
|
||||||
* @param chapter the chapter to download.
|
* @param chapter the chapter to download.
|
||||||
@ -272,7 +317,29 @@ class RecentsPresenter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
// History
|
||||||
|
/**
|
||||||
|
* Reset last read of chapter to 0L
|
||||||
|
* @param history history belonging to chapter
|
||||||
|
*/
|
||||||
|
fun removeFromHistory(history: History) {
|
||||||
|
history.last_read = 0L
|
||||||
|
db.updateHistoryLastRead(history).executeAsBlocking()
|
||||||
|
getRecents()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all chapters belonging to manga from history.
|
||||||
|
* @param mangaId id of manga
|
||||||
|
*/
|
||||||
|
fun removeAllFromHistory(mangaId: Long) {
|
||||||
|
val history = db.getHistoryByMangaId(mangaId).executeAsBlocking()
|
||||||
|
history.forEach { it.last_read = 0L }
|
||||||
|
db.updateHistoryLastRead(history).executeAsBlocking()
|
||||||
|
getRecents()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
var lastRecents: List<RecentMangaItem>? = null
|
var lastRecents: List<RecentMangaItem>? = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
android:icon="@drawable/recent_read_selector_24dp"
|
android:icon="@drawable/recent_read_selector_24dp"
|
||||||
android:title="@string/recents" />
|
android:title="@string/recents" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_catalogues"
|
android:id="@+id/nav_browse"
|
||||||
android:icon="@drawable/browse_selector_24dp"
|
android:icon="@drawable/browse_selector_24dp"
|
||||||
android:title="@string/browse" />
|
android:title="@string/browse" />
|
||||||
</group>
|
</group>
|
||||||
|
@ -6,15 +6,31 @@
|
|||||||
android:id="@+id/action_search"
|
android:id="@+id/action_search"
|
||||||
android:icon="@drawable/ic_search_white_24dp"
|
android:icon="@drawable/ic_search_white_24dp"
|
||||||
android:title="@string/search"
|
android:title="@string/search"
|
||||||
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
|
||||||
android:visible="false"
|
android:visible="false"
|
||||||
|
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
||||||
app:showAsAction="ifRoom|collapseActionView" />
|
app:showAsAction="ifRoom|collapseActionView" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_view"
|
android:id="@+id/action_filter"
|
||||||
android:icon="@drawable/ic_view_stream_24dp"
|
android:icon="@drawable/ic_filter_list_white_24dp"
|
||||||
android:title="@string/group_recents"
|
android:title="@string/group_all"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom">
|
||||||
|
<menu>
|
||||||
|
<group android:checkableBehavior="single">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_group_all"
|
||||||
|
android:title="@string/group_all" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_ungroup_all"
|
||||||
|
android:title="@string/ungroup_all" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_only_history"
|
||||||
|
android:title="@string/only_history" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_only_updates"
|
||||||
|
android:title="@string/only_updates" />
|
||||||
|
</group>
|
||||||
|
</menu>
|
||||||
|
</item>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_settings"
|
android:id="@+id/action_settings"
|
||||||
android:icon="@drawable/ic_settings_white_24dp"
|
android:icon="@drawable/ic_settings_white_24dp"
|
||||||
|
@ -177,7 +177,10 @@
|
|||||||
<string name="history">History</string>
|
<string name="history">History</string>
|
||||||
<string name="recently_read">Recently read</string>
|
<string name="recently_read">Recently read</string>
|
||||||
<string name="recent_updates">Recent updates</string>
|
<string name="recent_updates">Recent updates</string>
|
||||||
<string name="this_will_remove_the_read_date_question">This will remove the read date of this chapter. Are you sure?</string>
|
<string name="this_will_remove_the_read_date_for_x_question">This will remove the read date of
|
||||||
|
\"%1$s\". Are you sure?</string>
|
||||||
|
<string name="this_will_remove_the_read_date_question">This will remove the read date of this
|
||||||
|
chapter. Are you sure?</string>
|
||||||
<string name="reset_all_chapters_for_this_">Reset all chapters for this %1$s</string>
|
<string name="reset_all_chapters_for_this_">Reset all chapters for this %1$s</string>
|
||||||
<string name="source_dash_chapter_">%1$s - Ch.%2$s</string>
|
<string name="source_dash_chapter_">%1$s - Ch.%2$s</string>
|
||||||
<string name="last_read_">Last read %1$s</string>
|
<string name="last_read_">Last read %1$s</string>
|
||||||
@ -190,8 +193,12 @@
|
|||||||
<string name="search_recents">Search recents…</string>
|
<string name="search_recents">Search recents…</string>
|
||||||
<string name="no_recent_chapters">No recent chapters</string>
|
<string name="no_recent_chapters">No recent chapters</string>
|
||||||
<string name="no_recently_read_manga">No recently read manga</string>
|
<string name="no_recently_read_manga">No recently read manga</string>
|
||||||
<string name="group_recents">Group recents</string>
|
<string name="group_all">Group all</string>
|
||||||
<string name="ungroup_recents">Ungroup recents</string>
|
<string name="ungroup_all">Ungroup all</string>
|
||||||
|
<string name="only_history">Only history</string>
|
||||||
|
<string name="only_updates">Only updates</string>
|
||||||
|
<string name="reset_chapter_question">Reset chapter?</string>
|
||||||
|
<string name="press_and_hold_to_reset_history">Press and hold to reset chapter history</string>
|
||||||
|
|
||||||
<!-- Browse -->
|
<!-- Browse -->
|
||||||
<string name="search_filters">Search filters</string>
|
<string name="search_filters">Search filters</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user