mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2025-01-11 18:39:08 +01:00
Updates to Date Added
On upgrade, assign date added to the earliest chapter fetch Added "Newly Added" section to recents Reformated Recents to use a single recyclerview
This commit is contained in:
parent
0154653a2f
commit
5963c09691
@ -65,7 +65,7 @@ object Migrations {
|
|||||||
if (oldVersion < 54)
|
if (oldVersion < 54)
|
||||||
DownloadProvider(context).renameChaapters()
|
DownloadProvider(context).renameChaapters()
|
||||||
if (oldVersion < 62)
|
if (oldVersion < 62)
|
||||||
LibraryPresenter.resetCustomManga()
|
LibraryPresenter.updateDB()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -7,4 +7,8 @@ package eu.kanade.tachiyomi.data.database.models
|
|||||||
* @param chapter object containing chater
|
* @param chapter object containing chater
|
||||||
* @param history object containing history
|
* @param history object containing history
|
||||||
*/
|
*/
|
||||||
data class MangaChapterHistory(val manga: Manga, val chapter: Chapter, val history: History)
|
data class MangaChapterHistory(val manga: Manga, val chapter: Chapter, val history: History) {
|
||||||
|
companion object {
|
||||||
|
fun createBlank() = MangaChapterHistory(MangaImpl(), ChapterImpl(), HistoryImpl())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
|||||||
import eu.kanade.tachiyomi.data.database.resolvers.HistoryLastReadPutResolver
|
import eu.kanade.tachiyomi.data.database.resolvers.HistoryLastReadPutResolver
|
||||||
import eu.kanade.tachiyomi.data.database.resolvers.MangaChapterHistoryGetResolver
|
import eu.kanade.tachiyomi.data.database.resolvers.MangaChapterHistoryGetResolver
|
||||||
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
|
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
|
||||||
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
interface HistoryQueries : DbProvider {
|
interface HistoryQueries : DbProvider {
|
||||||
@ -33,6 +34,21 @@ 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 getRecentlyAdded(date: Date, search: String = "") = db.get()
|
||||||
|
.listOfObjects(MangaChapterHistory::class.java)
|
||||||
|
.withQuery(RawQuery.builder()
|
||||||
|
.query(getRecentAdditionsQuery(search))
|
||||||
|
.args(date.time)
|
||||||
|
.observesTables(MangaTable.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
|
||||||
|
@ -61,6 +61,18 @@ fun getRecentsQuery() = """
|
|||||||
ORDER BY ${Chapter.COL_DATE_UPLOAD} DESC
|
ORDER BY ${Chapter.COL_DATE_UPLOAD} DESC
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query to get the recent chapters of manga from the library up to a date.
|
||||||
|
*/
|
||||||
|
fun getRecentAdditionsQuery(search: String) = """
|
||||||
|
SELECT ${Manga.TABLE}.${Manga.COL_URL} as mangaUrl, * FROM ${Manga.TABLE}
|
||||||
|
WHERE ${Manga.COL_FAVORITE} = 1
|
||||||
|
AND ${Manga.COL_DATE_ADDED} > ?
|
||||||
|
AND lower(${Manga.COL_TITLE}) LIKE '%$search%'
|
||||||
|
ORDER BY ${Manga.COL_DATE_ADDED} DESC
|
||||||
|
LIMIT 8
|
||||||
|
"""
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query to get the recent chapters of manga from the library up to a date.
|
* Query to get the recent chapters of manga from the library up to a date.
|
||||||
*/
|
*/
|
||||||
@ -73,7 +85,7 @@ fun getRecentsQueryDistinct(search: String) = """
|
|||||||
SELECT ${Chapter.TABLE}.${Chapter.COL_MANGA_ID},${Chapter.TABLE}.${Chapter.COL_ID} as ${History.COL_CHAPTER_ID},MAX(${Chapter.TABLE}.${Chapter.COL_DATE_UPLOAD})
|
SELECT ${Chapter.TABLE}.${Chapter.COL_MANGA_ID},${Chapter.TABLE}.${Chapter.COL_ID} as ${History.COL_CHAPTER_ID},MAX(${Chapter.TABLE}.${Chapter.COL_DATE_UPLOAD})
|
||||||
FROM ${Chapter.TABLE} JOIN ${Manga.TABLE}
|
FROM ${Chapter.TABLE} JOIN ${Manga.TABLE}
|
||||||
ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}
|
ON ${Manga.TABLE}.${Manga.COL_ID} = ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}
|
||||||
WHERE ${Chapter.COL_DATE_FETCH} > ?
|
WHERE ${Chapter.COL_DATE_UPLOAD} > ?
|
||||||
AND ${Chapter.COL_READ} = 0
|
AND ${Chapter.COL_READ} = 0
|
||||||
GROUP BY ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}) AS newest_chapter
|
GROUP BY ${Chapter.TABLE}.${Chapter.COL_MANGA_ID}) AS newest_chapter
|
||||||
ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = newest_chapter.${Chapter.COL_MANGA_ID}
|
ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = newest_chapter.${Chapter.COL_MANGA_ID}
|
||||||
|
@ -5,6 +5,7 @@ import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
|
|||||||
import eu.kanade.tachiyomi.data.database.mappers.ChapterGetResolver
|
import eu.kanade.tachiyomi.data.database.mappers.ChapterGetResolver
|
||||||
import eu.kanade.tachiyomi.data.database.mappers.HistoryGetResolver
|
import eu.kanade.tachiyomi.data.database.mappers.HistoryGetResolver
|
||||||
import eu.kanade.tachiyomi.data.database.mappers.MangaGetResolver
|
import eu.kanade.tachiyomi.data.database.mappers.MangaGetResolver
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
|
||||||
import eu.kanade.tachiyomi.data.database.models.HistoryImpl
|
import eu.kanade.tachiyomi.data.database.models.HistoryImpl
|
||||||
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
||||||
|
|
||||||
@ -36,14 +37,17 @@ class MangaChapterHistoryGetResolver : DefaultGetResolver<MangaChapterHistory>()
|
|||||||
val manga = mangaGetResolver.mapFromCursor(cursor)
|
val manga = mangaGetResolver.mapFromCursor(cursor)
|
||||||
|
|
||||||
// Get chapter object
|
// Get chapter object
|
||||||
val chapter = chapterResolver.mapFromCursor(cursor)
|
val chapter = try { chapterResolver.mapFromCursor(cursor) } catch (e: Exception) {
|
||||||
|
ChapterImpl() }
|
||||||
|
|
||||||
// Get history object
|
// Get history object
|
||||||
val history = try { historyGetResolver.mapFromCursor(cursor) } catch (e: Exception) { HistoryImpl() }
|
val history = try { historyGetResolver.mapFromCursor(cursor) } catch (e: Exception) { HistoryImpl() }
|
||||||
|
|
||||||
// Make certain column conflicts are dealt with
|
// Make certain column conflicts are dealt with
|
||||||
|
if (chapter.id != null) {
|
||||||
manga.id = chapter.manga_id
|
manga.id = chapter.manga_id
|
||||||
manga.url = cursor.getString(cursor.getColumnIndex("mangaUrl"))
|
manga.url = cursor.getString(cursor.getColumnIndex("mangaUrl"))
|
||||||
|
}
|
||||||
if (history.id != null)
|
if (history.id != null)
|
||||||
chapter.id = history.chapter_id
|
chapter.id = history.chapter_id
|
||||||
|
|
||||||
|
@ -55,7 +55,8 @@ import kotlin.math.pow
|
|||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
import kotlin.math.sign
|
import kotlin.math.sign
|
||||||
|
|
||||||
class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
|
class
|
||||||
|
LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
|
||||||
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemLongClickListener,
|
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemLongClickListener,
|
||||||
FlexibleAdapter.OnItemMoveListener, LibraryCategoryAdapter.LibraryListener,
|
FlexibleAdapter.OnItemMoveListener, LibraryCategoryAdapter.LibraryListener,
|
||||||
SpinnerTitleInterface, OnTouchEventInterface, SwipeGestureInterface {
|
SpinnerTitleInterface, OnTouchEventInterface, SwipeGestureInterface {
|
||||||
|
@ -927,11 +927,16 @@ class LibraryPresenter(
|
|||||||
companion object {
|
companion object {
|
||||||
private var currentLibrary: Library? = null
|
private var currentLibrary: Library? = null
|
||||||
|
|
||||||
fun resetCustomManga() {
|
fun updateDB() {
|
||||||
val db: DatabaseHelper = Injekt.get()
|
val db: DatabaseHelper = Injekt.get()
|
||||||
db.inTransaction {
|
db.inTransaction {
|
||||||
val libraryManga = db.getLibraryMangas().executeAsBlocking()
|
val libraryManga = db.getLibraryMangas().executeAsBlocking()
|
||||||
libraryManga.forEach { manga ->
|
libraryManga.forEach { manga ->
|
||||||
|
if (manga.date_added == 0L) {
|
||||||
|
val chapters = db.getChapters(manga).executeAsBlocking()
|
||||||
|
manga.date_added = chapters.minBy { it.date_fetch }?.date_fetch ?: 0L
|
||||||
|
db.insertManga(manga).executeAsBlocking()
|
||||||
|
}
|
||||||
db.resetMangaInfo(manga).executeAsBlocking()
|
db.resetMangaInfo(manga).executeAsBlocking()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,6 @@ object LibrarySort {
|
|||||||
const val LATEST_CHAPTER = 2
|
const val LATEST_CHAPTER = 2
|
||||||
const val UNREAD = 3
|
const val UNREAD = 3
|
||||||
const val TOTAL = 4
|
const val TOTAL = 4
|
||||||
|
const val DATE_ADDED = 5
|
||||||
const val DRAG_AND_DROP = 6
|
const val DRAG_AND_DROP = 6
|
||||||
const val DATE_ADDED = 7
|
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,11 @@ open class BaseChapterHolder(
|
|||||||
) : BaseFlexibleViewHolder(view, adapter) {
|
) : BaseFlexibleViewHolder(view, adapter) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
download_button.setOnClickListener { downloadOrRemoveMenu() }
|
download_button?.setOnClickListener { downloadOrRemoveMenu() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun downloadOrRemoveMenu() {
|
private fun downloadOrRemoveMenu() {
|
||||||
val chapter = adapter.getItem(adapterPosition) as? BaseChapterItem ?: return
|
val chapter = adapter.getItem(adapterPosition) as? BaseChapterItem<*, *> ?: return
|
||||||
if (chapter.status == Download.NOT_DOWNLOADED || chapter.status == Download.ERROR) {
|
if (chapter.status == Download.NOT_DOWNLOADED || chapter.status == Download.ERROR) {
|
||||||
adapter.baseDelegate.downloadChapter(adapterPosition)
|
adapter.baseDelegate.downloadChapter(adapterPosition)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
package eu.kanade.tachiyomi.ui.manga.chapter
|
package eu.kanade.tachiyomi.ui.manga.chapter
|
||||||
|
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
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.database.models.Chapter
|
||||||
import eu.kanade.tachiyomi.data.download.model.Download
|
import eu.kanade.tachiyomi.data.download.model.Download
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
|
|
||||||
abstract class BaseChapterItem<T : BaseChapterHolder>(val chapter: Chapter) :
|
abstract class BaseChapterItem<T : BaseChapterHolder, H : AbstractHeaderItem<*>>(
|
||||||
AbstractFlexibleItem<T>(),
|
val chapter:
|
||||||
|
Chapter,
|
||||||
|
header: H? = null
|
||||||
|
) :
|
||||||
|
AbstractSectionableItem<T, H?>(header),
|
||||||
Chapter by chapter {
|
Chapter by chapter {
|
||||||
|
|
||||||
private var _status: Int = 0
|
private var _status: Int = 0
|
||||||
@ -28,13 +33,13 @@ abstract class BaseChapterItem<T : BaseChapterHolder>(val chapter: Chapter) :
|
|||||||
|
|
||||||
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 BaseChapterItem<*>) {
|
if (other is BaseChapterItem<*, *>) {
|
||||||
return chapter.id!! == other.chapter.id!!
|
return chapter.id == other.chapter.id
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
return chapter.id!!.hashCode()
|
return (chapter.id ?: 0L).hashCode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,16 @@ package eu.kanade.tachiyomi.ui.manga.chapter
|
|||||||
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.davidea.viewholders.FlexibleViewHolder
|
||||||
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
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaDetailsAdapter
|
import eu.kanade.tachiyomi.ui.manga.MangaDetailsAdapter
|
||||||
|
|
||||||
class ChapterItem(chapter: Chapter, val manga: Manga) :
|
class ChapterItem(chapter: Chapter, val manga: Manga) :
|
||||||
BaseChapterItem<ChapterHolder>(chapter) {
|
BaseChapterItem<ChapterHolder, AbstractHeaderItem<FlexibleViewHolder>>(chapter) {
|
||||||
|
|
||||||
var isLocked = false
|
var isLocked = false
|
||||||
|
|
||||||
|
@ -9,7 +9,11 @@ import java.text.DecimalFormat
|
|||||||
import java.text.DecimalFormatSymbols
|
import java.text.DecimalFormatSymbols
|
||||||
|
|
||||||
class RecentMangaAdapter(val delegate: RecentsInterface) :
|
class RecentMangaAdapter(val delegate: RecentsInterface) :
|
||||||
BaseChapterAdapter<IFlexible<RecentMangaHolder>>(delegate) {
|
BaseChapterAdapter<IFlexible<*>>(delegate) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
setDisplayHeadersAtStartUp(true)
|
||||||
|
}
|
||||||
|
|
||||||
val decimalFormat = DecimalFormat("#.###", DecimalFormatSymbols()
|
val decimalFormat = DecimalFormat("#.###", DecimalFormatSymbols()
|
||||||
.apply { decimalSeparator = '.' })
|
.apply { decimalSeparator = '.' })
|
||||||
@ -17,9 +21,11 @@ class RecentMangaAdapter(val delegate: RecentsInterface) :
|
|||||||
interface RecentsInterface : RecentMangaInterface, DownloadInterface
|
interface RecentsInterface : RecentMangaInterface, DownloadInterface
|
||||||
|
|
||||||
interface RecentMangaInterface {
|
interface RecentMangaInterface {
|
||||||
|
fun onHeaderClick(position: Int)
|
||||||
fun onCoverClick(position: Int)
|
fun onCoverClick(position: Int)
|
||||||
fun markAsRead(position: Int)
|
fun markAsRead(position: Int)
|
||||||
fun setCover(manga: Manga, view: ImageView)
|
fun setCover(manga: Manga, view: ImageView)
|
||||||
|
fun isSearching(): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemSwiped(position: Int, direction: Int) {
|
override fun onItemSwiped(position: Int, direction: Int) {
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
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.AbstractHeaderItem
|
||||||
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
||||||
|
import eu.kanade.tachiyomi.ui.library.LibraryHeaderItem
|
||||||
|
import kotlinx.android.synthetic.main.recents_header_item.*
|
||||||
|
|
||||||
|
class RecentMangaHeaderItem(val recentsType: Int) :
|
||||||
|
AbstractHeaderItem<RecentMangaHeaderItem.Holder>() {
|
||||||
|
|
||||||
|
override fun getLayoutRes(): Int {
|
||||||
|
return R.layout.recents_header_item
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createViewHolder(
|
||||||
|
view: View,
|
||||||
|
adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>
|
||||||
|
): Holder {
|
||||||
|
return Holder(view, adapter as RecentMangaAdapter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bindViewHolder(
|
||||||
|
adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>,
|
||||||
|
holder: Holder,
|
||||||
|
position: Int,
|
||||||
|
payloads: MutableList<Any?>?
|
||||||
|
) {
|
||||||
|
holder.bind(recentsType)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (other is LibraryHeaderItem) {
|
||||||
|
return recentsType == recentsType
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isDraggable(): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isSwipeable(): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return recentsType.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Holder(val view: View, adapter: RecentMangaAdapter) : BaseFlexibleViewHolder(view, adapter,
|
||||||
|
true) {
|
||||||
|
|
||||||
|
fun bind(recentsType: Int) {
|
||||||
|
title.setText(when (recentsType) {
|
||||||
|
RecentsItem.CONTINUE_READING -> R.string.continue_reading
|
||||||
|
RecentsItem.NEW_CHAPTERS -> R.string.new_chapters
|
||||||
|
RecentsItem.NEWLY_ADDED -> R.string.new_additions
|
||||||
|
else -> R.string.continue_reading
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,46 +17,55 @@ class RecentMangaHolder(
|
|||||||
) : BaseChapterHolder(view, adapter) {
|
) : BaseChapterHolder(view, adapter) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
cover_thumbnail.setOnClickListener { adapter.delegate.onCoverClick(adapterPosition) }
|
cover_thumbnail?.setOnClickListener { adapter.delegate.onCoverClick(adapterPosition) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bind(recentsType: Int) {
|
||||||
|
when (recentsType) {
|
||||||
|
RecentsItem.CONTINUE_READING -> {
|
||||||
|
title.setText(R.string.view_history)
|
||||||
|
}
|
||||||
|
RecentsItem.NEW_CHAPTERS -> {
|
||||||
|
title.setText(R.string.view_all_updates)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
title.text = item.mch.manga.title
|
title.text = item.mch.manga.title
|
||||||
val holder = (adapter.delegate as RecentsHolder)
|
val isSearch = adapter.delegate.isSearching()
|
||||||
val isSearch =
|
|
||||||
(holder.adapter.getItem(holder.adapterPosition) as RecentsItem).recentType == RecentsItem.SEARCH
|
|
||||||
subtitle.text = item.chapter.name
|
subtitle.text = item.chapter.name
|
||||||
body.text = if (isSearch) when {
|
val notValidNum = item.mch.chapter.chapter_number <= 0
|
||||||
|
body.text = when {
|
||||||
|
item.mch.chapter.id == null -> body.context.getString(
|
||||||
|
R.string.added_x, DateUtils.getRelativeTimeSpanString(
|
||||||
|
item.mch.manga.date_added, Date().time, DateUtils.MINUTE_IN_MILLIS
|
||||||
|
).toString()
|
||||||
|
)
|
||||||
item.chapter.id != item.mch.chapter.id -> body.context.getString(
|
item.chapter.id != item.mch.chapter.id -> body.context.getString(
|
||||||
R.string.last_read_chapter_x, adapter.decimalFormat.format(
|
if (notValidNum) R.string.last_read_x else R.string.last_read_chapter_x,
|
||||||
item.mch.chapter.chapter_number
|
if (notValidNum) item.mch.chapter.name else adapter.decimalFormat.format(item.mch.chapter.chapter_number) +
|
||||||
) + " (${DateUtils.getRelativeTimeSpanString(
|
" (${DateUtils.getRelativeTimeSpanString(
|
||||||
item.mch.history.last_read, Date().time, DateUtils.MINUTE_IN_MILLIS
|
item.mch.history.last_read, Date().time, DateUtils.MINUTE_IN_MILLIS
|
||||||
)})"
|
)})"
|
||||||
)
|
)
|
||||||
item.mch.history.id == null -> body.context.getString(
|
item.mch.history.id == null -> body.context.getString(
|
||||||
R.string.uploaded_x, DateUtils.getRelativeTimeSpanString(
|
R.string.updated_x, DateUtils.getRelativeTimeSpanString(
|
||||||
item.chapter.date_upload, Date().time, DateUtils.HOUR_IN_MILLIS
|
item.chapter.date_upload, Date().time, DateUtils.HOUR_IN_MILLIS
|
||||||
).toString()
|
).toString()
|
||||||
)
|
)
|
||||||
else -> body.context.getString(
|
!isSearch && item.chapter.pages_left > 0 -> itemView.resources.getQuantityString(
|
||||||
R.string.last_read_x, DateUtils.getRelativeTimeSpanString(
|
R.plurals.pages_left, item.chapter.pages_left, item.chapter.pages_left
|
||||||
|
) +
|
||||||
|
" (${DateUtils.getRelativeTimeSpanString(
|
||||||
|
item.mch.history.last_read, Date().time, DateUtils.MINUTE_IN_MILLIS
|
||||||
|
)})"
|
||||||
|
isSearch -> body.context.getString(
|
||||||
|
R.string.read_x, DateUtils.getRelativeTimeSpanString(
|
||||||
item.mch.history.last_read, Date().time, DateUtils.MINUTE_IN_MILLIS
|
item.mch.history.last_read, Date().time, DateUtils.MINUTE_IN_MILLIS
|
||||||
).toString()
|
).toString()
|
||||||
)
|
)
|
||||||
} else when {
|
|
||||||
item.chapter.id != item.mch.chapter.id -> body.context.getString(
|
|
||||||
R.string.last_read_chapter_x, adapter.decimalFormat.format(
|
|
||||||
item.mch.chapter.chapter_number
|
|
||||||
)
|
|
||||||
)
|
|
||||||
item.mch.history.id == null -> DateUtils.getRelativeTimeSpanString(
|
|
||||||
item.chapter.date_upload, Date().time, DateUtils.HOUR_IN_MILLIS
|
|
||||||
).toString()
|
|
||||||
item.chapter.pages_left > 0 -> itemView.resources.getQuantityString(
|
|
||||||
R.plurals.pages_left, item.chapter.pages_left, item.chapter.pages_left
|
|
||||||
)
|
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
adapter.delegate.setCover(item.mch.manga, cover_thumbnail)
|
adapter.delegate.setCover(item.mch.manga, cover_thumbnail)
|
||||||
|
@ -6,14 +6,21 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
|
|||||||
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
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
|
||||||
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory
|
||||||
import eu.kanade.tachiyomi.ui.manga.chapter.BaseChapterItem
|
import eu.kanade.tachiyomi.ui.manga.chapter.BaseChapterItem
|
||||||
|
|
||||||
class RecentMangaItem(val mch: MangaChapterHistory, chapter: Chapter) :
|
class RecentMangaItem(
|
||||||
BaseChapterItem<RecentMangaHolder>(chapter) {
|
val mch: MangaChapterHistory = MangaChapterHistory.createBlank(),
|
||||||
|
chapter: Chapter = ChapterImpl(),
|
||||||
|
header:
|
||||||
|
RecentMangaHeaderItem?
|
||||||
|
) :
|
||||||
|
BaseChapterItem<RecentMangaHolder, RecentMangaHeaderItem>(chapter, header) {
|
||||||
|
|
||||||
override fun getLayoutRes(): Int {
|
override fun getLayoutRes(): Int {
|
||||||
return R.layout.recent_manga_item
|
return if (mch.manga.id == null) R.layout.recents_footer_item
|
||||||
|
else R.layout.recent_manga_item
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createViewHolder(
|
override fun createViewHolder(
|
||||||
@ -23,12 +30,31 @@ class RecentMangaItem(val mch: MangaChapterHistory, chapter: Chapter) :
|
|||||||
return RecentMangaHolder(view, adapter as RecentMangaAdapter)
|
return RecentMangaHolder(view, adapter as RecentMangaAdapter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun isSwipeable(): Boolean {
|
||||||
|
return mch.manga.id != null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (other is RecentMangaItem) {
|
||||||
|
return if (mch.manga.id == null) header?.recentsType == other.header?.recentsType
|
||||||
|
else chapter.id == other.chapter.id
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return if (mch.manga.id == null) -(header?.recentsType ?: 0).hashCode()
|
||||||
|
else (chapter.id ?: 0L).hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
override fun bindViewHolder(
|
override fun bindViewHolder(
|
||||||
adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>,
|
adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>,
|
||||||
holder: RecentMangaHolder,
|
holder: RecentMangaHolder,
|
||||||
position: Int,
|
position: Int,
|
||||||
payloads: MutableList<Any?>?
|
payloads: MutableList<Any?>?
|
||||||
) {
|
) {
|
||||||
holder.bind(this)
|
if (mch.manga.id == null) holder.bind(header?.recentsType ?: 0)
|
||||||
|
else holder.bind(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.bluelinelabs.conductor.Controller
|
import com.bluelinelabs.conductor.Controller
|
||||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||||
@ -48,8 +49,9 @@ import kotlinx.android.synthetic.main.recently_read_controller.*
|
|||||||
* UI related actions should be called from here.
|
* UI related actions should be called from here.
|
||||||
*/
|
*/
|
||||||
class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
||||||
FlexibleAdapter.OnUpdateListener,
|
RecentMangaAdapter.RecentsInterface,
|
||||||
RecentsAdapter.RecentsInterface,
|
RecentsAdapter.RecentsInterface,
|
||||||
|
FlexibleAdapter.OnItemClickListener,
|
||||||
RootSearchInterface {
|
RootSearchInterface {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -59,10 +61,11 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
/**
|
/**
|
||||||
* Adapter containing the recent manga.
|
* Adapter containing the recent manga.
|
||||||
*/
|
*/
|
||||||
private val adapter = RecentsAdapter(this)
|
// private val adapter = RecentsAdapter(this)
|
||||||
|
private var adapter = RecentMangaAdapter(this)
|
||||||
|
|
||||||
private var presenter = RecentsPresenter(this)
|
private var presenter = RecentsPresenter(this)
|
||||||
private var recentItems: List<RecentsItem>? = null
|
private var recentItems: List<RecentMangaItem>? = null
|
||||||
private var snack: Snackbar? = null
|
private var snack: Snackbar? = null
|
||||||
private var lastChapterId: Long? = null
|
private var lastChapterId: Long? = null
|
||||||
|
|
||||||
@ -83,10 +86,20 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
super.onViewCreated(view)
|
super.onViewCreated(view)
|
||||||
view.applyWindowInsetsForRootController(activity!!.bottom_nav)
|
view.applyWindowInsetsForRootController(activity!!.bottom_nav)
|
||||||
// Initialize adapter
|
// Initialize adapter
|
||||||
|
adapter = RecentMangaAdapter(this)
|
||||||
recycler.adapter = adapter
|
recycler.adapter = adapter
|
||||||
recycler.layoutManager = LinearLayoutManager(view.context)
|
recycler.layoutManager = LinearLayoutManager(view.context)
|
||||||
recycler.setHasFixedSize(true)
|
recycler.setHasFixedSize(true)
|
||||||
|
recycler.recycledViewPool.setMaxRecycledViews(0, 0)
|
||||||
|
adapter.isSwipeEnabled = true
|
||||||
|
/*recycler.addItemDecoration(
|
||||||
|
DividerItemDecoration(
|
||||||
|
recycler.context, DividerItemDecoration.VERTICAL
|
||||||
|
)
|
||||||
|
)*/
|
||||||
|
adapter.itemTouchHelperCallback.setSwipeFlags(
|
||||||
|
ItemTouchHelper.LEFT
|
||||||
|
)
|
||||||
scrollViewWith(recycler, skipFirstSnap = true)
|
scrollViewWith(recycler, skipFirstSnap = true)
|
||||||
|
|
||||||
if (recentItems != null) adapter.updateDataSet(recentItems!!.toList())
|
if (recentItems != null) adapter.updateDataSet(recentItems!!.toList())
|
||||||
@ -108,37 +121,42 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
|
|
||||||
fun refresh() = presenter.getRecents()
|
fun refresh() = presenter.getRecents()
|
||||||
|
|
||||||
fun showLists(recents: List<RecentsItem>) {
|
fun showLists(recents: List<RecentMangaItem>) {
|
||||||
recentItems = recents
|
recentItems = recents
|
||||||
adapter.updateDataSet(recents)
|
adapter.updateDataSet(recents)
|
||||||
if (lastChapterId != null) {
|
if (lastChapterId != null) {
|
||||||
refreshItem(lastChapterId ?: 0L)
|
refreshItem(lastChapterId ?: 0L)
|
||||||
lastChapterId = null
|
lastChapterId = null
|
||||||
}
|
}
|
||||||
}
|
// recycler.removeItemDecorationAt(0)
|
||||||
|
|
||||||
override fun onUpdateEmptyView(size: Int) {
|
|
||||||
if (size > 0) {
|
|
||||||
empty_view?.hide()
|
|
||||||
} else {
|
|
||||||
empty_view?.show(R.drawable.ic_history_white_128dp, R.string
|
|
||||||
.information_no_recent_manga)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateChapterDownload(download: Download) {
|
fun updateChapterDownload(download: Download) {
|
||||||
if (view == null) return
|
if (view == null) return
|
||||||
for (i in 0 until adapter.itemCount) {
|
val id = download.chapter.id ?: return
|
||||||
|
val holder = recycler.findViewHolderForItemId(id) as? RecentMangaHolder ?: return
|
||||||
|
holder.notifyStatus(download.status, download.progress)
|
||||||
|
/* (i in 0 until adapter.itemCount) {
|
||||||
val holder = recycler.findViewHolderForAdapterPosition(i) as? RecentsHolder ?: continue
|
val holder = recycler.findViewHolderForAdapterPosition(i) as? RecentsHolder ?: continue
|
||||||
if (holder.updateChapterDownload(download)) break
|
if (holder.updateChapterDownload(download)) break
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshItem(chapterId: Long) {
|
private fun refreshItem(chapterId: Long) {
|
||||||
|
val recentItemPos = adapter.currentItems.indexOfFirst {
|
||||||
|
it is RecentMangaItem &&
|
||||||
|
it.mch.chapter.id == chapterId }
|
||||||
|
if (recentItemPos > -1) adapter.notifyItemChanged(recentItemPos)
|
||||||
|
/*holder.notifyStatus(download.status, download.progress)
|
||||||
for (i in 0 until adapter.itemCount) {
|
for (i in 0 until adapter.itemCount) {
|
||||||
val holder = recycler.findViewHolderForAdapterPosition(i) as? RecentsHolder ?: continue
|
val holder = recycler.findViewHolderForAdapterPosition(i) as? RecentsHolder ?: continue
|
||||||
holder.refreshChapter(chapterId)
|
holder.refreshChapter(chapterId)
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun downloadChapter(position: Int) {
|
||||||
|
val item = adapter.getItem(position) as? RecentMangaItem ?: return
|
||||||
|
downloadChapter(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun downloadChapter(item: RecentMangaItem) {
|
override fun downloadChapter(item: RecentMangaItem) {
|
||||||
@ -153,18 +171,49 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun startDownloadNow(position: Int) {
|
||||||
|
val chapter = (adapter.getItem(position) as? RecentMangaItem)?.chapter ?: return
|
||||||
|
presenter.startDownloadChapterNow(chapter)
|
||||||
|
}
|
||||||
|
|
||||||
override fun downloadChapterNow(chapter: Chapter) {
|
override fun downloadChapterNow(chapter: Chapter) {
|
||||||
presenter.startDownloadChapterNow(chapter)
|
presenter.startDownloadChapterNow(chapter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCoverClick(position: Int) {
|
||||||
|
val manga = (adapter.getItem(position) as? RecentMangaItem)?.mch?.manga ?: return
|
||||||
|
router.pushController(MangaDetailsController(manga).withFadeTransaction())
|
||||||
|
}
|
||||||
|
|
||||||
override fun showManga(manga: Manga) = router.pushController(MangaDetailsController(manga).withFadeTransaction())
|
override fun showManga(manga: Manga) = router.pushController(MangaDetailsController(manga).withFadeTransaction())
|
||||||
|
|
||||||
|
override fun onItemClick(view: View?, position: Int): Boolean {
|
||||||
|
val item = adapter.getItem(position) ?: return false
|
||||||
|
if (item is RecentMangaItem) {
|
||||||
|
if (item.mch.manga.id == null) {
|
||||||
|
val headerItem = adapter.getHeaderOf(item) as? RecentMangaHeaderItem
|
||||||
|
val controller: Controller = when (headerItem?.recentsType) {
|
||||||
|
RecentsItem.NEW_CHAPTERS -> RecentChaptersController()
|
||||||
|
RecentsItem.CONTINUE_READING -> RecentlyReadController()
|
||||||
|
else -> return false
|
||||||
|
}
|
||||||
|
router.pushController(controller.withFadeTransaction())
|
||||||
|
} else resumeManga(item.mch.manga, item.chapter)
|
||||||
|
} else if (item is RecentMangaHeaderItem) return false // onHeaderClick(position)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
override fun resumeManga(manga: Manga, chapter: Chapter) {
|
override fun resumeManga(manga: Manga, chapter: Chapter) {
|
||||||
val activity = activity ?: return
|
val activity = activity ?: return
|
||||||
val intent = ReaderActivity.newIntent(activity, manga, chapter)
|
val intent = ReaderActivity.newIntent(activity, manga, chapter)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun markAsRead(position: Int) {
|
||||||
|
val item = adapter.getItem(position) as? RecentMangaItem ?: return
|
||||||
|
markAsRead(item.mch.manga, item.chapter)
|
||||||
|
}
|
||||||
|
|
||||||
override fun markAsRead(manga: Manga, chapter: Chapter) {
|
override fun markAsRead(manga: Manga, chapter: Chapter) {
|
||||||
val lastRead = chapter.last_page_read
|
val lastRead = chapter.last_page_read
|
||||||
val pagesLeft = chapter.pages_left
|
val pagesLeft = chapter.pages_left
|
||||||
@ -191,6 +240,8 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
(activity as? MainActivity)?.setUndoSnackBar(snack)
|
(activity as? MainActivity)?.setUndoSnackBar(snack)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun isSearching() = presenter.query.isNotEmpty()
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
inflater.inflate(R.menu.recents, menu)
|
inflater.inflate(R.menu.recents, menu)
|
||||||
val searchItem = menu.findItem(R.id.action_search)
|
val searchItem = menu.findItem(R.id.action_search)
|
||||||
@ -229,8 +280,9 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
.signature(ObjectKey(MangaImpl.getLastCoverFetch(manga.id!!).toString())).into(view)
|
.signature(ObjectKey(MangaImpl.getLastCoverFetch(manga.id!!).toString())).into(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun viewAll(position: Int) {
|
override fun onHeaderClick(position: Int) {
|
||||||
val recentsType = (adapter.getItem(position) as? RecentsItem)?.recentType ?: return
|
val recentsType = (adapter.getItem(position) as? RecentMangaHeaderItem)?.recentsType
|
||||||
|
?: return
|
||||||
val controller: Controller = when (recentsType) {
|
val controller: Controller = when (recentsType) {
|
||||||
RecentsItem.NEW_CHAPTERS -> RecentChaptersController()
|
RecentsItem.NEW_CHAPTERS -> RecentChaptersController()
|
||||||
RecentsItem.CONTINUE_READING -> RecentlyReadController()
|
RecentsItem.CONTINUE_READING -> RecentlyReadController()
|
||||||
@ -239,6 +291,16 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
|
|||||||
router.pushController(controller.withFadeTransaction())
|
router.pushController(controller.withFadeTransaction())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun viewAll(position: Int) {
|
||||||
|
/*val recentsType = (adapter.getItem(position) as? RecentsItem)?.recentType ?: return
|
||||||
|
val controller: Controller = when (recentsType) {
|
||||||
|
RecentsItem.NEW_CHAPTERS -> RecentChaptersController()
|
||||||
|
RecentsItem.CONTINUE_READING -> RecentlyReadController()
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
router.pushController(controller.withFadeTransaction())*/
|
||||||
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.action_refresh -> {
|
R.id.action_refresh -> {
|
||||||
|
@ -129,4 +129,8 @@ class RecentsHolder(
|
|||||||
val item = (subAdapter.getItem(position) as RecentMangaItem)
|
val item = (subAdapter.getItem(position) as RecentMangaItem)
|
||||||
adapter.delegate.markAsRead(item.mch.manga, item.chapter)
|
adapter.delegate.markAsRead(item.mch.manga, item.chapter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onHeaderClick(position: Int) {
|
||||||
|
}
|
||||||
|
override fun isSearching() = false
|
||||||
}
|
}
|
||||||
|
@ -32,9 +32,12 @@ class RecentsPresenter(
|
|||||||
|
|
||||||
private var scope = CoroutineScope(Job() + Dispatchers.Default)
|
private var scope = CoroutineScope(Job() + Dispatchers.Default)
|
||||||
|
|
||||||
private var recentItems = listOf<RecentMangaItem>()
|
var recentItems = listOf<RecentMangaItem>()
|
||||||
var groupedRecentItems = listOf<RecentsItem>()
|
// var groupedRecentItems = listOf<RecentsItem>()
|
||||||
var query = ""
|
var query = ""
|
||||||
|
var newAdditionsHeader = RecentMangaHeaderItem(RecentsItem.NEWLY_ADDED)
|
||||||
|
var newChaptersHeader = RecentMangaHeaderItem(RecentsItem.NEW_CHAPTERS)
|
||||||
|
var continueReadingHeader = RecentMangaHeaderItem(RecentsItem.CONTINUE_READING)
|
||||||
|
|
||||||
fun onCreate() {
|
fun onCreate() {
|
||||||
downloadManager.addListener(this)
|
downloadManager.addListener(this)
|
||||||
@ -43,51 +46,75 @@ class RecentsPresenter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getRecents() {
|
fun getRecents() {
|
||||||
|
val oldQuery = query
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val cal = Calendar.getInstance()
|
val cal = Calendar.getInstance()
|
||||||
cal.time = Date()
|
cal.time = Date()
|
||||||
if (query.isNotEmpty()) cal.add(Calendar.YEAR, -50)
|
if (query.isNotEmpty()) cal.add(Calendar.YEAR, -50)
|
||||||
else cal.add(Calendar.MONTH, -1)
|
else cal.add(Calendar.MONTH, -1)
|
||||||
|
|
||||||
|
val calWeek = Calendar.getInstance()
|
||||||
|
calWeek.time = Date()
|
||||||
|
if (query.isNotEmpty()) calWeek.add(Calendar.YEAR, -50)
|
||||||
|
else calWeek.add(Calendar.DAY_OF_YEAR, -1)
|
||||||
|
|
||||||
val cReading =
|
val cReading =
|
||||||
if (query.isEmpty())
|
if (query.isEmpty()) db.getRecentsWithUnread(cal.time, query).executeOnIO()
|
||||||
db.getRecentsWithUnread(cal.time, query).executeOnIO()
|
else db.getRecentMangaLimit(cal.time, 8, query).executeOnIO()
|
||||||
else
|
|
||||||
db.getRecentMangaLimit(cal.time, 8, query).executeOnIO()
|
|
||||||
val rUpdates = db.getUpdatedManga(cal.time, query).executeOnIO()
|
val rUpdates = db.getUpdatedManga(cal.time, query).executeOnIO()
|
||||||
rUpdates.forEach {
|
rUpdates.forEach {
|
||||||
it.history.last_read = it.chapter.date_upload
|
it.history.last_read = it.chapter.date_fetch
|
||||||
}
|
}
|
||||||
val mangaList = (cReading + rUpdates).sortedByDescending {
|
val nAdditions = db.getRecentlyAdded(calWeek.time, query).executeOnIO()
|
||||||
|
nAdditions.forEach {
|
||||||
|
it.history.last_read = it.manga.date_added
|
||||||
|
}
|
||||||
|
if (query != oldQuery) return@launch
|
||||||
|
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()) it.manga.id else it.chapter.id
|
||||||
recentItems = mangaList.mapNotNull {
|
}
|
||||||
val chapter = if (it.chapter.read) getNextChapter(it.manga)
|
val pairs = mangaList.mapNotNull {
|
||||||
|
val chapter = if (it.chapter.read || it.chapter.id == null) getNextChapter(it.manga)
|
||||||
else it.chapter
|
else it.chapter
|
||||||
if (chapter == null) if (query.isNotEmpty()) RecentMangaItem(it, it.chapter)
|
if (chapter == null) if (query.isNotEmpty() && it.chapter.id != null) Pair(
|
||||||
|
it, it.chapter
|
||||||
|
)
|
||||||
else null
|
else null
|
||||||
else RecentMangaItem(it, chapter)
|
else Pair(it, chapter)
|
||||||
|
}
|
||||||
|
if (query.isEmpty()) {
|
||||||
|
val nChaptersItems =
|
||||||
|
pairs.filter { it.first.history.id == null && it.first.chapter.id != null }
|
||||||
|
.sortedByDescending { it.second.date_upload }
|
||||||
|
.take(4).map {
|
||||||
|
RecentMangaItem(
|
||||||
|
it.first,
|
||||||
|
it.second,
|
||||||
|
newChaptersHeader
|
||||||
|
)
|
||||||
|
} +
|
||||||
|
RecentMangaItem(header = newChaptersHeader)
|
||||||
|
val cReadingItems =
|
||||||
|
pairs.filter { it.first.history.id != null }.take(9 - nChaptersItems.size).map {
|
||||||
|
RecentMangaItem(
|
||||||
|
it.first,
|
||||||
|
it.second,
|
||||||
|
continueReadingHeader
|
||||||
|
)
|
||||||
|
} + RecentMangaItem(header = continueReadingHeader)
|
||||||
|
val nAdditionsItems = pairs.filter { it.first.chapter.id == null }.take(4)
|
||||||
|
.map { RecentMangaItem(it.first, it.second, newAdditionsHeader) }
|
||||||
|
recentItems =
|
||||||
|
listOf(nChaptersItems, cReadingItems, nAdditionsItems).sortedByDescending {
|
||||||
|
it.firstOrNull()?.mch?.history?.last_read ?: 0L
|
||||||
|
}.flatten()
|
||||||
|
} else {
|
||||||
|
recentItems = pairs.map { RecentMangaItem(it.first, it.second, null) }
|
||||||
}
|
}
|
||||||
setDownloadedChapters(recentItems)
|
setDownloadedChapters(recentItems)
|
||||||
if (query.isEmpty()) {
|
withContext(Dispatchers.Main) { controller.showLists(recentItems) }
|
||||||
val nChaptersItems = RecentsItem(
|
|
||||||
RecentsItem.NEW_CHAPTERS,
|
|
||||||
recentItems.filter { it.mch.history.id == null }.take(4)
|
|
||||||
)
|
|
||||||
val cReadingItems = RecentsItem(
|
|
||||||
RecentsItem.CONTINUE_READING,
|
|
||||||
recentItems.filter { it.mch.history.id != null }.take(
|
|
||||||
8 - nChaptersItems.mangaList.size
|
|
||||||
)
|
|
||||||
)
|
|
||||||
// TODO: Add Date Added
|
|
||||||
groupedRecentItems = listOf(cReadingItems, nChaptersItems).sortedByDescending {
|
|
||||||
it.mangaList.firstOrNull()?.mch?.history?.last_read ?: 0
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
groupedRecentItems = listOf(RecentsItem(RecentsItem.SEARCH, recentItems))
|
|
||||||
}
|
|
||||||
withContext(Dispatchers.Main) { controller.showLists(groupedRecentItems) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +174,7 @@ class RecentsPresenter(
|
|||||||
download = null
|
download = null
|
||||||
}
|
}
|
||||||
|
|
||||||
controller.showLists(groupedRecentItems)
|
controller.showLists(recentItems)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,5 +173,14 @@
|
|||||||
android:layout_height="6dp"
|
android:layout_height="6dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/bottom_line" />
|
app:layout_constraintTop_toBottomOf="@+id/bottom_line" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:background="?android:attr/divider"/>
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
34
app/src/main/res/layout/recents_footer_item.xml
Normal file
34
app/src/main/res/layout/recents_footer_item.xml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/recent_item"
|
||||||
|
android:background="?selectable_list_drawable"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
android:layout_marginBottom="12dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/arrow"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
android:textColor="?colorAccent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
tools:text="@string/view_all_updates" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/arrow"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_arrow_forward_white_24dp"
|
||||||
|
android:tint="?colorAccent"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/title"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
23
app/src/main/res/layout/recents_header_item.xml
Normal file
23
app/src/main/res/layout/recents_header_item.xml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/recent_item"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
tools:text="@string/label_recent_updates" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -21,7 +21,7 @@
|
|||||||
<string name="label_catalogues">Catalogues</string>
|
<string name="label_catalogues">Catalogues</string>
|
||||||
<string name="label_recent_updates">Recent updates</string>
|
<string name="label_recent_updates">Recent updates</string>
|
||||||
<string name="new_chapters">New chapters</string>
|
<string name="new_chapters">New chapters</string>
|
||||||
<string name="new_additions">New additions</string>
|
<string name="new_additions">Newly added</string>
|
||||||
<string name="label_selected">Selected: %1$d</string>
|
<string name="label_selected">Selected: %1$d</string>
|
||||||
<string name="label_migration">Source migration</string>
|
<string name="label_migration">Source migration</string>
|
||||||
<string name="label_extensions">Extensions</string>
|
<string name="label_extensions">Extensions</string>
|
||||||
@ -761,7 +761,9 @@
|
|||||||
<string name="previously_read_chapter">Previously read Chapter %1$s</string>
|
<string name="previously_read_chapter">Previously read Chapter %1$s</string>
|
||||||
<string name="last_read_chapter_x">Last read Chapter %1$s</string>
|
<string name="last_read_chapter_x">Last read Chapter %1$s</string>
|
||||||
<string name="last_read_x">Last read %1$s</string>
|
<string name="last_read_x">Last read %1$s</string>
|
||||||
<string name="uploaded_x">Uploaded %1$s</string>
|
<string name="read_x">Read %1$s</string>
|
||||||
|
<string name="updated_x">Updated %1$s</string>
|
||||||
|
<string name="added_x">Added %1$s</string>
|
||||||
<string name="view_history">View history</string>
|
<string name="view_history">View history</string>
|
||||||
<string name="view_all_updates">View all updates</string>
|
<string name="view_all_updates">View all updates</string>
|
||||||
<string name="marked_as_read">Marked as read</string>
|
<string name="marked_as_read">Marked as read</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user