Update manga details list item

pull/293/head
Koitharu 3 years ago
parent 7f530d0476
commit 516470e8ae
No known key found for this signature in database
GPG Key ID: 8E861F8CE6E7CE27

@ -1,7 +1,11 @@
package org.koitharu.kotatsu.list.ui package org.koitharu.kotatsu.list.ui
import android.os.Bundle import android.os.Bundle
import android.view.* import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.MarginLayoutParams import android.view.ViewGroup.MarginLayoutParams
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
@ -15,7 +19,6 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import coil.ImageLoader import coil.ImageLoader
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.domain.reverseAsync import org.koitharu.kotatsu.base.domain.reverseAsync
@ -42,13 +45,23 @@ import org.koitharu.kotatsu.list.ui.adapter.MangaListListener
import org.koitharu.kotatsu.list.ui.model.ListHeader import org.koitharu.kotatsu.list.ui.model.ListHeader
import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.list.ui.model.MangaItemModel import org.koitharu.kotatsu.list.ui.model.MangaItemModel
import org.koitharu.kotatsu.main.ui.MainActivity
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
import org.koitharu.kotatsu.main.ui.owners.BottomNavOwner import org.koitharu.kotatsu.main.ui.owners.BottomNavOwner
import org.koitharu.kotatsu.main.ui.MainActivity
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.reader.ui.ReaderActivity
import org.koitharu.kotatsu.search.ui.MangaListActivity
import org.koitharu.kotatsu.utils.ShareHelper import org.koitharu.kotatsu.utils.ShareHelper
import org.koitharu.kotatsu.utils.ext.* import org.koitharu.kotatsu.utils.ext.addMenuProvider
import org.koitharu.kotatsu.utils.ext.clearItemDecorations
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
import org.koitharu.kotatsu.utils.ext.getThemeColor
import org.koitharu.kotatsu.utils.ext.measureHeight
import org.koitharu.kotatsu.utils.ext.resolveDp
import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
abstract class MangaListFragment : abstract class MangaListFragment :
@ -138,6 +151,20 @@ abstract class MangaListFragment :
return selectionController?.onItemLongClick(item.id) ?: false return selectionController?.onItemLongClick(item.id) ?: false
} }
override fun onReadClick(manga: Manga, view: View) {
if (selectionController?.onItemClick(manga.id) != true) {
val intent = ReaderActivity.newIntent(context ?: return, manga)
startActivity(intent, scaleUpActivityOptionsOf(view).toBundle())
}
}
override fun onTagClick(manga: Manga, tag: MangaTag, view: View) {
if (selectionController?.onItemClick(manga.id) != true) {
val intent = MangaListActivity.newIntent(context ?: return, setOf(tag))
startActivity(intent)
}
}
@CallSuper @CallSuper
override fun onRefresh() { override fun onRefresh() {
binding.swipeRefreshLayout.isRefreshing = true binding.swipeRefreshLayout.isRefreshing = true
@ -251,12 +278,14 @@ abstract class MangaListFragment :
) )
addItemDecoration(decoration) addItemDecoration(decoration)
} }
ListMode.DETAILED_LIST -> { ListMode.DETAILED_LIST -> {
layoutManager = FitHeightLinearLayoutManager(context) layoutManager = FitHeightLinearLayoutManager(context)
val spacing = resources.getDimensionPixelOffset(R.dimen.list_spacing) val spacing = resources.getDimensionPixelOffset(R.dimen.list_spacing)
updatePadding(left = spacing, right = spacing) updatePadding(left = spacing, right = spacing)
addItemDecoration(SpacingItemDecoration(spacing)) addItemDecoration(SpacingItemDecoration(spacing))
} }
ListMode.GRID -> { ListMode.GRID -> {
layoutManager = FitHeightGridLayoutManager(context, checkNotNull(spanResolver).spanCount).also { layoutManager = FitHeightGridLayoutManager(context, checkNotNull(spanResolver).spanCount).also {
it.spanSizeLookup = spanSizeLookup it.spanSizeLookup = spanSizeLookup
@ -284,21 +313,25 @@ abstract class MangaListFragment :
selectionController?.addAll(ids) selectionController?.addAll(ids)
true true
} }
R.id.action_share -> { R.id.action_share -> {
ShareHelper(requireContext()).shareMangaLinks(selectedItems) ShareHelper(requireContext()).shareMangaLinks(selectedItems)
mode.finish() mode.finish()
true true
} }
R.id.action_favourite -> { R.id.action_favourite -> {
FavouriteCategoriesBottomSheet.show(childFragmentManager, selectedItems) FavouriteCategoriesBottomSheet.show(childFragmentManager, selectedItems)
mode.finish() mode.finish()
true true
} }
R.id.action_save -> { R.id.action_save -> {
DownloadService.confirmAndStart(requireContext(), selectedItems) DownloadService.confirmAndStart(requireContext(), selectedItems)
mode.finish() mode.finish()
true true
} }
else -> false else -> false
} }
} }

@ -22,11 +22,12 @@ open class MangaSelectionDecoration(context: Context) : AbstractSelectionItemDec
protected val paint = Paint(Paint.ANTI_ALIAS_FLAG) protected val paint = Paint(Paint.ANTI_ALIAS_FLAG)
protected val checkIcon = ContextCompat.getDrawable(context, materialR.drawable.ic_mtrl_checked_circle) protected val checkIcon = ContextCompat.getDrawable(context, materialR.drawable.ic_mtrl_checked_circle)
protected val iconOffset = context.resources.getDimensionPixelOffset(R.dimen.grid_spacing_outer) protected val iconOffset = context.resources.getDimensionPixelOffset(R.dimen.card_indicator_offset)
protected val iconSize = context.resources.getDimensionPixelOffset(R.dimen.card_indicator_size)
protected val strokeColor = context.getThemeColor(materialR.attr.colorPrimary, Color.RED) protected val strokeColor = context.getThemeColor(materialR.attr.colorPrimary, Color.RED)
protected val fillColor = ColorUtils.setAlphaComponent( protected val fillColor = ColorUtils.setAlphaComponent(
ColorUtils.blendARGB(strokeColor, context.getThemeColor(materialR.attr.colorSurface), 0.8f), ColorUtils.blendARGB(strokeColor, context.getThemeColor(materialR.attr.colorSurface), 0.8f),
0x74 0x74,
) )
protected val defaultRadius = context.resources.getDimension(R.dimen.list_selector_corner) protected val defaultRadius = context.resources.getDimension(R.dimen.list_selector_corner)
@ -65,11 +66,11 @@ open class MangaSelectionDecoration(context: Context) : AbstractSelectionItemDec
setBounds( setBounds(
(bounds.left + iconOffset).toInt(), (bounds.left + iconOffset).toInt(),
(bounds.top + iconOffset).toInt(), (bounds.top + iconOffset).toInt(),
(bounds.left + iconOffset + intrinsicWidth).toInt(), (bounds.left + iconOffset + iconSize).toInt(),
(bounds.top + iconOffset + intrinsicHeight).toInt(), (bounds.top + iconOffset + iconSize).toInt(),
) )
draw(canvas) draw(canvas)
} }
} }
} }
} }

@ -0,0 +1,13 @@
package org.koitharu.kotatsu.list.ui.adapter
import android.view.View
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaTag
interface MangaDetailsClickListener : OnListItemClickListener<Manga> {
fun onReadClick(manga: Manga, view: View)
fun onTagClick(manga: Manga, tag: MangaTag, view: View)
}

@ -1,34 +1,52 @@
package org.koitharu.kotatsu.list.ui.adapter package org.koitharu.kotatsu.list.ui.adapter
import android.view.View
import androidx.core.view.isVisible
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import coil.ImageLoader import coil.ImageLoader
import com.google.android.material.badge.BadgeDrawable import com.google.android.material.badge.BadgeDrawable
import com.google.android.material.chip.Chip
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.base.ui.widgets.ChipsView
import org.koitharu.kotatsu.databinding.ItemMangaListDetailsBinding import org.koitharu.kotatsu.databinding.ItemMangaListDetailsBinding
import org.koitharu.kotatsu.history.domain.PROGRESS_NONE import org.koitharu.kotatsu.history.domain.PROGRESS_NONE
import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.list.ui.model.MangaListDetailedModel import org.koitharu.kotatsu.list.ui.model.MangaListDetailedModel
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.utils.ext.* import org.koitharu.kotatsu.utils.ext.disposeImageRequest
import org.koitharu.kotatsu.utils.ext.enqueueWith
import org.koitharu.kotatsu.utils.ext.newImageRequest
import org.koitharu.kotatsu.utils.ext.referer
import org.koitharu.kotatsu.utils.ext.textAndVisible
import org.koitharu.kotatsu.utils.image.CoverSizeResolver import org.koitharu.kotatsu.utils.image.CoverSizeResolver
fun mangaListDetailedItemAD( fun mangaListDetailedItemAD(
coil: ImageLoader, coil: ImageLoader,
lifecycleOwner: LifecycleOwner, lifecycleOwner: LifecycleOwner,
clickListener: OnListItemClickListener<Manga>, clickListener: MangaDetailsClickListener,
) = adapterDelegateViewBinding<MangaListDetailedModel, ListModel, ItemMangaListDetailsBinding>( ) = adapterDelegateViewBinding<MangaListDetailedModel, ListModel, ItemMangaListDetailsBinding>(
{ inflater, parent -> ItemMangaListDetailsBinding.inflate(inflater, parent, false) }, { inflater, parent -> ItemMangaListDetailsBinding.inflate(inflater, parent, false) },
) { ) {
var badge: BadgeDrawable? = null var badge: BadgeDrawable? = null
itemView.setOnClickListener { val listenerAdapter = object : View.OnClickListener, View.OnLongClickListener, ChipsView.OnChipClickListener {
clickListener.onItemClick(item.manga, it) override fun onClick(v: View) = when (v.id) {
} R.id.button_read -> clickListener.onReadClick(item.manga, v)
itemView.setOnLongClickListener { else -> clickListener.onItemClick(item.manga, v)
clickListener.onItemLongClick(item.manga, it) }
override fun onLongClick(v: View): Boolean = clickListener.onItemLongClick(item.manga, v)
override fun onChipClick(chip: Chip, data: Any?) {
val tag = data as? MangaTag ?: return
clickListener.onTagClick(item.manga, tag, chip)
}
} }
itemView.setOnClickListener(listenerAdapter)
itemView.setOnLongClickListener(listenerAdapter)
binding.buttonRead.setOnClickListener(listenerAdapter)
binding.chipsTags.onChipClickListener = listenerAdapter
bind { payloads -> bind { payloads ->
binding.textViewTitle.text = item.title binding.textViewTitle.text = item.title
@ -44,8 +62,9 @@ fun mangaListDetailedItemAD(
lifecycle(lifecycleOwner) lifecycle(lifecycleOwner)
enqueueWith(coil) enqueueWith(coil)
} }
binding.textViewRating.textAndVisible = item.rating binding.chipsTags.setChips(item.tags)
binding.textViewTags.text = item.tags binding.ratingBar.isVisible = item.manga.hasRating
binding.ratingBar.rating = binding.ratingBar.numStars * item.manga.rating
badge = itemView.bindBadge(badge, item.counter) badge = itemView.bindBadge(badge, item.counter)
} }

@ -1,11 +1,9 @@
package org.koitharu.kotatsu.list.ui.adapter package org.koitharu.kotatsu.list.ui.adapter
import android.view.View import android.view.View
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.MangaTag
interface MangaListListener : OnListItemClickListener<Manga>, ListStateHolderListener, ListHeaderClickListener { interface MangaListListener : MangaDetailsClickListener, ListStateHolderListener, ListHeaderClickListener {
fun onUpdateFilter(tags: Set<MangaTag>) fun onUpdateFilter(tags: Set<MangaTag>)

@ -1,8 +1,7 @@
package org.koitharu.kotatsu.list.ui.model package org.koitharu.kotatsu.list.ui.model
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.widgets.ChipsView
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.prefs.ListMode
@ -11,6 +10,8 @@ import org.koitharu.kotatsu.list.domain.ListExtraProvider
import org.koitharu.kotatsu.parsers.exception.AuthRequiredException import org.koitharu.kotatsu.parsers.exception.AuthRequiredException
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.utils.ext.ifZero import org.koitharu.kotatsu.utils.ext.ifZero
import java.net.SocketTimeoutException
import java.net.UnknownHostException
fun Manga.toListModel(counter: Int, progress: Float) = MangaListModel( fun Manga.toListModel(counter: Int, progress: Float) = MangaListModel(
id = id, id = id,
@ -26,12 +27,11 @@ fun Manga.toListDetailedModel(counter: Int, progress: Float) = MangaListDetailed
id = id, id = id,
title = title, title = title,
subtitle = altTitle, subtitle = altTitle,
rating = if (hasRating) String.format("%.1f", rating * 5) else null,
tags = tags.joinToString(", ") { it.title },
coverUrl = coverUrl, coverUrl = coverUrl,
manga = this, manga = this,
counter = counter, counter = counter,
progress = progress, progress = progress,
tags = tags.map { ChipsView.ChipModel(0, it.title, false, false, it) },
) )
fun Manga.toGridModel(counter: Int, progress: Float) = MangaGridModel( fun Manga.toGridModel(counter: Int, progress: Float) = MangaGridModel(
@ -69,9 +69,11 @@ suspend fun <C : MutableCollection<in MangaItemModel>> List<Manga>.toUi(
ListMode.LIST -> mapTo(destination) { ListMode.LIST -> mapTo(destination) {
it.toListModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id)) it.toListModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id))
} }
ListMode.DETAILED_LIST -> mapTo(destination) { ListMode.DETAILED_LIST -> mapTo(destination) {
it.toListDetailedModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id)) it.toListDetailedModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id))
} }
ListMode.GRID -> mapTo(destination) { ListMode.GRID -> mapTo(destination) {
it.toGridModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id)) it.toGridModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id))
} }
@ -95,5 +97,6 @@ private fun getErrorIcon(error: Throwable) = when (error) {
is UnknownHostException, is UnknownHostException,
is SocketTimeoutException, is SocketTimeoutException,
-> R.drawable.ic_plug_large -> R.drawable.ic_plug_large
else -> R.drawable.ic_error_large else -> R.drawable.ic_error_large
} }

@ -1,15 +1,15 @@
package org.koitharu.kotatsu.list.ui.model package org.koitharu.kotatsu.list.ui.model
import org.koitharu.kotatsu.base.ui.widgets.ChipsView
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
data class MangaListDetailedModel( data class MangaListDetailedModel(
override val id: Long, override val id: Long,
override val title: String, override val title: String,
val subtitle: String?, val subtitle: String?,
val tags: String,
override val coverUrl: String, override val coverUrl: String,
val rating: String?,
override val manga: Manga, override val manga: Manga,
override val counter: Int, override val counter: Int,
override val progress: Float, override val progress: Float,
) : MangaItemModel val tags: List<ChipsView.ChipModel>,
) : MangaItemModel

@ -12,7 +12,6 @@ import androidx.core.graphics.Insets
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import coil.ImageLoader import coil.ImageLoader
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseActivity import org.koitharu.kotatsu.base.ui.BaseActivity
import org.koitharu.kotatsu.base.ui.list.ListSelectionController import org.koitharu.kotatsu.base.ui.list.ListSelectionController
@ -27,11 +26,15 @@ import org.koitharu.kotatsu.list.ui.adapter.MangaListListener
import org.koitharu.kotatsu.list.ui.model.ListHeader import org.koitharu.kotatsu.list.ui.model.ListHeader
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.reader.ui.ReaderActivity
import org.koitharu.kotatsu.search.ui.MangaListActivity
import org.koitharu.kotatsu.search.ui.SearchActivity import org.koitharu.kotatsu.search.ui.SearchActivity
import org.koitharu.kotatsu.search.ui.multi.adapter.MultiSearchAdapter import org.koitharu.kotatsu.search.ui.multi.adapter.MultiSearchAdapter
import org.koitharu.kotatsu.utils.ShareHelper import org.koitharu.kotatsu.utils.ShareHelper
import org.koitharu.kotatsu.utils.ext.assistedViewModels import org.koitharu.kotatsu.utils.ext.assistedViewModels
import org.koitharu.kotatsu.utils.ext.invalidateNestedItemDecorations import org.koitharu.kotatsu.utils.ext.invalidateNestedItemDecorations
import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf
import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class MultiSearchActivity : class MultiSearchActivity :
@ -110,6 +113,20 @@ class MultiSearchActivity :
return selectionController.onItemLongClick(item.id) return selectionController.onItemLongClick(item.id)
} }
override fun onReadClick(manga: Manga, view: View) {
if (!selectionController.onItemClick(manga.id)) {
val intent = ReaderActivity.newIntent(this, manga)
startActivity(intent, scaleUpActivityOptionsOf(view).toBundle())
}
}
override fun onTagClick(manga: Manga, tag: MangaTag, view: View) {
if (!selectionController.onItemClick(manga.id)) {
val intent = MangaListActivity.newIntent(this, setOf(tag))
startActivity(intent)
}
}
override fun onRetryClick(error: Throwable) { override fun onRetryClick(error: Throwable) {
viewModel.doSearch(viewModel.query.value.orEmpty()) viewModel.doSearch(viewModel.query.value.orEmpty())
} }
@ -139,16 +156,19 @@ class MultiSearchActivity :
mode.finish() mode.finish()
true true
} }
R.id.action_favourite -> { R.id.action_favourite -> {
FavouriteCategoriesBottomSheet.show(supportFragmentManager, collectSelectedItems()) FavouriteCategoriesBottomSheet.show(supportFragmentManager, collectSelectedItems())
mode.finish() mode.finish()
true true
} }
R.id.action_save -> { R.id.action_save -> {
DownloadService.confirmAndStart(this, collectSelectedItems()) DownloadService.confirmAndStart(this, collectSelectedItems())
mode.finish() mode.finish()
true true
} }
else -> false else -> false
} }
} }

@ -144,6 +144,10 @@ class FeedFragment :
startActivity(DetailsActivity.newIntent(context ?: return, item)) startActivity(DetailsActivity.newIntent(context ?: return, item))
} }
override fun onReadClick(manga: Manga, view: View) = Unit
override fun onTagClick(manga: Manga, tag: MangaTag, view: View) = Unit
companion object { companion object {
fun newInstance() = FeedFragment() fun newInstance() = FeedFragment()

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/selector_overlay">
<item>
<shape android:shape="oval">
<solid android:color="?colorSurface" />
</shape>
</item>
<item android:id="@android:id/mask">
<shape android:shape="oval">
<solid android:color="@color/selector_overlay" />
</shape>
</item>
</ripple>

@ -1,7 +1,7 @@
<vector <vector
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:width="14dp" android:width="18dp"
android:height="14dp" android:height="18dp"
android:tint="?attr/colorControlNormal" android:tint="?attr/colorControlNormal"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24"> android:viewportHeight="24">

@ -34,9 +34,9 @@
<org.koitharu.kotatsu.history.ui.util.ReadingProgressView <org.koitharu.kotatsu.history.ui.util.ReadingProgressView
android:id="@+id/progressView" android:id="@+id/progressView"
android:layout_width="32dp" android:layout_width="@dimen/card_indicator_size"
android:layout_height="32dp" android:layout_height="@dimen/card_indicator_size"
android:layout_margin="4dp" android:layout_margin="@dimen/card_indicator_offset"
app:layout_constraintBottom_toBottomOf="@id/imageView_cover" app:layout_constraintBottom_toBottomOf="@id/imageView_cover"
app:layout_constraintEnd_toEndOf="@id/imageView_cover" /> app:layout_constraintEnd_toEndOf="@id/imageView_cover" />

@ -34,9 +34,9 @@
<org.koitharu.kotatsu.history.ui.util.ReadingProgressView <org.koitharu.kotatsu.history.ui.util.ReadingProgressView
android:id="@+id/progressView" android:id="@+id/progressView"
android:layout_width="32dp" android:layout_width="@dimen/card_indicator_size"
android:layout_height="32dp" android:layout_height="@dimen/card_indicator_size"
android:layout_margin="4dp" android:layout_margin="@dimen/card_indicator_offset"
app:layout_constraintBottom_toBottomOf="@id/imageView_cover" app:layout_constraintBottom_toBottomOf="@id/imageView_cover"
app:layout_constraintEnd_toEndOf="@id/imageView_cover" /> app:layout_constraintEnd_toEndOf="@id/imageView_cover" />

@ -7,13 +7,13 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clipChildren="false" android:clipChildren="false"
app:cardCornerRadius="16dp"> app:cardCornerRadius="16dp"
tools:layout_width="140dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical">
android:padding="4dp">
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -31,10 +31,10 @@
<org.koitharu.kotatsu.history.ui.util.ReadingProgressView <org.koitharu.kotatsu.history.ui.util.ReadingProgressView
android:id="@+id/progressView" android:id="@+id/progressView"
android:layout_width="32dp" android:layout_width="@dimen/card_indicator_size"
android:layout_height="32dp" android:layout_height="@dimen/card_indicator_size"
android:layout_gravity="bottom|end" android:layout_gravity="bottom|end"
android:layout_margin="4dp" /> android:layout_margin="@dimen/card_indicator_offset" />
</FrameLayout> </FrameLayout>
@ -45,8 +45,7 @@
android:elegantTextHeight="false" android:elegantTextHeight="false"
android:ellipsize="end" android:ellipsize="end"
android:lines="2" android:lines="2"
android:paddingHorizontal="8dp" android:padding="8dp"
android:paddingVertical="4dp"
android:textAppearance="?attr/textAppearanceTitleSmall" android:textAppearance="?attr/textAppearanceTitleSmall"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"

@ -4,31 +4,29 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/manga_list_details_item_height" android:layout_height="wrap_content"
app:cardCornerRadius="16dp"> app:cardCornerRadius="16dp">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:orientation="horizontal"
android:padding="4dp">
<org.koitharu.kotatsu.base.ui.widgets.CoverImageView <com.google.android.material.imageview.ShapeableImageView
android:id="@+id/imageView_cover" android:id="@+id/imageView_cover"
android:layout_width="wrap_content" android:layout_width="98dp"
android:layout_height="match_parent" android:layout_height="0dp"
android:orientation="vertical"
android:scaleType="centerCrop" android:scaleType="centerCrop"
app:layout_constraintDimensionRatio="13:18"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Kotatsu.Cover" app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Kotatsu.Cover"
tools:src="@sample/covers" /> tools:src="@sample/covers" />
<org.koitharu.kotatsu.history.ui.util.ReadingProgressView <org.koitharu.kotatsu.history.ui.util.ReadingProgressView
android:id="@+id/progressView" android:id="@+id/progressView"
android:layout_width="32dp" android:layout_width="@dimen/card_indicator_size"
android:layout_height="32dp" android:layout_height="@dimen/card_indicator_size"
android:layout_margin="4dp" android:layout_margin="@dimen/card_indicator_offset"
app:layout_constraintBottom_toBottomOf="@id/imageView_cover" app:layout_constraintBottom_toBottomOf="@id/imageView_cover"
app:layout_constraintEnd_toEndOf="@id/imageView_cover" /> app:layout_constraintEnd_toEndOf="@id/imageView_cover" />
@ -36,13 +34,13 @@
android:id="@+id/textView_title" android:id="@+id/textView_title"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="12dp"
android:layout_marginTop="8dp" android:layout_marginTop="12dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="12dp"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="2" android:maxLines="2"
android:textAppearance="?attr/textAppearanceTitleMedium" android:textAppearance="?attr/textAppearanceTitleLarge"
app:layout_constraintBottom_toTopOf="@+id/textView_subtitle" android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView_cover" app:layout_constraintStart_toEndOf="@+id/imageView_cover"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@ -52,61 +50,68 @@
android:id="@+id/textView_subtitle" android:id="@+id/textView_subtitle"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="12dp"
android:layout_marginEnd="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="12dp"
android:ellipsize="none" android:ellipsize="none"
android:gravity="center_vertical" android:gravity="center_vertical"
android:maxLines="2" android:maxLines="2"
android:requiresFadingEdge="horizontal" android:requiresFadingEdge="horizontal"
android:textAppearance="?attr/textAppearanceBodyMedium" android:textAppearance="?attr/textAppearanceSubtitle1"
app:layout_constraintBottom_toTopOf="@+id/linearLayout"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView_cover" app:layout_constraintStart_toEndOf="@+id/imageView_cover"
app:layout_constraintTop_toBottomOf="@+id/textView_title" app:layout_constraintTop_toBottomOf="@+id/textView_title"
tools:text="@tools:sample/lorem/random" /> tools:text="@tools:sample/lorem/random" />
<LinearLayout <HorizontalScrollView
android:id="@+id/linearLayout" android:id="@+id/scrollView_tags"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="12dp"
android:layout_marginEnd="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:baselineAligned="false" android:scrollbars="none"
android:clipChildren="false"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView_cover" app:layout_constraintStart_toEndOf="@+id/imageView_cover"
app:layout_constraintTop_toBottomOf="@+id/textView_subtitle"> app:layout_constraintTop_toBottomOf="@id/textView_subtitle"
app:layout_goneMarginTop="12dp">
<TextView <org.koitharu.kotatsu.base.ui.widgets.ChipsView
android:id="@+id/textView_tags" android:id="@+id/chips_tags"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="none"
android:gravity="center_vertical"
android:requiresFadingEdge="horizontal"
android:singleLine="true"
android:textAppearance="?attr/textAppearanceBodySmall"
tools:text="@sample/genres" />
<TextView
android:id="@+id/textView_rating"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:drawablePadding="4dp" app:chipSpacingHorizontal="6dp"
android:elegantTextHeight="false" app:chipSpacingVertical="6dp"
android:gravity="center_vertical" app:singleLine="true" />
android:paddingStart="6dp" </HorizontalScrollView>
android:singleLine="true"
android:textAppearance="?attr/textAppearanceBodySmall" <RatingBar
app:drawableEndCompat="@drawable/ic_star" android:id="@+id/ratingBar"
tools:ignore="RtlSymmetry" style="?android:ratingBarStyleSmall"
tools:text="9.6" /> android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:isIndicator="true"
android:paddingVertical="8dp"
app:layout_constraintEnd_toEndOf="@id/imageView_cover"
app:layout_constraintStart_toStartOf="@id/imageView_cover"
app:layout_constraintTop_toBottomOf="@id/imageView_cover" />
</LinearLayout> <ImageView
android:id="@+id/button_read"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="12dp"
android:background="@drawable/bg_circle_button"
android:contentDescription="@string/read"
android:scaleType="center"
android:src="@drawable/ic_read"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/scrollView_tags"
app:layout_constraintVertical_bias="1" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

@ -17,10 +17,10 @@
<TextView <TextView
android:id="@+id/textView_number" android:id="@+id/textView_number"
android:layout_width="32dp" android:layout_width="@dimen/card_indicator_size"
android:layout_height="32dp" android:layout_height="@dimen/card_indicator_size"
android:layout_gravity="bottom|end" android:layout_gravity="bottom|end"
android:layout_margin="8dp" android:layout_margin="@dimen/card_indicator_offset"
android:ellipsize="none" android:ellipsize="none"
android:gravity="center" android:gravity="center"
android:singleLine="true" android:singleLine="true"

@ -40,6 +40,9 @@
<dimen name="bottom_sheet_handle_size_max">24dp</dimen> <dimen name="bottom_sheet_handle_size_max">24dp</dimen>
<dimen name="dialog_radius">8dp</dimen> <dimen name="dialog_radius">8dp</dimen>
<dimen name="card_indicator_size">32dp</dimen>
<dimen name="card_indicator_offset">8dp</dimen>
<dimen name="appwidget_corner_radius_inner">8dp</dimen> <dimen name="appwidget_corner_radius_inner">8dp</dimen>
<!-- FastScroller --> <!-- FastScroller -->

@ -224,6 +224,11 @@
<item name="cornerSize">6dp</item> <item name="cornerSize">6dp</item>
</style> </style>
<style name="ShapeAppearanceOverlay.Kotatsu.Circle" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">50%</item>
</style>
<!--Preferences--> <!--Preferences-->
<style name="PreferenceThemeOverlay.Kotatsu"> <style name="PreferenceThemeOverlay.Kotatsu">

Loading…
Cancel
Save