Chapter cleanup (#210)

* clean up chapterholder and reader chapter item to use a helper class for colors

* update gradle.properties to cache and have larger memory

* fixed bug causing some chapters that were swiped to crash app

* add relative date to chapter util
reference colors instead of attrs in color.xml
add a bookmarked and read alpha

Co-authored-by: Jays2Kings <jays@outlook.com>
This commit is contained in:
Carlos 2020-04-23 21:57:04 -04:00 committed by GitHub
parent d4449c1d03
commit 1519395267
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 135 additions and 86 deletions

View File

@ -8,7 +8,7 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.manga.chapter.BaseChapterAdapter import eu.kanade.tachiyomi.ui.manga.chapter.BaseChapterAdapter
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.chapter.ChapterUtil
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.text.DecimalFormat import java.text.DecimalFormat
import java.text.DecimalFormatSymbols import java.text.DecimalFormatSymbols
@ -25,11 +25,13 @@ class MangaDetailsAdapter(
val delegate: MangaDetailsInterface = controller val delegate: MangaDetailsInterface = controller
val presenter = controller.presenter val presenter = controller.presenter
val readColor = context.getResourceColor(android.R.attr.textColorHint) val readColor = ChapterUtil.readColor(context)
val unreadColor = context.getResourceColor(android.R.attr.textColorPrimary) val unreadColor = ChapterUtil.unreadColor(context)
val bookmarkedColor = context.getResourceColor(R.attr.colorAccent) val bookmarkedColor = ChapterUtil.bookmarkedColor(context)
val bookmarkedAndReadColor = ChapterUtil.bookmarkedAndReadColor(context)
val decimalFormat = DecimalFormat("#.###", DecimalFormatSymbols() val decimalFormat = DecimalFormat("#.###", DecimalFormatSymbols()
.apply { decimalSeparator = '.' }) .apply { decimalSeparator = '.' })

View File

@ -7,6 +7,7 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
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.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.util.system.HashCode
class MangaHeaderItem(val manga: Manga, var startExpanded: Boolean) : class MangaHeaderItem(val manga: Manga, var startExpanded: Boolean) :
AbstractFlexibleItem<MangaHeaderHolder>() { AbstractFlexibleItem<MangaHeaderHolder>() {
@ -46,6 +47,6 @@ class MangaHeaderItem(val manga: Manga, var startExpanded: Boolean) :
} }
override fun hashCode(): Int { override fun hashCode(): Int {
return manga.id!!.hashCode() return HashCode.generate(manga.id, manga.title)
} }
} }

View File

@ -5,6 +5,7 @@ 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
import eu.kanade.tachiyomi.util.system.HashCode
abstract class BaseChapterItem<T : BaseChapterHolder, H : AbstractHeaderItem<*>>( abstract class BaseChapterItem<T : BaseChapterHolder, H : AbstractHeaderItem<*>>(
val chapter: val chapter:
@ -40,6 +41,6 @@ Chapter,
} }
override fun hashCode(): Int { override fun hashCode(): Int {
return (chapter.id ?: 0L).hashCode() return HashCode.generate(chapter.id ?: 0L, chapter.name)
} }
} }

View File

@ -1,18 +1,17 @@
package eu.kanade.tachiyomi.ui.manga.chapter package eu.kanade.tachiyomi.ui.manga.chapter
import android.text.format.DateUtils
import android.view.View import android.view.View
import androidx.core.content.ContextCompat
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.ui.manga.MangaDetailsAdapter import eu.kanade.tachiyomi.ui.manga.MangaDetailsAdapter
import eu.kanade.tachiyomi.util.chapter.ChapterUtil
import eu.kanade.tachiyomi.util.system.contextCompatDrawable
import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.view.gone
import eu.kanade.tachiyomi.util.view.visibleIf import eu.kanade.tachiyomi.util.view.visibleIf
import kotlinx.android.synthetic.main.chapters_item.* import kotlinx.android.synthetic.main.chapters_item.*
import kotlinx.android.synthetic.main.download_button.* import kotlinx.android.synthetic.main.download_button.*
import java.util.Date
class ChapterHolder( class ChapterHolder(
view: View, view: View,
@ -20,6 +19,7 @@ class ChapterHolder(
) : BaseChapterHolder(view, adapter) { ) : BaseChapterHolder(view, adapter) {
private var localSource = false private var localSource = false
init { init {
download_button.setOnLongClickListener { download_button.setOnLongClickListener {
adapter.delegate.startDownloadRange(adapterPosition) adapter.delegate.startDownloadRange(adapterPosition)
@ -39,33 +39,32 @@ class ChapterHolder(
} }
localSource = manga.source == LocalSource.ID localSource = manga.source == LocalSource.ID
download_button.visibleIf(!localSource) download_button.visibleIf(!localSource && !isLocked)
if (isLocked) download_button.gone() var chapterColor = when {
isLocked -> adapter.unreadColor
chapter.bookmark && chapter.read -> adapter.bookmarkedAndReadColor
chapter.bookmark -> adapter.bookmarkedColor
chapter.read -> adapter.readColor
else -> adapter.unreadColor
}
// Set correct text color // Set correct text color
chapter_title.setTextColor( chapter_title.setTextColor(chapterColor)
if (chapter.read && !isLocked) adapter.readColor else adapter.unreadColor
)
if (chapter.bookmark && !isLocked) chapter_title.setTextColor(adapter.bookmarkedColor)
val statuses = mutableListOf<String>() val statuses = mutableListOf<String>()
if (chapter.date_upload > 0) { ChapterUtil.relativeDate(chapter)?.let { statuses.add(it) }
statuses.add(
DateUtils.getRelativeTimeSpanString(
chapter.date_upload, Date().time, DateUtils.HOUR_IN_MILLIS
).toString()
)
}
if (!chapter.read && chapter.last_page_read > 0 && chapter.pages_left > 0 && !isLocked) { val showPagesLeft = !chapter.read && chapter.last_page_read > 0 && !isLocked
if (showPagesLeft && chapter.pages_left > 0) {
statuses.add( statuses.add(
itemView.resources.getQuantityString( itemView.resources.getQuantityString(
R.plurals.pages_left, chapter.pages_left, chapter.pages_left R.plurals.pages_left, chapter.pages_left, chapter.pages_left
) )
) )
} else if (!chapter.read && chapter.last_page_read > 0 && !isLocked) { } else if (showPagesLeft) {
statuses.add( statuses.add(
itemView.context.getString( itemView.context.getString(
R.string.page_, chapter.last_page_read + 1 R.string.page_, chapter.last_page_read + 1
@ -73,31 +72,36 @@ class ChapterHolder(
) )
} }
if (!chapter.scanlator.isNullOrBlank()) { chapter.scanlator?.isNotBlank()?.let { statuses.add(chapter.scanlator!!) }
statuses.add(chapter.scanlator!!)
}
if (front_view.translationX == 0f) { if (front_view.translationX == 0f) {
read.setImageDrawable( read.setImageDrawable(
ContextCompat.getDrawable( read.context.contextCompatDrawable(
read.context, if (item.read) R.drawable.ic_eye_off_24dp when (item.read) {
else R.drawable.ic_eye_24dp true -> R.drawable.ic_eye_off_24dp
false -> R.drawable.ic_eye_24dp
}
) )
) )
bookmark.setImageDrawable( bookmark.setImageDrawable(
ContextCompat.getDrawable( read.context.contextCompatDrawable(
read.context, if (item.bookmark) R.drawable.ic_bookmark_off_24dp when (item.bookmark) {
else R.drawable.ic_bookmark_24dp true -> R.drawable.ic_bookmark_off_24dp
false -> R.drawable.ic_bookmark_24dp
}
) )
) )
} }
chapter_scanlator.setTextColor(if (chapter.read) adapter.readColor else adapter.unreadColor) // this will color the scanlator the same bookmarks
chapter_scanlator.setTextColor(chapterColor)
chapter_scanlator.text = statuses.joinToString("") chapter_scanlator.text = statuses.joinToString("")
notifyStatus(
if (adapter.isSelected(adapterPosition)) Download.CHECKED else item.status, val status = when (adapter.isSelected(adapterPosition)) {
item.isLocked, true -> Download.CHECKED
item.progress false -> item.status
) }
notifyStatus(status, item.isLocked, item.progress)
resetFrontView() resetFrontView()
} }

View File

@ -1,39 +1,33 @@
package eu.kanade.tachiyomi.ui.reader package eu.kanade.tachiyomi.ui.reader
import android.content.res.ColorStateList
import android.graphics.Typeface import android.graphics.Typeface
import android.text.format.DateUtils
import android.view.View import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.core.graphics.drawable.DrawableCompat
import com.mikepenz.fastadapter.FastAdapter import com.mikepenz.fastadapter.FastAdapter
import com.mikepenz.fastadapter.items.AbstractItem import com.mikepenz.fastadapter.items.AbstractItem
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.util.chapter.ChapterUtil
import eu.kanade.tachiyomi.util.system.contextCompatDrawable import eu.kanade.tachiyomi.util.system.contextCompatDrawable
import eu.kanade.tachiyomi.util.system.getResourceColor
import java.text.DecimalFormat import java.text.DecimalFormat
import java.text.DecimalFormatSymbols import java.text.DecimalFormatSymbols
import java.util.Date
class ReaderChapterItem(val chapter: Chapter, val manga: Manga, val isCurrent: Boolean) : class ReaderChapterItem(val chapter: Chapter, val manga: Manga, val isCurrent: Boolean) :
AbstractItem<ReaderChapterItem.ViewHolder> AbstractItem<ReaderChapterItem.ViewHolder>
() { () {
var name: String? = null
var description: String? = null
val decimalFormat = val decimalFormat =
DecimalFormat("#.###", DecimalFormatSymbols().apply { decimalSeparator = '.' }) DecimalFormat("#.###", DecimalFormatSymbols().apply { decimalSeparator = '.' })
/** defines the type defining this item. must be unique. preferably an id */ /** defines the type defining this item. must be unique. preferably an id */
override val type: Int override val type: Int = R.id.reader_chapter_layout
get() = R.id.reader_chapter_layout
/** defines the layout which will be used for this item in the list */ /** defines the layout which will be used for this item in the list */
override val layoutRes: Int override val layoutRes: Int = R.layout.reader_chapter_item
get() = R.layout.reader_chapter_item
override var identifier: Long override var identifier: Long
get() = chapter.id!! get() = chapter.id!!
@ -49,9 +43,10 @@ class ReaderChapterItem(val chapter: Chapter, val manga: Manga, val isCurrent: B
var bookmarkButton: FrameLayout = view.findViewById(R.id.bookmark_layout) var bookmarkButton: FrameLayout = view.findViewById(R.id.bookmark_layout)
var bookmarkImage: ImageView = view.findViewById(R.id.bookmark_image) var bookmarkImage: ImageView = view.findViewById(R.id.bookmark_image)
private var readColor = view.context.getResourceColor(android.R.attr.textColorHint) private var readColor = ChapterUtil.readColor(view.context)
private var unreadColor = view.context.getResourceColor(android.R.attr.textColorPrimary) private var unreadColor = ChapterUtil.unreadColor(view.context)
private var activeColor = view.context.getResourceColor(android.R.attr.colorAccent) private var bookmarkColor = ChapterUtil.bookmarkedColor(view.context)
private var bookmarkReadColor = ChapterUtil.bookmarkedAndReadColor(view.context)
private var unbookmark = view.context.contextCompatDrawable(R.drawable.ic_bookmark_border_24dp) private var unbookmark = view.context.contextCompatDrawable(R.drawable.ic_bookmark_border_24dp)
private var bookmark = view.context.contextCompatDrawable(R.drawable.ic_bookmark_24dp) private var bookmark = view.context.contextCompatDrawable(R.drawable.ic_bookmark_24dp)
@ -59,6 +54,15 @@ class ReaderChapterItem(val chapter: Chapter, val manga: Manga, val isCurrent: B
override fun bindView(item: ReaderChapterItem, payloads: List<Any>) { override fun bindView(item: ReaderChapterItem, payloads: List<Any>) {
val chapter = item.chapter val chapter = item.chapter
val manga = item.manga val manga = item.manga
var chapterColor = when {
chapter.bookmark && chapter.read -> bookmarkReadColor
chapter.bookmark -> bookmarkColor
chapter.read && !item.isCurrent -> readColor
else -> unreadColor
}
chapterTitle.setTextColor(chapterColor)
chapterTitle.text = when (manga.displayMode) { chapterTitle.text = when (manga.displayMode) {
Manga.DISPLAY_NUMBER -> { Manga.DISPLAY_NUMBER -> {
val number = item.decimalFormat.format(chapter.chapter_number.toDouble()) val number = item.decimalFormat.format(chapter.chapter_number.toDouble())
@ -66,47 +70,35 @@ class ReaderChapterItem(val chapter: Chapter, val manga: Manga, val isCurrent: B
} }
else -> chapter.name else -> chapter.name
} }
val statuses = mutableListOf<String>() val statuses = mutableListOf<String>()
if (chapter.date_upload > 0) { ChapterUtil.relativeDate(chapter)?.let { statuses.add(it) }
statuses.add( chapter.scanlator?.isNotBlank()?.let { statuses.add(chapter.scanlator!!) }
DateUtils.getRelativeTimeSpanString(
chapter.date_upload, Date().time, DateUtils.HOUR_IN_MILLIS
).toString()
)
}
if (!chapter.scanlator.isNullOrBlank()) {
statuses.add(chapter.scanlator!!)
}
chapterTitle.setTextColor(
when {
chapter.bookmark -> activeColor
chapter.read && !item.isCurrent -> readColor
else -> unreadColor
}
)
if (item.isCurrent) { if (item.isCurrent) {
chapterTitle.setTypeface(null, Typeface.BOLD) chapterTitle.setTypeface(null, Typeface.BOLD_ITALIC)
chapterSubtitle.setTypeface(null, Typeface.BOLD) chapterSubtitle.setTypeface(null, Typeface.BOLD_ITALIC)
} else { } else {
chapterTitle.setTypeface(null, Typeface.NORMAL) chapterTitle.setTypeface(null, Typeface.NORMAL)
chapterSubtitle.setTypeface(null, Typeface.NORMAL) chapterSubtitle.setTypeface(null, Typeface.NORMAL)
} }
chapterSubtitle.setTextColor( // match color of the chapter title
when { chapterSubtitle.setTextColor(chapterColor)
chapter.read -> readColor
else -> unreadColor bookmarkImage.setImageDrawable(when (chapter.bookmark) {
true -> bookmark
false -> unbookmark
})
val drawableColor = when {
chapter.bookmark && chapter.read -> bookmarkReadColor
chapter.bookmark -> bookmarkColor
else -> readColor
} }
)
bookmarkImage.setImageDrawable(if (chapter.bookmark) DrawableCompat.setTint(bookmarkImage.drawable, drawableColor)
bookmark
else unbookmark)
bookmarkImage.imageTintList = ColorStateList.valueOf(if (chapter.bookmark)
activeColor
else readColor)
chapterSubtitle.text = statuses.joinToString("") chapterSubtitle.text = statuses.joinToString("")
} }

View File

@ -0,0 +1,29 @@
package eu.kanade.tachiyomi.util.chapter
import android.content.Context
import android.text.format.DateUtils
import androidx.core.graphics.ColorUtils
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.util.system.contextCompatColor
import java.util.Date
class ChapterUtil {
companion object {
fun relativeDate(chapter: Chapter): String? {
return when (chapter.date_upload > 0) {
true -> DateUtils.getRelativeTimeSpanString(chapter.date_upload, Date().time, DateUtils.HOUR_IN_MILLIS).toString()
false -> null
}
}
fun readColor(context: Context): Int = context.contextCompatColor(R.color.read_chapter)
fun unreadColor(context: Context): Int = context.contextCompatColor(R.color.unread_chapter)
fun bookmarkedColor(context: Context): Int = context.contextCompatColor(R.color.bookmarked_chapter)
fun bookmarkedAndReadColor(context: Context): Int = ColorUtils.setAlphaComponent(context.contextCompatColor(R.color.bookmarked_chapter), 150)
}
}

View File

@ -0,0 +1,14 @@
package eu.kanade.tachiyomi.util.system
/**Generate a unique hash code*/
class HashCode {
companion object {
fun <T> generate(vararg thingsToHash: T): Int {
var hash = 17
for (t in thingsToHash) {
hash = hash * 31 + t.hashCode()
}
return hash
}
}
}

View File

@ -16,6 +16,11 @@
<color name="actionModeShadow">@color/md_black_1000_38</color> <color name="actionModeShadow">@color/md_black_1000_38</color>
<color name="gray_button">#404040</color> <color name="gray_button">#404040</color>
<color name="read_chapter">@color/textColorHint</color>
<color name="unread_chapter">@color/textColorPrimary</color>
<color name="bookmarked_chapter">@color/colorAccent</color>
<color name="active_chapter">@color/colorAccent</color>
<color name="unread_badge">@color/colorAccent</color> <color name="unread_badge">@color/colorAccent</color>
<color name="unread_badge_text">@color/md_white_1000</color> <color name="unread_badge_text">@color/md_white_1000</color>
<color name="download_badge">@color/pale_green</color> <color name="download_badge">@color/pale_green</color>
@ -23,7 +28,6 @@
<color name="total_badge">@color/material_deep_purple_500</color> <color name="total_badge">@color/material_deep_purple_500</color>
<color name="total_badge_text">@color/md_white_1000</color> <color name="total_badge_text">@color/md_white_1000</color>
<color name="colorAmoledPrimary">@color/md_black_1000</color> <color name="colorAmoledPrimary">@color/md_black_1000</color>
<color name="textColorPrimary">@color/md_black_1000_87</color> <color name="textColorPrimary">@color/md_black_1000_87</color>

View File

@ -20,3 +20,5 @@
# AndroidX support # AndroidX support
android.enableJetifier=true android.enableJetifier=true
android.useAndroidX=true android.useAndroidX=true
org.gradle.jvmargs=-Xmx2048M
org.gradle.caching=true