diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/stats/data/StatsDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/stats/data/StatsDao.kt index effc33cf2..94b5ba86f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/stats/data/StatsDao.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/stats/data/StatsDao.kt @@ -4,34 +4,34 @@ import androidx.room.Dao import androidx.room.MapColumn import androidx.room.Query import androidx.room.Upsert -import org.koitharu.kotatsu.core.db.entity.MangaEntity -import org.koitharu.kotatsu.core.db.entity.MangaWithTags -import org.koitharu.kotatsu.parsers.model.Manga @Dao -abstract class StatsDao { +interface StatsDao { @Query("SELECT * FROM stats ORDER BY started_at") - abstract suspend fun findAll(): List + suspend fun findAll(): List @Query("SELECT * FROM stats WHERE manga_id = :mangaId ORDER BY started_at") - abstract suspend fun findAll(mangaId: Long): List + suspend fun findAll(mangaId: Long): List @Query("SELECT IFNULL(SUM(pages),0) FROM stats WHERE manga_id = :mangaId") - abstract suspend fun getReadPagesCount(mangaId: Long): Int + suspend fun getReadPagesCount(mangaId: Long): Int @Query("SELECT IFNULL(SUM(duration)/SUM(pages), 0) FROM stats WHERE manga_id = :mangaId") - abstract suspend fun getAverageTimePerPage(mangaId: Long): Long + suspend fun getAverageTimePerPage(mangaId: Long): Long + + @Query("SELECT IFNULL(SUM(duration)/SUM(pages), 0) FROM stats") + suspend fun getAverageTimePerPage(): Long @Query("SELECT IFNULL(SUM(duration), 0) FROM stats WHERE manga_id = :mangaId") - abstract suspend fun getReadingTime(mangaId: Long): Long + suspend fun getReadingTime(mangaId: Long): Long @Query("SELECT IFNULL(SUM(duration), 0) FROM stats") - abstract suspend fun getTotalReadingTime(): Long + suspend fun getTotalReadingTime(): Long @Query("SELECT manga_id, SUM(duration) AS d FROM stats GROUP BY manga_id ORDER BY d") - abstract suspend fun getDurationStats(): Map<@MapColumn("manga_id") Long, @MapColumn("d") Long> + suspend fun getDurationStats(): Map<@MapColumn("manga_id") Long, @MapColumn("d") Long> @Upsert - abstract suspend fun upsert(entity: StatsEntity) + suspend fun upsert(entity: StatsEntity) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/stats/data/StatsRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/stats/data/StatsRepository.kt index c9e829b11..7d81ff121 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/stats/data/StatsRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/stats/data/StatsRepository.kt @@ -1,14 +1,9 @@ package org.koitharu.kotatsu.stats.data -import androidx.collection.ArrayMap -import androidx.collection.MutableScatterMap -import androidx.collection.ScatterMap import androidx.room.withTransaction import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.db.entity.toManga -import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.stats.domain.StatsRecord -import java.util.Date import javax.inject.Inject class StatsRepository @Inject constructor( diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/stats/domain/StatsRecord.kt b/app/src/main/kotlin/org/koitharu/kotatsu/stats/domain/StatsRecord.kt index 6f9a1e2d4..172fdc45a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/stats/domain/StatsRecord.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/stats/domain/StatsRecord.kt @@ -7,16 +7,19 @@ import com.google.android.material.R import com.google.android.material.color.MaterialColors import org.koitharu.kotatsu.core.util.ext.getThemeColor import org.koitharu.kotatsu.details.data.ReadingTime +import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.parsers.model.Manga -import java.util.Date import java.util.concurrent.TimeUnit import kotlin.math.absoluteValue -import kotlin.math.min data class StatsRecord( val manga: Manga, val duration: Long, -) { +) : ListModel { + + override fun areItemsTheSame(other: ListModel): Boolean { + return other is StatsRecord && other.manga == manga + } val time: ReadingTime diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/StatsAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/StatsAD.kt new file mode 100644 index 000000000..671b12892 --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/StatsAD.kt @@ -0,0 +1,25 @@ +package org.koitharu.kotatsu.stats.ui + +import android.content.res.ColorStateList +import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener +import org.koitharu.kotatsu.databinding.ItemStatsBinding +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.stats.domain.StatsRecord + +fun statsAD( + listener: OnListItemClickListener, +) = adapterDelegateViewBinding( + { layoutInflater, parent -> ItemStatsBinding.inflate(layoutInflater, parent, false) }, +) { + + binding.root.setOnClickListener { v -> + listener.onItemClick(item.manga, v) + } + + bind { + binding.textViewTitle.text = item.manga.title + binding.textViewSummary.text = item.time.format(context.resources) + binding.imageViewBadge.imageTintList = ColorStateList.valueOf(item.getColor(context)) + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/StatsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/StatsFragment.kt index 6b414da6d..34d80dc88 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/StatsFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/StatsFragment.kt @@ -1,29 +1,25 @@ package org.koitharu.kotatsu.stats.ui -import android.graphics.drawable.ShapeDrawable -import android.graphics.drawable.shapes.OvalShape -import android.graphics.drawable.shapes.Shape import android.os.Bundle -import android.text.style.DynamicDrawableSpan -import android.text.style.ImageSpan import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup -import androidx.core.content.ContextCompat import androidx.core.graphics.Insets -import androidx.core.text.buildSpannedString -import androidx.core.text.inSpans import androidx.fragment.app.viewModels import dagger.hilt.android.AndroidEntryPoint -import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.BaseFragment +import org.koitharu.kotatsu.core.ui.BaseListAdapter +import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.databinding.FragmentStatsBinding +import org.koitharu.kotatsu.details.ui.DetailsActivity +import org.koitharu.kotatsu.list.ui.adapter.ListItemType import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.stats.domain.StatsRecord import org.koitharu.kotatsu.stats.ui.views.PieChartView @AndroidEntryPoint -class StatsFragment : BaseFragment() { +class StatsFragment : BaseFragment(), OnListItemClickListener { private val viewModel: StatsViewModel by viewModels() @@ -33,6 +29,9 @@ class StatsFragment : BaseFragment() { override fun onViewBindingCreated(binding: FragmentStatsBinding, savedInstanceState: Bundle?) { super.onViewBindingCreated(binding, savedInstanceState) + val adapter = BaseListAdapter() + .addDelegate(ListItemType.FEED, statsAD(this)) + binding.recyclerView.adapter = adapter viewModel.readingStats.observe(viewLifecycleOwner) { val sum = it.sumOf { it.duration } binding.chart.setData( @@ -45,27 +44,13 @@ class StatsFragment : BaseFragment() { ) }, ) - binding.textViewLegend.text = buildLegend(it) + adapter.emit(it) } } override fun onWindowInsetsChanged(insets: Insets) = Unit - private fun buildLegend(stats: List) = buildSpannedString { - val context = context ?: return@buildSpannedString - for (item in stats) { - ContextCompat.getDrawable(context, R.drawable.bg_rounded_square)?.let { icon -> - icon.setBounds(0, 0, icon.intrinsicWidth, icon.intrinsicHeight) - icon.setTint(item.getColor(context)) - inSpans(ImageSpan(icon, DynamicDrawableSpan.ALIGN_BASELINE)) { - append(' ') - } - append(' ') - } - append(item.manga.title) - append(" - ") - append(item.time.format(context.resources)) - appendLine() - } + override fun onItemClick(item: Manga, view: View) { + startActivity(DetailsActivity.newIntent(view.context, item)) } } diff --git a/app/src/main/res/layout/fragment_stats.xml b/app/src/main/res/layout/fragment_stats.xml index 7380c3a10..c3c806baa 100644 --- a/app/src/main/res/layout/fragment_stats.xml +++ b/app/src/main/res/layout/fragment_stats.xml @@ -4,7 +4,9 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:background="?android:colorBackground" + android:fillViewport="true"> - + tools:itemCount="4" + tools:listitem="@layout/item_stats" /> diff --git a/app/src/main/res/layout/item_stats.xml b/app/src/main/res/layout/item_stats.xml new file mode 100644 index 000000000..eeb73eee4 --- /dev/null +++ b/app/src/main/res/layout/item_stats.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + +