mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
Can now expand history grouped chapters
just like the update sections, the preferences for history its either always collapsed by default, or its separated out
This commit is contained in:
parent
f1c5f65090
commit
addabd70bb
12 changed files with 159 additions and 154 deletions
|
@ -21,6 +21,9 @@ interface Chapter : SChapter, Serializable {
|
||||||
|
|
||||||
var source_order: Int
|
var source_order: Int
|
||||||
|
|
||||||
|
var dateRead: Long?
|
||||||
|
var history: History?
|
||||||
|
|
||||||
val isRecognizedNumber: Boolean
|
val isRecognizedNumber: Boolean
|
||||||
get() = chapter_number >= 0f
|
get() = chapter_number >= 0f
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,13 @@ class ChapterImpl : Chapter {
|
||||||
|
|
||||||
override var date_upload: Long = 0
|
override var date_upload: Long = 0
|
||||||
|
|
||||||
|
override var dateRead: Long? = null
|
||||||
|
override var history: History? = null
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
dateRead = history?.last_read
|
||||||
|
}
|
||||||
|
|
||||||
override var chapter_number: Float = 0f
|
override var chapter_number: Float = 0f
|
||||||
|
|
||||||
override var source_order: Int = 0
|
override var source_order: Int = 0
|
||||||
|
|
|
@ -35,23 +35,6 @@ interface HistoryQueries : DbProvider {
|
||||||
// .withGetResolver(MangaChapterHistoryGetResolver.INSTANCE)
|
// .withGetResolver(MangaChapterHistoryGetResolver.INSTANCE)
|
||||||
// .prepare()
|
// .prepare()
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns history of recent manga containing last read chapter in 25s
|
|
||||||
* @param date recent date range
|
|
||||||
* @offset offset the db by
|
|
||||||
*/
|
|
||||||
fun getRecentMangaLimit(search: String = "", offset: Int, isResuming: Boolean) = db.get()
|
|
||||||
.listOfObjects(MangaChapterHistory::class.java)
|
|
||||||
.withQuery(
|
|
||||||
RawQuery.builder()
|
|
||||||
.query(getRecentMangasLimitQuery(search.sqLite, offset, isResuming))
|
|
||||||
// .args(date.time, startDate.time)
|
|
||||||
.observesTables(HistoryTable.TABLE)
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.withGetResolver(MangaChapterHistoryGetResolver.INSTANCE)
|
|
||||||
.prepare()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns history of recent manga containing last read chapter in 25s
|
* Returns history of recent manga containing last read chapter in 25s
|
||||||
* @param date recent date range
|
* @param date recent date range
|
||||||
|
@ -62,7 +45,6 @@ interface HistoryQueries : DbProvider {
|
||||||
.withQuery(
|
.withQuery(
|
||||||
RawQuery.builder()
|
RawQuery.builder()
|
||||||
.query(getRecentHistoryUngrouped(search.sqLite, offset, isResuming))
|
.query(getRecentHistoryUngrouped(search.sqLite, offset, isResuming))
|
||||||
// .args(date.time, startDate.time)
|
|
||||||
.observesTables(HistoryTable.TABLE)
|
.observesTables(HistoryTable.TABLE)
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -61,18 +61,6 @@ fun getRecentsQuery(search: String, offset: Int, isResuming: Boolean) =
|
||||||
${limitAndOffset(true, isResuming, offset)}
|
${limitAndOffset(true, isResuming, offset)}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
/**
|
|
||||||
* Query to get the recently added manga
|
|
||||||
*/
|
|
||||||
fun getRecentAdditionsQuery(search: String, endless: Boolean, offset: Int, isResuming: Boolean) =
|
|
||||||
"""
|
|
||||||
SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, * FROM ${Manga.TABLE}
|
|
||||||
WHERE ${Manga.COL_FAVORITE} = 1
|
|
||||||
AND lower(${Manga.COL_TITLE}) LIKE '%$search%'
|
|
||||||
ORDER BY ${Manga.COL_DATE_ADDED} DESC
|
|
||||||
${limitAndOffset(endless, isResuming, offset)}
|
|
||||||
"""
|
|
||||||
|
|
||||||
fun limitAndOffset(endless: Boolean, isResuming: Boolean, offset: Int): String {
|
fun limitAndOffset(endless: Boolean, isResuming: Boolean, offset: Int): String {
|
||||||
return when {
|
return when {
|
||||||
isResuming && endless && offset > 0 -> "LIMIT $offset"
|
isResuming && endless && offset > 0 -> "LIMIT $offset"
|
||||||
|
@ -81,37 +69,6 @@ fun limitAndOffset(endless: Boolean, isResuming: Boolean, offset: Int): String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Query to get the recently read chapters of manga from the library up to a date.
|
|
||||||
* The max_last_read table contains the most recent chapters grouped by manga
|
|
||||||
* The select statement returns all information of chapters that have the same id as the chapter in max_last_read
|
|
||||||
* and are read after the given time period
|
|
||||||
*/
|
|
||||||
fun getRecentMangasLimitQuery(
|
|
||||||
search: String = "",
|
|
||||||
offset: Int = 0,
|
|
||||||
isResuming: Boolean,
|
|
||||||
) =
|
|
||||||
"""
|
|
||||||
SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, ${Manga.TABLE}.*, ${Chapter.TABLE}.*, ${History.TABLE}.*
|
|
||||||
FROM ${Manga.TABLE}
|
|
||||||
JOIN ${Chapter.TABLE}
|
|
||||||
ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}
|
|
||||||
JOIN ${History.TABLE}
|
|
||||||
ON ${Chapter.TABLE}.${Chapter.COL_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
|
|
||||||
JOIN (
|
|
||||||
SELECT ${Chapter.TABLE}.${Chapter.COL_MANGA_ID},${Chapter.TABLE}.${Chapter.COL_ID} as ${History.COL_CHAPTER_ID}, MAX(${History.TABLE}.${History.COL_LAST_READ}) as ${History.COL_LAST_READ}
|
|
||||||
FROM ${Chapter.TABLE} JOIN ${History.TABLE}
|
|
||||||
ON ${Chapter.TABLE}.${Chapter.COL_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
|
|
||||||
GROUP BY ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}) AS max_last_read
|
|
||||||
ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = max_last_read.${Chapter.COL_MANGA_ID}
|
|
||||||
AND max_last_read.${History.COL_CHAPTER_ID} = ${History.TABLE}.${History.COL_CHAPTER_ID}
|
|
||||||
AND max_last_read.${History.COL_LAST_READ} > 0
|
|
||||||
AND lower(${Manga.TABLE}.${Manga.COL_TITLE}) LIKE '%$search%'
|
|
||||||
ORDER BY max_last_read.${History.COL_LAST_READ} DESC
|
|
||||||
${limitAndOffset(true, isResuming, offset)}
|
|
||||||
"""
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query to get the recently read chapters of manga from the library up to a date.
|
* Query to get the recently read chapters of manga from the library up to a date.
|
||||||
* The max_last_read table contains the most recent chapters grouped by manga
|
* The max_last_read table contains the most recent chapters grouped by manga
|
||||||
|
|
|
@ -88,6 +88,7 @@ class RecentMangaAdapter(val delegate: RecentsInterface) :
|
||||||
fun isSearching(): Boolean
|
fun isSearching(): Boolean
|
||||||
fun scope(): CoroutineScope
|
fun scope(): CoroutineScope
|
||||||
fun getViewType(): Int
|
fun getViewType(): Int
|
||||||
|
fun onItemLongClick(position: Int, chapter: Chapter): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemSwiped(position: Int, direction: Int) {
|
override fun onItemSwiped(position: Int, direction: Int) {
|
||||||
|
|
|
@ -39,9 +39,11 @@ class RecentMangaHolder(
|
||||||
|
|
||||||
private val binding = RecentMangaItemBinding.bind(view)
|
private val binding = RecentMangaItemBinding.bind(view)
|
||||||
var chapterId: Long? = null
|
var chapterId: Long? = null
|
||||||
|
private val isUpdates
|
||||||
|
get() = adapter.viewType == RecentsPresenter.VIEW_TYPE_ONLY_UPDATES
|
||||||
|
|
||||||
private val isSmallUpdates
|
private val isSmallUpdates
|
||||||
get() = adapter.viewType == RecentsPresenter.VIEW_TYPE_ONLY_UPDATES &&
|
get() = isUpdates && !adapter.showUpdatedTime
|
||||||
!adapter.showUpdatedTime
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
binding.cardLayout.setOnClickListener { adapter.delegate.onCoverClick(flexibleAdapterPosition) }
|
binding.cardLayout.setOnClickListener { adapter.delegate.onCoverClick(flexibleAdapterPosition) }
|
||||||
|
@ -62,7 +64,7 @@ class RecentMangaHolder(
|
||||||
RecentSubChapterItemBinding.bind(view).updateDivider()
|
RecentSubChapterItemBinding.bind(view).updateDivider()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (binding.moreChaptersLayout.children.any { view ->
|
if (isUpdates && binding.moreChaptersLayout.children.any { view ->
|
||||||
!RecentSubChapterItemBinding.bind(view).subtitle.text.isNullOrBlank()
|
!RecentSubChapterItemBinding.bind(view).subtitle.text.isNullOrBlank()
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
@ -230,7 +232,7 @@ class RecentMangaHolder(
|
||||||
RecentSubChapterItemBinding.bind(binding.moreChaptersLayout.getChildAt(index))
|
RecentSubChapterItemBinding.bind(binding.moreChaptersLayout.getChildAt(index))
|
||||||
.configureView(chapter, item)
|
.configureView(chapter, item)
|
||||||
}
|
}
|
||||||
if (binding.moreChaptersLayout.children.any { view ->
|
if (isUpdates && binding.moreChaptersLayout.children.any { view ->
|
||||||
!RecentSubChapterItemBinding.bind(view).subtitle.text.isNullOrBlank()
|
!RecentSubChapterItemBinding.bind(view).subtitle.text.isNullOrBlank()
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
@ -247,7 +249,7 @@ class RecentMangaHolder(
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
binding.configureView(chapter, item)
|
binding.configureView(chapter, item)
|
||||||
if (chapter.isRecognizedNumber &&
|
if (isUpdates && chapter.isRecognizedNumber &&
|
||||||
chapter.chapter_number == item.chapter.chapter_number &&
|
chapter.chapter_number == item.chapter.chapter_number &&
|
||||||
!chapter.scanlator.isNullOrBlank()
|
!chapter.scanlator.isNullOrBlank()
|
||||||
) {
|
) {
|
||||||
|
@ -309,13 +311,20 @@ class RecentMangaHolder(
|
||||||
val showDLs = adapter.showDownloads
|
val showDLs = adapter.showDownloads
|
||||||
title.text = chapter.preferredChapterName(context, item.mch.manga, adapter.preferences)
|
title.text = chapter.preferredChapterName(context, item.mch.manga, adapter.preferences)
|
||||||
title.setTextColor(ChapterUtil.readColor(context, chapter))
|
title.setTextColor(ChapterUtil.readColor(context, chapter))
|
||||||
|
chapter.dateRead?.let { dateRead ->
|
||||||
|
subtitle.text = context.timeSpanFromNow(R.string.read_, dateRead)
|
||||||
|
subtitle.isVisible = true
|
||||||
|
}
|
||||||
root.setOnClickListener {
|
root.setOnClickListener {
|
||||||
adapter.delegate.onSubChapterClicked(
|
adapter.delegate.onSubChapterClicked(
|
||||||
flexibleAdapterPosition,
|
bindingAdapterPosition,
|
||||||
chapter,
|
chapter,
|
||||||
it,
|
it,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
root.setOnLongClickListener {
|
||||||
|
adapter.delegate.onItemLongClick(bindingAdapterPosition, chapter)
|
||||||
|
}
|
||||||
listOf(root, downloadButton.root).forEach {
|
listOf(root, downloadButton.root).forEach {
|
||||||
it.setOnTouchListener { _, event ->
|
it.setOnTouchListener { _, event ->
|
||||||
if (event.action == MotionEvent.ACTION_DOWN) {
|
if (event.action == MotionEvent.ACTION_DOWN) {
|
||||||
|
|
|
@ -652,7 +652,7 @@ class RecentsController(bundle: Bundle? = null) :
|
||||||
|
|
||||||
override fun areExtraChaptersExpanded(position: Int): Boolean {
|
override fun areExtraChaptersExpanded(position: Int): Boolean {
|
||||||
val item = (adapter.getItem(position) as? RecentMangaItem) ?: return false
|
val item = (adapter.getItem(position) as? RecentMangaItem) ?: return false
|
||||||
val date = presenter.dateFormat.format(item.chapter.date_fetch)
|
val date = presenter.dateFormat.format(item.chapter.dateRead ?: item.chapter.date_fetch)
|
||||||
val invertDefault = !adapter.collapseGroupedUpdates
|
val invertDefault = !adapter.collapseGroupedUpdates
|
||||||
return presenter.expandedSectionsMap["${item.mch.manga} - $date"]?.xor(invertDefault)
|
return presenter.expandedSectionsMap["${item.mch.manga} - $date"]?.xor(invertDefault)
|
||||||
?: invertDefault
|
?: invertDefault
|
||||||
|
@ -660,7 +660,7 @@ class RecentsController(bundle: Bundle? = null) :
|
||||||
|
|
||||||
override fun updateExpandedExtraChapters(position: Int, expanded: Boolean) {
|
override fun updateExpandedExtraChapters(position: Int, expanded: Boolean) {
|
||||||
val item = (adapter.getItem(position) as? RecentMangaItem) ?: return
|
val item = (adapter.getItem(position) as? RecentMangaItem) ?: return
|
||||||
val date = presenter.dateFormat.format(item.chapter.date_fetch)
|
val date = presenter.dateFormat.format(item.chapter.dateRead ?: item.chapter.date_fetch)
|
||||||
val invertDefault = !adapter.collapseGroupedUpdates
|
val invertDefault = !adapter.collapseGroupedUpdates
|
||||||
presenter.expandedSectionsMap["${item.mch.manga} - $date"] = expanded.xor(invertDefault)
|
presenter.expandedSectionsMap["${item.mch.manga} - $date"] = expanded.xor(invertDefault)
|
||||||
}
|
}
|
||||||
|
@ -727,6 +727,16 @@ class RecentsController(bundle: Bundle? = null) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onItemLongClick(position: Int, chapter: Chapter): Boolean {
|
||||||
|
val history = chapter.history ?: return false
|
||||||
|
val item = adapter.getItem(position) as? RecentMangaItem ?: return false
|
||||||
|
val manga = item.mch.manga
|
||||||
|
if (history.id != null) {
|
||||||
|
RemoveHistoryDialog(this, manga, history, chapter).showDialog(router)
|
||||||
|
}
|
||||||
|
return history.id != null
|
||||||
|
}
|
||||||
|
|
||||||
override fun removeHistory(manga: Manga, history: History, all: Boolean) {
|
override fun removeHistory(manga: Manga, history: History, all: Boolean) {
|
||||||
if (all) {
|
if (all) {
|
||||||
// Reset last read of chapter to 0L
|
// Reset last read of chapter to 0L
|
||||||
|
|
|
@ -6,7 +6,6 @@ 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.HistoryImpl
|
import eu.kanade.tachiyomi.data.database.models.HistoryImpl
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.models.MangaChapter
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadService
|
import eu.kanade.tachiyomi.data.download.DownloadService
|
||||||
|
@ -19,6 +18,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BaseCoroutinePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BaseCoroutinePresenter
|
||||||
import eu.kanade.tachiyomi.util.chapter.ChapterFilter
|
import eu.kanade.tachiyomi.util.chapter.ChapterFilter
|
||||||
|
import eu.kanade.tachiyomi.util.chapter.ChapterFilter.Companion.filterChaptersByScanlators
|
||||||
import eu.kanade.tachiyomi.util.chapter.ChapterSort
|
import eu.kanade.tachiyomi.util.chapter.ChapterSort
|
||||||
import eu.kanade.tachiyomi.util.system.executeOnIO
|
import eu.kanade.tachiyomi.util.system.executeOnIO
|
||||||
import eu.kanade.tachiyomi.util.system.launchIO
|
import eu.kanade.tachiyomi.util.system.launchIO
|
||||||
|
@ -60,12 +60,9 @@ class RecentsPresenter(
|
||||||
}
|
}
|
||||||
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 continueReadingHeader = RecentMangaHeaderItem(
|
private val continueReadingHeader =
|
||||||
RecentMangaHeaderItem
|
RecentMangaHeaderItem(RecentMangaHeaderItem.CONTINUE_READING)
|
||||||
.CONTINUE_READING,
|
|
||||||
)
|
|
||||||
var finished = false
|
var finished = false
|
||||||
var heldItems: HashMap<Int, List<RecentMangaItem>> = hashMapOf()
|
|
||||||
private var shouldMoveToTop = false
|
private var shouldMoveToTop = false
|
||||||
var viewType: Int = preferences.recentsViewType().get()
|
var viewType: Int = preferences.recentsViewType().get()
|
||||||
private set
|
private set
|
||||||
|
@ -173,19 +170,40 @@ class RecentsPresenter(
|
||||||
).executeOnIO()
|
).executeOnIO()
|
||||||
}
|
}
|
||||||
viewType == VIEW_TYPE_ONLY_HISTORY -> {
|
viewType == VIEW_TYPE_ONLY_HISTORY -> {
|
||||||
|
val items = db.getHistoryUngrouped(
|
||||||
|
query,
|
||||||
|
if (isCustom) ENDLESS_LIMIT else pageOffset,
|
||||||
|
!updatePageCount && !isOnFirstPage,
|
||||||
|
)
|
||||||
if (groupChaptersHistory) {
|
if (groupChaptersHistory) {
|
||||||
db.getRecentMangaLimit(
|
items.executeOnIO().groupBy {
|
||||||
query,
|
val date = it.history.last_read
|
||||||
if (isCustom) ENDLESS_LIMIT else pageOffset,
|
it.manga.id to if (date <= 0L) "-1" else dateFormat.format(Date(date))
|
||||||
!updatePageCount && !isOnFirstPage,
|
}
|
||||||
)
|
.mapNotNull { (key, mchs) ->
|
||||||
|
val manga = mchs.first().manga
|
||||||
|
val chapters = mchs.map { mch ->
|
||||||
|
mch.chapter.also { it.history = mch.history }
|
||||||
|
}.filterChaptersByScanlators(manga)
|
||||||
|
if (chapters.isEmpty()) return@mapNotNull null
|
||||||
|
val existingItem = recentItems.find {
|
||||||
|
val date = Date(it.mch.history.last_read)
|
||||||
|
key == it.manga_id to dateFormat.format(date)
|
||||||
|
}?.takeIf { updatePageCount }
|
||||||
|
val sort = Comparator<Chapter> { c1, c2 ->
|
||||||
|
c2.dateRead!!.compareTo(c1.dateRead!!)
|
||||||
|
}
|
||||||
|
val (sortedChapters, firstChapter, subCount) =
|
||||||
|
setupExtraChapters(existingItem, chapters, sort)
|
||||||
|
?: return@mapNotNull null
|
||||||
|
extraCount += subCount
|
||||||
|
mchs.find { firstChapter.id == it.chapter.id }?.also {
|
||||||
|
it.extraChapters = sortedChapters
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
db.getHistoryUngrouped(
|
items.executeOnIO()
|
||||||
query,
|
}
|
||||||
if (isCustom) ENDLESS_LIMIT else pageOffset,
|
|
||||||
!updatePageCount && !isOnFirstPage,
|
|
||||||
)
|
|
||||||
}.executeOnIO()
|
|
||||||
}
|
}
|
||||||
viewType == VIEW_TYPE_ONLY_UPDATES -> {
|
viewType == VIEW_TYPE_ONLY_UPDATES -> {
|
||||||
db.getRecentChapters(
|
db.getRecentChapters(
|
||||||
|
@ -196,49 +214,21 @@ class RecentsPresenter(
|
||||||
val date = it.chapter.date_fetch
|
val date = it.chapter.date_fetch
|
||||||
it.manga.id to if (date <= 0L) "-1" else dateFormat.format(Date(date))
|
it.manga.id to if (date <= 0L) "-1" else dateFormat.format(Date(date))
|
||||||
}
|
}
|
||||||
.mapNotNull { entry ->
|
.mapNotNull { (key, mcs) ->
|
||||||
val manga = entry.value.first().manga
|
val manga = mcs.first().manga
|
||||||
val chapters = chapterFilter.filterChaptersByScanlators(
|
val chapters = mcs.map { it.chapter }.filterChaptersByScanlators(manga)
|
||||||
entry.value.map(MangaChapter::chapter),
|
if (chapters.isEmpty()) return@mapNotNull null
|
||||||
manga,
|
|
||||||
)
|
|
||||||
if (chapters.isEmpty()) { return@mapNotNull null }
|
|
||||||
val firstChapter: Chapter
|
|
||||||
var sortedChapters: MutableList<Chapter>
|
|
||||||
val existingItem = recentItems.find {
|
val existingItem = recentItems.find {
|
||||||
val date = Date(it.chapter.date_fetch)
|
val date = Date(it.chapter.date_fetch)
|
||||||
entry.key == it.manga_id to dateFormat.format(date)
|
key == it.manga_id to dateFormat.format(date)
|
||||||
}?.takeIf { updatePageCount }
|
}?.takeIf { updatePageCount }
|
||||||
if (existingItem != null) {
|
|
||||||
extraCount += chapters.size
|
|
||||||
val newChapters = existingItem.mch.extraChapters + chapters
|
|
||||||
val sort: Comparator<Chapter> =
|
val sort: Comparator<Chapter> =
|
||||||
ChapterSort(manga, chapterFilter, preferences)
|
ChapterSort(manga, chapterFilter, preferences)
|
||||||
.sortComparator(true)
|
.sortComparator(true)
|
||||||
sortedChapters = newChapters.sortedWith(sort).toMutableList()
|
val (sortedChapters, firstChapter, subCount) =
|
||||||
sortedChapters = (
|
setupExtraChapters(existingItem, chapters, sort)
|
||||||
sortedChapters.filter { !it.read } +
|
?: return@mapNotNull null
|
||||||
sortedChapters.filter { it.read }.reversed()
|
extraCount += subCount
|
||||||
).toMutableList()
|
|
||||||
existingItem.mch.extraChapters = sortedChapters
|
|
||||||
return@mapNotNull null
|
|
||||||
}
|
|
||||||
if (chapters.size == 1) {
|
|
||||||
firstChapter = chapters.first()
|
|
||||||
sortedChapters = mutableListOf()
|
|
||||||
} else {
|
|
||||||
val sort: Comparator<Chapter> =
|
|
||||||
ChapterSort(manga, chapterFilter, preferences)
|
|
||||||
.sortComparator(true)
|
|
||||||
sortedChapters = chapters.sortedWith(sort).toMutableList()
|
|
||||||
firstChapter =
|
|
||||||
sortedChapters.firstOrNull { !it.read } ?: sortedChapters.last()
|
|
||||||
sortedChapters.remove(firstChapter)
|
|
||||||
sortedChapters = (
|
|
||||||
sortedChapters.filter { !it.read } +
|
|
||||||
sortedChapters.filter { it.read }.reversed()
|
|
||||||
).toMutableList()
|
|
||||||
}
|
|
||||||
MangaChapterHistory(
|
MangaChapterHistory(
|
||||||
manga,
|
manga,
|
||||||
firstChapter,
|
firstChapter,
|
||||||
|
@ -281,8 +271,15 @@ class RecentsPresenter(
|
||||||
it.chapter
|
it.chapter
|
||||||
}
|
}
|
||||||
(it.chapter.read && viewType != VIEW_TYPE_ONLY_UPDATES) || it.chapter.id == null -> {
|
(it.chapter.read && viewType != VIEW_TYPE_ONLY_UPDATES) || it.chapter.id == null -> {
|
||||||
getNextChapter(it.manga)
|
val nextChapter = getNextChapter(it.manga)
|
||||||
?: if (showRead && it.chapter.id != null) it.chapter else null
|
?: if (showRead && it.chapter.id != null) it.chapter else null
|
||||||
|
if (viewType == VIEW_TYPE_ONLY_HISTORY && nextChapter?.id != null &&
|
||||||
|
nextChapter.id != it.chapter.id
|
||||||
|
) {
|
||||||
|
nextChapter.dateRead = it.chapter.dateRead
|
||||||
|
it.extraChapters = listOf(it.chapter) + it.extraChapters
|
||||||
|
}
|
||||||
|
nextChapter
|
||||||
}
|
}
|
||||||
it.history.id == null && viewType != VIEW_TYPE_ONLY_UPDATES -> {
|
it.history.id == null && viewType != VIEW_TYPE_ONLY_UPDATES -> {
|
||||||
getFirstUpdatedChapter(it.manga, it.chapter)
|
getFirstUpdatedChapter(it.manga, it.chapter)
|
||||||
|
@ -369,8 +366,6 @@ class RecentsPresenter(
|
||||||
} else {
|
} else {
|
||||||
recentItems + newItems
|
recentItems + newItems
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
heldItems[customViewType] = newItems
|
|
||||||
}
|
}
|
||||||
val newCount = itemCount + newItems.size + newItems.sumOf { it.mch.extraChapters.size } + extraCount
|
val newCount = itemCount + newItems.size + newItems.sumOf { it.mch.extraChapters.size } + extraCount
|
||||||
val hasNewItems = newItems.isNotEmpty()
|
val hasNewItems = newItems.isNotEmpty()
|
||||||
|
@ -393,6 +388,45 @@ class RecentsPresenter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupExtraChapters(
|
||||||
|
existingItem: RecentMangaItem?,
|
||||||
|
chapters: List<Chapter>,
|
||||||
|
sort: Comparator<Chapter>,
|
||||||
|
): Triple<MutableList<Chapter>, Chapter, Int>? {
|
||||||
|
var extraCount = 0
|
||||||
|
val firstChapter: Chapter
|
||||||
|
var sortedChapters: MutableList<Chapter>
|
||||||
|
val reverseRead = viewType != VIEW_TYPE_ONLY_HISTORY
|
||||||
|
if (existingItem != null) {
|
||||||
|
extraCount += chapters.size
|
||||||
|
val newChapters = existingItem.mch.extraChapters + chapters
|
||||||
|
sortedChapters = newChapters.sortedWith(sort).toMutableList()
|
||||||
|
sortedChapters = (
|
||||||
|
sortedChapters.filter { !it.read } +
|
||||||
|
sortedChapters.filter { it.read }
|
||||||
|
.run { if (reverseRead) reversed() else this }
|
||||||
|
).toMutableList()
|
||||||
|
existingItem.mch.extraChapters = sortedChapters
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (chapters.size == 1) {
|
||||||
|
firstChapter = chapters.first()
|
||||||
|
sortedChapters = mutableListOf()
|
||||||
|
} else {
|
||||||
|
sortedChapters = chapters.sortedWith(sort).toMutableList()
|
||||||
|
firstChapter = sortedChapters.firstOrNull { !it.read }
|
||||||
|
?: sortedChapters.run { if (reverseRead) last() else first() }
|
||||||
|
sortedChapters.last()
|
||||||
|
sortedChapters.remove(firstChapter)
|
||||||
|
sortedChapters = (
|
||||||
|
sortedChapters.filter { !it.read } +
|
||||||
|
sortedChapters.filter { it.read }
|
||||||
|
.run { if (reverseRead) reversed() else this }
|
||||||
|
).toMutableList()
|
||||||
|
}
|
||||||
|
return Triple(sortedChapters, firstChapter, extraCount)
|
||||||
|
}
|
||||||
|
|
||||||
private fun getNextChapter(manga: Manga): Chapter? {
|
private fun getNextChapter(manga: Manga): Chapter? {
|
||||||
val chapters = db.getChapters(manga).executeAsBlocking()
|
val chapters = db.getChapters(manga).executeAsBlocking()
|
||||||
return ChapterSort(manga, chapterFilter, preferences).getNextUnreadChapter(chapters, false)
|
return ChapterSort(manga, chapterFilter, preferences).getNextUnreadChapter(chapters, false)
|
||||||
|
@ -564,7 +598,6 @@ class RecentsPresenter(
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark the selected chapter list as read/unread.
|
* Mark the selected chapter list as read/unread.
|
||||||
* @param selectedChapters the list of selected chapters.
|
|
||||||
* @param read whether to mark chapters as read or unread.
|
* @param read whether to mark chapters as read or unread.
|
||||||
*/
|
*/
|
||||||
fun markChapterRead(
|
fun markChapterRead(
|
||||||
|
|
|
@ -19,7 +19,7 @@ class ChapterFilter(val preferences: PreferencesHelper = Injekt.get(), val downl
|
||||||
val notBookmarkEnabled = manga.bookmarkedFilter(preferences) == Manga.CHAPTER_SHOW_NOT_BOOKMARKED
|
val notBookmarkEnabled = manga.bookmarkedFilter(preferences) == Manga.CHAPTER_SHOW_NOT_BOOKMARKED
|
||||||
|
|
||||||
// if none of the filters are enabled skip the filtering of them
|
// if none of the filters are enabled skip the filtering of them
|
||||||
val filteredChapters = filterChaptersByScanlators(chapters, manga)
|
val filteredChapters = chapters.filterChaptersByScanlators(manga)
|
||||||
return if (readEnabled || unreadEnabled || downloadEnabled || notDownloadEnabled || bookmarkEnabled || notBookmarkEnabled) {
|
return if (readEnabled || unreadEnabled || downloadEnabled || notDownloadEnabled || bookmarkEnabled || notBookmarkEnabled) {
|
||||||
filteredChapters.filter {
|
filteredChapters.filter {
|
||||||
if (readEnabled && it.read.not() ||
|
if (readEnabled && it.read.not() ||
|
||||||
|
@ -40,7 +40,7 @@ class ChapterFilter(val preferences: PreferencesHelper = Injekt.get(), val downl
|
||||||
|
|
||||||
/** filter chapters for the reader */
|
/** filter chapters for the reader */
|
||||||
fun <T : Chapter> filterChaptersForReader(chapters: List<T>, manga: Manga, selectedChapter: T? = null): List<T> {
|
fun <T : Chapter> filterChaptersForReader(chapters: List<T>, manga: Manga, selectedChapter: T? = null): List<T> {
|
||||||
var filteredChapters = filterChaptersByScanlators(chapters, manga)
|
var filteredChapters = chapters.filterChaptersByScanlators(manga)
|
||||||
// if filter prefs aren't enabled don't even filter
|
// if filter prefs aren't enabled don't even filter
|
||||||
if (!preferences.skipRead() && !preferences.skipFiltered() && !preferences.skipDupe().get()) {
|
if (!preferences.skipRead() && !preferences.skipFiltered() && !preferences.skipDupe().get()) {
|
||||||
return filteredChapters
|
return filteredChapters
|
||||||
|
@ -82,11 +82,13 @@ class ChapterFilter(val preferences: PreferencesHelper = Injekt.get(), val downl
|
||||||
return filteredChapters
|
return filteredChapters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
/** filters chapters for scanlators */
|
/** filters chapters for scanlators */
|
||||||
fun <T : Chapter> filterChaptersByScanlators(chapters: List<T>, manga: Manga): List<T> {
|
fun <T : Chapter> List<T>.filterChaptersByScanlators(manga: Manga): List<T> {
|
||||||
return manga.filtered_scanlators?.let { filteredScanlatorString ->
|
return manga.filtered_scanlators?.let { filteredScanlatorString ->
|
||||||
val filteredScanlators = ChapterUtil.getScanlators(filteredScanlatorString)
|
val filteredScanlators = ChapterUtil.getScanlators(filteredScanlatorString)
|
||||||
chapters.filter { ChapterUtil.getScanlators(it.scanlator).none { group -> filteredScanlators.contains(group) } }
|
filter { ChapterUtil.getScanlators(it.scanlator).none { group -> filteredScanlators.contains(group) } }
|
||||||
} ?: chapters
|
} ?: this
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.util.chapter
|
||||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.util.chapter.ChapterFilter.Companion.filterChaptersByScanlators
|
||||||
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
|
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
@ -31,7 +32,7 @@ class ChapterSort(val manga: Manga, val chapterFilter: ChapterFilter = Injekt.ge
|
||||||
fun <T : Chapter> getNextUnreadChapter(rawChapters: List<T>, andFiltered: Boolean = true): T? {
|
fun <T : Chapter> getNextUnreadChapter(rawChapters: List<T>, andFiltered: Boolean = true): T? {
|
||||||
val chapters = when {
|
val chapters = when {
|
||||||
andFiltered -> chapterFilter.filterChapters(rawChapters, manga)
|
andFiltered -> chapterFilter.filterChapters(rawChapters, manga)
|
||||||
else -> chapterFilter.filterChaptersByScanlators(rawChapters, manga)
|
else -> rawChapters.filterChaptersByScanlators(manga)
|
||||||
}
|
}
|
||||||
|
|
||||||
return chapters.sortedWith(sortComparator(true)).find { !it.read }
|
return chapters.sortedWith(sortComparator(true)).find { !it.read }
|
||||||
|
|
|
@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
|
import eu.kanade.tachiyomi.util.chapter.ChapterFilter.Companion.filterChaptersByScanlators
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
@ -32,7 +33,6 @@ fun syncChaptersWithSource(
|
||||||
}
|
}
|
||||||
|
|
||||||
val downloadManager: DownloadManager = Injekt.get()
|
val downloadManager: DownloadManager = Injekt.get()
|
||||||
val chapterFilter: ChapterFilter = Injekt.get()
|
|
||||||
// Chapters from db.
|
// Chapters from db.
|
||||||
val dbChapters = db.getChapters(manga).executeAsBlocking()
|
val dbChapters = db.getChapters(manga).executeAsBlocking()
|
||||||
|
|
||||||
|
@ -169,9 +169,10 @@ fun syncChaptersWithSource(
|
||||||
}
|
}
|
||||||
db.updateLastUpdated(manga).executeAsBlocking()
|
db.updateLastUpdated(manga).executeAsBlocking()
|
||||||
}
|
}
|
||||||
|
val reAddedSet = readded.toSet()
|
||||||
return Pair(
|
return Pair(
|
||||||
chapterFilter.filterChaptersByScanlators(toAdd.subtract(readded).toList(), manga),
|
toAdd.subtract(reAddedSet).toList().filterChaptersByScanlators(manga),
|
||||||
toDelete - readded,
|
toDelete - reAddedSet,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,18 +178,6 @@
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/subtitle">
|
app:layout_constraintTop_toBottomOf="@id/subtitle">
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/remove_history"
|
|
||||||
android:layout_width="45dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="?selectableItemBackgroundBorderless"
|
|
||||||
android:contentDescription="@string/reset_chapter_history"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:tooltipText="@string/reset_chapter_history"
|
|
||||||
app:layout_constraintHorizontal_chainStyle="spread"
|
|
||||||
app:srcCompat="@drawable/ic_eye_remove_outline_24dp"
|
|
||||||
app:tint="@color/holo_red" />
|
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/show_more_chapters"
|
android:id="@+id/show_more_chapters"
|
||||||
android:layout_width="45dp"
|
android:layout_width="45dp"
|
||||||
|
@ -205,6 +193,17 @@
|
||||||
app:tint="?attr/colorSecondary"
|
app:tint="?attr/colorSecondary"
|
||||||
app:srcCompat="@drawable/ic_expand_more_24dp" />
|
app:srcCompat="@drawable/ic_expand_more_24dp" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/remove_history"
|
||||||
|
android:layout_width="45dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?selectableItemBackgroundBorderless"
|
||||||
|
android:contentDescription="@string/reset_chapter_history"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:tooltipText="@string/reset_chapter_history"
|
||||||
|
app:layout_constraintHorizontal_chainStyle="spread"
|
||||||
|
app:srcCompat="@drawable/ic_eye_remove_outline_24dp"
|
||||||
|
app:tint="@color/holo_red" />
|
||||||
<include
|
<include
|
||||||
android:id="@+id/download_button"
|
android:id="@+id/download_button"
|
||||||
layout="@layout/download_button"
|
layout="@layout/download_button"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue