Using badges for downloads/unread again

Added compact grid option in sort sheet, closer to the old style
This commit is contained in:
Jay 2020-02-15 02:48:47 -08:00
parent dea8e18eda
commit 214008ac5c
28 changed files with 463 additions and 257 deletions

View File

@ -111,9 +111,7 @@ object PreferenceKeys {
const val downloadNewCategories = "download_new_categories"
const val libraryAsList = "pref_display_library_as_list"
const val libraryGridFixed = "library_grid_fixes"
const val libraryLayout = "pref_display_library_layout"
const val lang = "app_language"

View File

@ -171,9 +171,7 @@ class PreferencesHelper(val context: Context) {
fun libraryUpdatePrioritization() = rxPrefs.getInteger(Keys.libraryUpdatePrioritization, 0)
fun libraryAsList() = rxPrefs.getBoolean(Keys.libraryAsList, false)
fun libraryGridFixedSize() = rxPrefs.getBoolean(Keys.libraryGridFixed, false)
fun libraryLayout() = rxPrefs.getInteger(Keys.libraryLayout, 1)
fun downloadBadge() = rxPrefs.getBoolean(Keys.downloadBadge, false)

View File

@ -5,14 +5,15 @@ import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.signature.ObjectKey
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaImpl
import eu.kanade.tachiyomi.data.glide.GlideApp
import eu.kanade.tachiyomi.ui.library.LibraryCategoryAdapter
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.view.gone
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
import eu.kanade.tachiyomi.widget.StateImageViewTarget
import kotlinx.android.synthetic.main.catalogue_grid_item.*
@ -38,10 +39,15 @@ class CatalogueGridHolder(
*/
override fun onSetValues(manga: Manga) {
// Update the title of the manga.
title.text = manga.currentTitle()
subtitle.gone()
title.gone()
compact_title.text = manga.currentTitle()
bookmark_text.visibility = if (manga.favorite) View.VISIBLE else View.GONE
badge_view.visibility = if (manga.favorite) View.VISIBLE else View.GONE
unread_angle.visibility = View.GONE
unread_text.updatePaddingRelative(start = 5.dpToPx)
unread_text.visibility = if (manga.favorite) View.VISIBLE else View.GONE
unread_text.text = itemView.resources.getText(R.string.in_library)
// Update the cover.
setImage(manga)

View File

@ -4,6 +4,7 @@ import android.view.View
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.FrameLayout
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
import com.f2prateek.rx.preferences.Preference
import eu.davidea.flexibleadapter.FlexibleAdapter
@ -12,6 +13,7 @@ import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
import kotlinx.android.synthetic.main.catalogue_grid_item.view.*
@ -30,7 +32,12 @@ class CatalogueItem(val manga: Manga, private val catalogueAsList: Preference<Bo
return if (parent is AutofitRecyclerView) {
view.apply {
val coverHeight = (parent.itemWidth / 3 * 4f).toInt()
constraint_layout.layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
constraint_layout.layoutParams = FrameLayout.LayoutParams(MATCH_PARENT,
WRAP_CONTENT)
val marginParams = card.layoutParams as ConstraintLayout.LayoutParams
marginParams.bottomMargin = 10.dpToPx
card.layoutParams = marginParams
constraint_layout.minHeight = 0
cover_thumbnail.adjustViewBounds = false
cover_thumbnail.layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, coverHeight)
}

View File

@ -8,6 +8,7 @@ import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.SelectableAdapter
import eu.kanade.tachiyomi.R
@ -81,7 +82,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
fun onCreate(controller: LibraryController) {
this.controller = controller
recycler = if (preferences.libraryAsList().getOrDefault()) {
recycler = if (preferences.libraryLayout().getOrDefault() == 0) {
(swipe_refresh.inflate(R.layout.library_list_recycler) as RecyclerView).apply {
layoutManager = LinearLayoutManager(context)
}
@ -97,7 +98,6 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
recycler.adapter = adapter
swipe_refresh.addView(recycler)
adapter.fastScroller = fast_scroller
// recycler.addOnScrollListener(adapter.preloader())
if (::category.isInitialized) {
val mangaForCategory = controller.presenter.getMangaInCategory(category.id)
@ -336,7 +336,8 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
override fun startReading(position: Int) {
val manga = adapter.getItem(position)?.manga ?: return
controller.startReading(manga)
if (adapter.mode == SelectableAdapter.Mode.MULTI) toggleSelection(position)
else controller.startReading(manga)
}
private fun saveDragSort() {

View File

@ -378,11 +378,13 @@ class LibraryController(
* Called when a filter is changed.
*/
private fun onFilterChanged() {
activity?.invalidateOptionsMenu()
presenter.requestFilterUpdate()
destroyActionModeIfNeeded()
}
private fun onRefresh() {
activity?.invalidateOptionsMenu()
presenter.getLibrary()
destroyActionModeIfNeeded()
}

View File

@ -1,7 +1,8 @@
package eu.kanade.tachiyomi.ui.library
import android.view.View
import androidx.core.content.ContextCompat
import android.view.ViewTreeObserver
import androidx.constraintlayout.widget.ConstraintLayout
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.signature.ObjectKey
@ -9,9 +10,11 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.MangaImpl
import eu.kanade.tachiyomi.data.glide.GlideApp
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.view.gone
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
import eu.kanade.tachiyomi.util.view.visible
import kotlinx.android.synthetic.main.catalogue_grid_item.*
import kotlinx.android.synthetic.main.catalogue_grid_item.view.*
/**
* Class used to hold the displayed data of a manga in the library, like the cover or the title.
@ -36,47 +39,82 @@ class LibraryGridHolder(
* @param item the manga item to bind.
*/
override fun onSetValues(item: LibraryItem) {
// Update the title of the manga.
// Update the title and subtitle of the manga.
title.text = item.manga.currentTitle()
subtitle.text = item.manga.originalAuthor()?.trim()
if (!fixedSize) {
title.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean {
title.viewTreeObserver.removeOnPreDrawListener(this)
// Drawing happens after layout so we can assume getLineCount() returns the correct value
val marginParams = title.layoutParams as ConstraintLayout.LayoutParams
if (title.lineCount == 2) {
// Do whatever you want in case text view has more than 2 lines
subtitle.gone()
marginParams.bottomMargin = 10.dpToPx
marginParams.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID
} else {
subtitle.visible()
marginParams.bottomMargin = 0
marginParams.bottomToBottom = -1
}
title.layoutParams = marginParams
return true
}
})
}
compact_title.text = title.text
// Update the unread count and its visibility.
val unread = item.manga.unread
// Update the subtitle of the manga with artist or the unread count
with(subtitle) {
text = when {
item.manga.unread > 0 -> when (item.unreadType) {
1 -> view.resources.getQuantityString(R.plurals.unread_count, unread, unread)
0 -> view.resources.getString(R.string.new_chapter)
else -> item.manga.originalAuthor()
}
else -> item.manga.originalAuthor()
}
setTextColor(
view.context.getResourceColor(
if (item.manga.unread > 0 && item.unreadType > -1) android.R.attr.colorAccent
else android.R.attr.textColorSecondary
)
)
with(unread_text) {
text = unread.toString()
visibility = if (unread > 0) View.VISIBLE else View.GONE
}
play_layout.visibility = if (unread > 0) View.VISIBLE else View.GONE
play_layout.setOnClickListener { playButtonClicked() }
// Update the download count or local status and its visibility.
with(download_text) {
visibility = if (item.downloadCount > -1 && (item.downloadCount > 0 || item.manga
.source == LocalSource.ID))
.source == LocalSource.ID))
View.VISIBLE else View.GONE
text = if (item.manga.source == LocalSource.ID)
itemView.resources.getString(R.string.local_source_badge)
else item.downloadCount.toString()
backgroundTintList = ContextCompat.getColorStateList(itemView.context,
if (item.manga.source == LocalSource.ID) R.color.md_teal_500
else R.color.md_red_500)
else item.downloadCount.toString()
}
// Show the bade card if unread or downloads exists
badge_view.visibility = if (download_text.visibility == View.VISIBLE || unread_text
.visibility == View.VISIBLE) View.VISIBLE else View.GONE
// Show the angles divider if both unread and downloads exists
unread_angle.visibility = if (download_text.visibility == View.VISIBLE && unread_text
.visibility == View.VISIBLE) View.VISIBLE else View.GONE
if (unread_angle.visibility == View.VISIBLE) {
download_text.updatePaddingRelative(end = 8.dpToPx)
unread_text.updatePaddingRelative(start = 2.dpToPx)
}
else {
download_text.updatePaddingRelative(end = 5.dpToPx)
unread_text.updatePaddingRelative(start = 5.dpToPx)
}
play_layout.visibility = if (unread > 0) View.VISIBLE else View.GONE
play_layout.setOnClickListener { playButtonClicked() }
if (fixedSize) {
title.gone()
subtitle.gone()
}
else {
compact_title.gone()
gradient.gone()
}
// Update the cover.
if (item.manga.thumbnail_url == null) Glide.with(view.context).clear(cover_thumbnail)
if (item.manga.thumbnail_url == null) GlideApp.with(view.context).clear(cover_thumbnail)
else {
val id = item.manga.id ?: return
var glide = GlideApp.with(view.context).load(item.manga)
@ -94,13 +132,15 @@ class LibraryGridHolder(
override fun onActionStateChanged(position: Int, actionState: Int) {
super.onActionStateChanged(position, actionState)
if (actionState == 2) {
view.card.isDragged = true
card.isDragged = true
badge_view.isDragged = true
}
}
override fun onItemReleased(position: Int) {
super.onItemReleased(position)
view.card.isDragged = false
card.isDragged = false
badge_view.isDragged = false
}
}

View File

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.ui.library
import android.view.View
import androidx.core.content.ContextCompat
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import androidx.recyclerview.widget.RecyclerView
@ -37,4 +38,7 @@ abstract class LibraryHolder(
(adapter as? LibraryCategoryAdapter)?.onItemReleaseListener?.onItemReleased(position)
}
protected fun convertColor(color: Int):String {
return Integer.toHexString(color and 0x00ffffff)
}
}

View File

@ -4,6 +4,8 @@ import android.annotation.SuppressLint
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.f2prateek.rx.preferences.Preference
import eu.davidea.flexibleadapter.FlexibleAdapter
@ -14,19 +16,19 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.LibraryManga
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
import kotlinx.android.synthetic.main.catalogue_grid_item.view.*
import uy.kohesive.injekt.injectLazy
class LibraryItem(val manga: LibraryManga, private val libraryAsList: Preference<Boolean>,
private val fixedGrid: Preference<Boolean>) :
class LibraryItem(val manga: LibraryManga, private val libraryLayout: Preference<Int>) :
AbstractFlexibleItem<LibraryHolder>(), IFilterable<String> {
var downloadCount = -1
var unreadType = 1
override fun getLayoutRes(): Int {
return if (libraryAsList.getOrDefault())
return if (libraryLayout.getOrDefault() == 0)
R.layout.catalogue_list_item
else
R.layout.catalogue_grid_item
@ -35,7 +37,7 @@ class LibraryItem(val manga: LibraryManga, private val libraryAsList: Preference
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): LibraryHolder {
val parent = adapter.recyclerView
return if (parent is AutofitRecyclerView) {
val fixedSize = fixedGrid.getOrDefault()
val fixedSize = libraryLayout.getOrDefault() == 1
view.apply {
val coverHeight = (parent.itemWidth / 3f * 4f).toInt()
if (fixedSize) {
@ -43,12 +45,18 @@ class LibraryItem(val manga: LibraryManga, private val libraryAsList: Preference
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
val marginParams = card.layoutParams as ConstraintLayout.LayoutParams
marginParams.bottomMargin = 10.dpToPx
card.layoutParams = marginParams
constraint_layout.minHeight = 0
cover_thumbnail.adjustViewBounds = false
cover_thumbnail.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, coverHeight)
}
else {
constraint_layout.minHeight = coverHeight
cover_thumbnail.maxHeight = (parent.itemWidth / 3f * 6f).toInt()
constraint_layout.background = ContextCompat.getDrawable(context,
R.drawable.library_item_selector)
}
}
LibraryGridHolder(view, adapter as LibraryCategoryAdapter, parent.itemWidth, fixedSize)

View File

@ -12,9 +12,18 @@ import kotlinx.android.synthetic.main.catalogue_list_item.*
import com.bumptech.glide.signature.ObjectKey
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.MangaImpl
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
import kotlinx.android.synthetic.main.catalogue_grid_item.*
import kotlinx.android.synthetic.main.catalogue_list_item.badge_view
import kotlinx.android.synthetic.main.catalogue_list_item.cover_thumbnail
import kotlinx.android.synthetic.main.catalogue_list_item.download_text
import kotlinx.android.synthetic.main.catalogue_list_item.play_layout
import kotlinx.android.synthetic.main.catalogue_list_item.subtitle
import kotlinx.android.synthetic.main.catalogue_list_item.title
import kotlinx.android.synthetic.main.catalogue_list_item.unread_angle
import kotlinx.android.synthetic.main.catalogue_list_item.unread_text
import kotlinx.android.synthetic.main.catalogue_list_item.view.*
/**
@ -45,25 +54,39 @@ class LibraryListHolder(
// Update the unread count and its visibility.
val unread = item.manga.unread
// Update the subtitle of the manga with artist or the unread count and download count
"<font color=#cc0029>First Color</font>"
val subtitleText = when {
unread > 0 -> when (item.unreadType) {
1 -> view.resources.getQuantityString(R.plurals.unread_count, unread, unread)
0 -> view.resources.getString(R.string.new_chapter)
else -> item.manga.originalAuthor()
}
else -> item.manga.originalAuthor()
with(unread_text) {
text = unread.toString()
visibility = if (unread > 0) View.VISIBLE else View.GONE
}
// Update the download count or local status and its visibility.
val downloadText =
if (item.manga.source == LocalSource.ID)
itemView.resources.getString(R.string.local_source_badge)
else view.resources.getQuantityString(R.plurals.download_count,
item.downloadCount, item.downloadCount)
// Combine the 2 above using html
val subText = if (item.downloadCount > 0 || item.manga.source == LocalSource.ID) {
// Update the download count or local status and its visibility.
with(download_text) {
visibility = if (item.downloadCount > -1 && (item.downloadCount > 0 || item.manga
.source == LocalSource.ID))
View.VISIBLE else View.GONE
text = if (item.manga.source == LocalSource.ID)
itemView.resources.getString(R.string.local_source_badge)
else item.downloadCount.toString()
}
// Show the bade card if unread or downloads exists
badge_view.visibility = if (download_text.visibility == View.VISIBLE || unread_text
.visibility == View.VISIBLE) View.VISIBLE else View.GONE
// Show the angles divider if both unread and downloads exists
unread_angle.visibility = if (download_text.visibility == View.VISIBLE && unread_text
.visibility == View.VISIBLE) View.VISIBLE else View.GONE
if (unread_angle.visibility == View.VISIBLE) {
download_text.updatePaddingRelative(end = 8.dpToPx)
unread_text.updatePaddingRelative(start = 2.dpToPx)
}
else {
download_text.updatePaddingRelative(end = 5.dpToPx)
unread_text.updatePaddingRelative(start = 5.dpToPx)
}
/* if (item.downloadCount > 0 || item.manga.source == LocalSource.ID) {
val downloadColor = convertColor(ContextCompat.getColor(itemView.context,
if (item.manga.source == LocalSource.ID) R.color.md_teal_500
else R.color.md_red_500))
@ -76,21 +99,14 @@ class LibraryListHolder(
subtitleText
else -> "<font color=#$downloadColor>$downloadText</font>"
}
}
else {
}*/
/*else {
subtitleText
}
with(subtitle) {
text = HtmlCompat.fromHtml(subText ?: "", HtmlCompat.FROM_HTML_MODE_LEGACY)
setTextColor(
view.context.getResourceColor(
if (item.manga.unread > 0 && item.unreadType > -1 && item.downloadCount <= 0
&& item.manga.source != LocalSource.ID)
android.R.attr.colorAccent
else android.R.attr.textColorSecondary
)
)
}
}*/
subtitle.text = item.manga.originalAuthor()?.trim()
subtitle.visibility = if (!item.manga.originalAuthor().isNullOrBlank()) View.VISIBLE
else View.GONE
play_layout.visibility = if (unread > 0) View.VISIBLE else View.GONE
play_layout.setOnClickListener { playButtonClicked() }
@ -108,10 +124,6 @@ class LibraryListHolder(
}
}
private fun convertColor(color: Int):String {
return Integer.toHexString(color and 0x00ffffff)
}
private fun playButtonClicked() {
adapter.libraryListener.startReading(adapterPosition)
}

View File

@ -417,15 +417,14 @@ class LibraryPresenter(
*/
private fun getLibraryFromDB(): Library {
val categories = db.getCategories().executeAsBlocking().toMutableList()
val libraryAsList = preferences.libraryAsList()
val fixedGrid = preferences.libraryGridFixedSize()
val libraryLayout = preferences.libraryLayout()
val showCategories = !preferences.hideCategories().getOrDefault()
val unreadBadgeType = preferences.unreadBadgeType().getOrDefault()
var libraryManga = db.getLibraryMangas().executeAsBlocking()
if (!showCategories)
libraryManga = libraryManga.distinctBy { it.id }
val libraryMap = libraryManga.map { manga ->
LibraryItem(manga, libraryAsList, fixedGrid).apply { unreadType = unreadBadgeType }
LibraryItem(manga, libraryLayout).apply { unreadType = unreadBadgeType }
}.groupBy {
if (showCategories) it.manga.category else 0
}

View File

@ -12,6 +12,7 @@ import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.RadioButton
import android.widget.RadioGroup
import android.widget.Spinner
import androidx.appcompat.view.menu.MenuBuilder
import androidx.appcompat.widget.PopupMenu
import androidx.core.content.ContextCompat
@ -34,6 +35,7 @@ import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.updatePadding
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
import eu.kanade.tachiyomi.util.view.visible
import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener
import kotlinx.android.synthetic.main.filter_bottom_sheet.view.*
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
@ -188,7 +190,7 @@ class SortFilterBottomSheet @JvmOverloads constructor(context: Context, attrs: A
showUnreadMenu()
}
display_group.bindToPreference(preferences.libraryAsList())
display_spinner.bindToPreference(preferences.libraryLayout())
}
override fun onSaveInstanceState(): Parcelable? {
@ -612,19 +614,16 @@ class SortFilterBottomSheet @JvmOverloads constructor(context: Context, attrs: A
}
/**
* Binds a radio group with a boolean preference.
* Binds a Spinner with a boolean preference.
*/
private fun RadioGroup.bindToPreference(pref: Preference<Boolean>) {
(getChildAt(pref.getOrDefault().toInt()) as RadioButton).isChecked = true
setOnCheckedChangeListener { _, value ->
val index = indexOfChild(findViewById(value))
pref.set(index == 1)
private fun Spinner.bindToPreference(pref: Preference<Int>) {
onItemSelectedListener = IgnoreFirstSpinnerListener { position ->
pref.set(position)
onGroupClicked(ACTION_DISPLAY)
}
setSelection(pref.getOrDefault(), false)
}
private fun Boolean.toInt() = if (this) 1 else 0
private fun tintVector(resId: Int): Drawable? {
return ContextCompat.getDrawable(context, resId)?.mutate()?.apply {
setTint(context.getResourceColor(android.R.attr.colorAccent))

View File

@ -52,13 +52,6 @@ class SettingsLibraryController : SettingsController() {
}
}
switchPreference {
key = Keys.libraryGridFixed
titleRes = R.string.pref_fixed_grid
summaryRes = R.string.pref_fixed_grid_summary
defaultValue = false
}
switchPreference {
key = Keys.removeArticles
titleRes = R.string.pref_remove_articles

View File

@ -229,7 +229,6 @@ fun Controller.setOnQueryTextChangeListener(searchView: SearchView, f: (text: St
})
}
@RequiresApi(17)
inline fun View.updatePaddingRelative(
@Px start: Int = paddingStart,
@Px top: Int = paddingTop,

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M4,6L2,6v14c0,1.1 0.9,2 2,2h14v-2L4,20L4,6zM20,2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM19,11L9,11L9,9h10v2zM15,15L9,15v-2h6v2zM19,7L9,7L9,5h10v2z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M21,5c-1.11,-0.35 -2.33,-0.5 -3.5,-0.5 -1.95,0 -4.05,0.4 -5.5,1.5 -1.45,-1.1 -3.55,-1.5 -5.5,-1.5S2.45,4.9 1,6v14.65c0,0.25 0.25,0.5 0.5,0.5 0.1,0 0.15,-0.05 0.25,-0.05C3.1,20.45 5.05,20 6.5,20c1.95,0 4.05,0.4 5.5,1.5 1.35,-0.85 3.8,-1.5 5.5,-1.5 1.65,0 3.35,0.3 4.75,1.05 0.1,0.05 0.15,0.05 0.25,0.05 0.25,0 0.5,-0.25 0.5,-0.5L23,6c-0.6,-0.45 -1.25,-0.75 -2,-1zM21,18.5c-1.1,-0.35 -2.3,-0.5 -3.5,-0.5 -1.7,0 -4.15,0.65 -5.5,1.5L12,8c1.35,-0.85 3.8,-1.5 5.5,-1.5 1.2,0 2.4,0.15 3.5,0.5v11.5z"/>
</vector>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/fullRippleColor">
<item android:id="@android:id/mask"
android:top="4dp"
android:bottom="4dp"
android:left="2dp"
android:right="2dp">
<shape android:shape="rectangle">
<corners android:radius="4dp" />
<solid android:color="@color/fullRippleColor" />
</shape>
</item>
<item
android:top="4dp"
android:bottom="4dp"
android:left="2dp"
android:right="2dp">
<selector>
<item android:state_selected="true">
<shape android:shape="rectangle">
<corners android:radius="4dp" />
<solid android:color="@color/fullRippleColor" />
</shape>
</item>
<item android:state_activated="true">
<shape android:shape="rectangle">
<corners android:radius="4dp" />
<solid android:color="@color/fullRippleColor" />
</shape>
</item>
</selector>
</item>
</ripple>

View File

@ -2,8 +2,8 @@
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/fullRippleColor">
<item android:id="@android:id/mask"
android:top="0dp"
android:bottom="12dp"
android:top="6dp"
android:bottom="8dp"
android:left="4dp"
android:right="4dp">
<shape android:shape="rectangle">
@ -12,8 +12,8 @@
</shape>
</item>
<item
android:top="0dp"
android:bottom="12dp"
android:top="6dp"
android:bottom="8dp"
android:left="4dp"
android:right="4dp">
<selector>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:width="100dp"
android:height="100dp"
android:viewportHeight="10"
android:viewportWidth="100"
tools:background="@color/red_error">
<path
android:fillColor="@color/colorAccent"
android:pathData="M0 20 L100 0 L100 20 Z"
android:strokeColor="@color/colorAccent" />
</vector>

View File

@ -135,35 +135,21 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="14dp"
android:layout_marginEnd="6dp"
android:clickable="true"
android:focusable="true"
android:text="@string/display_as"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textColor="?android:attr/textColorPrimary"
android:textColor="?android:attr/textColorSecondary"
android:textSize="15sp"
android:textStyle="normal" />
<RadioGroup
android:id="@+id/display_group"
<androidx.appcompat.widget.AppCompatSpinner
android:id="@+id/display_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="0dp"
android:paddingEnd="8dp"
android:text="@string/action_display_grid" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:text="@string/action_display_list" />
</RadioGroup>
android:entries="@array/library_display"/>
</LinearLayout>
<LinearLayout

View File

@ -145,25 +145,11 @@
android:textStyle="normal" />
<RadioGroup
android:id="@+id/display_group"
<androidx.appcompat.widget.AppCompatSpinner
android:id="@+id/display_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="0dp"
android:paddingEnd="8dp"
android:text="@string/action_display_grid" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:text="@string/action_display_list" />
</RadioGroup>
android:entries="@array/library_display"/>
</LinearLayout>
<LinearLayout

View File

@ -12,7 +12,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@drawable/library_item_selector"
android:background="@drawable/library_compact_grid_selector"
android:minHeight="200dp"
android:orientation="vertical">
@ -21,9 +21,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginTop="2dp"
android:layout_marginStart="6dp"
android:layout_marginEnd="6dp"
android:layout_marginStart="8dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toTopOf="@+id/title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@ -46,54 +46,12 @@
tools:background="?android:attr/colorBackground"
tools:ignore="ContentDescription"
tools:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/download_text"
style="@style/TextAppearance.Regular.Caption.Light"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="-10dp"
android:layout_marginTop="-10dp"
android:background="@drawable/dialog_rounded_background"
android:backgroundTint="@color/md_red_500"
android:gravity="start|center"
android:paddingStart="14dp"
android:paddingTop="10dp"
android:paddingEnd="5dp"
android:paddingBottom="3dp"
android:textColor="@color/md_white_1000"
android:textSize="13sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="1" />
<TextView
android:id="@+id/bookmark_text"
style="@style/TextAppearance.Regular.Caption.Light"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="-10dp"
android:layout_marginTop="-10dp"
android:background="@drawable/dialog_rounded_background"
android:backgroundTint="@color/md_blue_A400_87"
android:gravity="start|center"
android:paddingStart="14dp"
android:paddingTop="10dp"
android:paddingEnd="5dp"
android:paddingBottom="3dp"
android:text="@string/in_library"
android:textColor="@color/md_white_1000"
android:textSize="13sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<FrameLayout
android:id="@+id/play_layout"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="end|bottom"
android:layout_gravity="end"
android:clickable="true"
android:focusable="true"
android:visibility="gone"
@ -103,17 +61,39 @@
android:id="@+id/play_button"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="end|bottom"
android:layout_gravity="end"
android:layout_marginTop="6dp"
android:layout_marginEnd="6dp"
android:layout_marginBottom="6dp"
android:padding="3dp"
android:background="@drawable/round_play_background"
android:contentDescription="@string/start_reading"
android:src="@drawable/ic_play_arrow_white_24dp"
android:padding="6dp"
android:src="@drawable/ic_start_reading_white_24dp"
android:tint="@android:color/white" />
</FrameLayout>
<View
android:id="@+id/gradient"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_gravity="bottom"
android:background="@drawable/gradient_shape" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/compact_title"
style="@style/TextAppearance.Regular.Body1.SemiBold"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
android:layout_marginBottom="4dp"
android:ellipsize="end"
android:maxLines="2"
android:textColor="@android:color/white"
android:textSize="13sp"
tools:text="Sample name" />
<ProgressBar
android:id="@+id/progress"
style="?android:attr/progressBarStyleSmall"
@ -128,18 +108,92 @@
</com.google.android.material.card.MaterialCardView>
<View
android:id="@+id/badge_guide"
android:layout_width="match_parent"
android:layout_height="10dp"
app:layout_constraintTop_toTopOf="@+id/card"/>
<com.google.android.material.card.MaterialCardView
android:id="@+id/badge_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="10dp"
app:cardElevation="5dp"
android:layout_marginStart="2dp"
android:layout_marginTop="5dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="@id/badge_guide"
android:visibility="gone"
tools:visibility="visible">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/download_text"
style="@style/TextAppearance.Regular.Caption.Light"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/pale_green"
android:gravity="center"
android:maxLines="1"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:textColor="@color/md_black_1000"
android:textSize="13sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="1"
tools:paddingEnd="8dp"
tools:visibility="visible" />
<ImageView
android:id="@+id/unread_angle"
android:layout_width="10dp"
android:scaleType="fitXY"
android:layout_height="0dp"
android:src="@drawable/unread_angled_badge"
app:layout_constraintBottom_toBottomOf="@+id/unread_text"
app:layout_constraintEnd_toStartOf="@id/unread_text"
app:layout_constraintTop_toTopOf="@+id/unread_text" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/unread_text"
style="@style/TextAppearance.Regular.Caption.Light"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/colorAccent"
android:gravity="center"
android:maxLines="1"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:textColor="@color/md_white_1000"
android:textSize="13sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/download_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/download_text"
app:layout_constraintTop_toTopOf="@+id/download_text"
tools:text="20"
tools:visibility="visible"
tools:paddingStart="2dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.textview.MaterialTextView
android:id="@+id/title"
style="@style/TextAppearance.Regular.Body1.Light"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="6dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:ellipsize="end"
android:lineSpacingExtra="-4dp"
android:singleLine="true"
android:maxLines="2"
android:textColor="?android:attr/textColorPrimary"
android:textSize="12sp"
app:layout_constraintBottom_toTopOf="@+id/subtitle"
@ -152,11 +206,11 @@
style="@style/TextAppearance.Regular.Body1.Light"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="14dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="-1dp"
android:ellipsize="end"
android:lineSpacingExtra="-4dp"
android:layout_marginStart="6dp"
android:paddingEnd="6dp"
android:singleLine="true"
android:textColor="?android:attr/textColorSecondary"
android:textSize="12sp"

View File

@ -37,6 +37,29 @@
tools:ignore="ContentDescription"
tools:src="@mipmap/ic_launcher" />
<FrameLayout
android:id="@+id/play_layout"
android:layout_width="55dp"
android:layout_height="match_parent"
android:layout_gravity="center"
android:clickable="true"
android:focusable="true"
android:visibility="gone"
tools:visibility="visible">
<ImageView
android:id="@+id/play_button"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center"
android:background="@drawable/round_play_background"
android:contentDescription="@string/start_reading"
android:padding="6dp"
android:src="@drawable/ic_start_reading_white_24dp"
android:tint="@android:color/white" />
</FrameLayout>
<ProgressBar
android:id="@+id/progress"
style="?android:attr/progressBarStyleSmall"
@ -64,7 +87,7 @@
android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="@+id/extras_layout"
app:layout_constraintEnd_toStartOf="@+id/badge_view"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="@+id/card"
app:layout_constraintTop_toTopOf="parent"
@ -83,49 +106,83 @@
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="@+id/extras_layout"
app:layout_constraintEnd_toStartOf="@+id/badge_view"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/title"
app:layout_constraintTop_toBottomOf="@+id/title"
app:layout_constraintVertical_bias="0.0"
tools:text="Manga artist" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/extras_layout"
<com.google.android.material.card.MaterialCardView
android:id="@+id/badge_view"
android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:layout_marginEnd="12dp"
android:visibility="gone"
app:cardCornerRadius="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
app:cardElevation="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible">
<FrameLayout
android:id="@+id/play_layout"
android:layout_width="55dp"
android:layout_height="match_parent"
android:layout_gravity="end|bottom"
android:clickable="true"
android:focusable="true"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/download_text"
style="@style/TextAppearance.Regular.Caption.Light"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/pale_green"
android:gravity="center"
android:maxLines="1"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:textColor="@color/md_black_1000"
android:textSize="13sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:paddingEnd="8dp"
tools:text="1"
tools:visibility="visible" />
<ImageView
android:id="@+id/play_button"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="end|center"
android:layout_marginEnd="12dp"
android:background="@drawable/round_play_background"
android:contentDescription="@string/start_reading"
android:padding="3dp"
android:src="@drawable/ic_play_arrow_white_24dp"
android:tint="@android:color/white" />
android:id="@+id/unread_angle"
android:layout_width="10dp"
android:layout_height="0dp"
android:scaleType="fitXY"
android:src="@drawable/unread_angled_badge"
app:layout_constraintBottom_toBottomOf="@+id/unread_text"
app:layout_constraintEnd_toStartOf="@id/unread_text"
app:layout_constraintTop_toTopOf="@+id/unread_text" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.textview.MaterialTextView
android:id="@+id/unread_text"
style="@style/TextAppearance.Regular.Caption.Light"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/colorAccent"
android:gravity="center"
android:maxLines="1"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:textColor="@color/md_white_1000"
android:textSize="13sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/download_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/download_text"
app:layout_constraintTop_toTopOf="@+id/download_text"
tools:paddingStart="2dp"
tools:text="20"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<androidx.constraintlayout.widget.Barrier
android:id="@+id/bottom_line"

View File

@ -124,6 +124,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="7dp"
android:layout_marginTop="7dp"
android:layout_marginBottom="7dp"
android:layout_marginEnd="14dp"
android:baselineAligned="false"
android:gravity="center|start"
@ -132,35 +134,20 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="14dp"
android:layout_marginEnd="0dp"
android:clickable="true"
android:focusable="true"
android:text="@string/display_as"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textColor="?android:attr/textColorPrimary"
android:textColor="?android:attr/textColorSecondary"
android:textSize="15sp"
android:textStyle="normal" />
<RadioGroup
android:id="@+id/display_group"
<androidx.appcompat.widget.AppCompatSpinner
android:id="@+id/display_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="0dp"
android:paddingEnd="8dp"
android:text="@string/action_display_grid" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:text="@string/action_display_list" />
</RadioGroup>
android:entries="@array/library_display"/>
</LinearLayout>
<LinearLayout

View File

@ -32,6 +32,7 @@
android:id="@+id/shadow"
android:layout_width="match_parent"
android:layout_height="24dp"
android:alpha="0.5"
android:background="@drawable/shape_gradient_top_shadow"
android:paddingBottom="10dp"
app:layout_anchorGravity="top"

View File

@ -45,4 +45,10 @@
<item>@string/filter_mode_screen</item>
</string-array>
<string-array name="library_display">
<item>@string/action_display_list</item>
<item>@string/action_display_grid</item>
<item>@string/action_display_comfy_grid</item>
</string-array>
</resources>

View File

@ -68,6 +68,7 @@
<color name="md_black_1000">#000000</color>
<color name="md_grey_50">#FAFAFA</color>
<color name="md_grey_200">#CCCCCC</color>
<color name="md_grey_800">#424242</color>
<color name="md_blue_A200_50">#80448AFF</color>
@ -82,4 +83,5 @@
<color name="md_teal_500">#009688</color>
<color name="pale_green">#99CC99</color>
</resources>

View File

@ -94,7 +94,8 @@
<string name="action_add_to_home_screen">Add to home screen</string>
<string name="action_display_mode">Display mode</string>
<string name="action_display">Display</string>
<string name="action_display_grid">Grid</string>
<string name="action_display_comfy_grid">Comfy Grid</string>
<string name="action_display_grid">Compact Grid</string>
<string name="action_display_list">List</string>
<string name="action_display_download_badge">Download badges</string>
<string name="action_display_unread_text">Unread text</string>
@ -647,6 +648,6 @@
<string name="skip_this_step_next_time">Skip this step next time</string>
<string name="pre_migration_skip_toast">To show this screen again, go to Settings -> Library.</string>
<string name="reset_tags">Reset Tags</string>
<string name="display_as">Display as:</string>
<string name="display_as">Display as</string>
</resources>