Clearing stats

This commit is contained in:
Koitharu
2024-02-29 14:27:52 +02:00
parent 101d357eff
commit 096f5b15dc
8 changed files with 111 additions and 4 deletions

View File

@@ -32,6 +32,9 @@ interface StatsDao {
@Query("SELECT manga_id, SUM(duration) AS d FROM stats GROUP BY manga_id ORDER BY d DESC")
suspend fun getDurationStats(): Map<@MapColumn("manga_id") Long, @MapColumn("d") Long>
@Query("DELETE FROM stats")
suspend fun clear()
@Upsert
suspend fun upsert(entity: StatsEntity)
}

View File

@@ -44,4 +44,8 @@ class StatsRepository @Inject constructor(
}
time
}
suspend fun clearStats() {
db.getStatsDao().clear()
}
}

View File

@@ -1,19 +1,28 @@
package org.koitharu.kotatsu.stats.ui
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.activity.viewModels
import androidx.core.graphics.Insets
import androidx.fragment.app.viewModels
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity
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.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.util.ext.DIALOG_THEME_CENTERED
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.showOrHide
import org.koitharu.kotatsu.databinding.ActivityStatsBinding
import org.koitharu.kotatsu.details.ui.DetailsActivity
import org.koitharu.kotatsu.list.ui.adapter.ListItemType
@@ -22,7 +31,8 @@ import org.koitharu.kotatsu.stats.domain.StatsRecord
import org.koitharu.kotatsu.stats.ui.views.PieChartView
@AndroidEntryPoint
class StatsActivity : BaseActivity<ActivityStatsBinding>(), OnListItemClickListener<Manga> {
class StatsActivity : BaseActivity<ActivityStatsBinding>(), OnListItemClickListener<Manga>,
PieChartView.OnSegmentClickListener {
private val viewModel: StatsViewModel by viewModels()
@@ -33,6 +43,11 @@ class StatsActivity : BaseActivity<ActivityStatsBinding>(), OnListItemClickListe
val adapter = BaseListAdapter<StatsRecord>()
.addDelegate(ListItemType.FEED, statsAD(this))
viewBinding.recyclerView.adapter = adapter
viewBinding.chart.onSegmentClickListener = this
viewModel.isLoading.observe(this) {
viewBinding.progressBar.showOrHide(it)
}
viewModel.onActionDone.observeEvent(this, ReversibleActionObserver(viewBinding.recyclerView))
viewModel.readingStats.observe(this) {
val sum = it.sumOf { it.duration }
viewBinding.chart.setData(
@@ -54,4 +69,37 @@ class StatsActivity : BaseActivity<ActivityStatsBinding>(), OnListItemClickListe
override fun onItemClick(item: Manga, view: View) {
startActivity(DetailsActivity.newIntent(view.context, item))
}
override fun onSegmentClick(view: PieChartView, segment: PieChartView.Segment) {
Toast.makeText(this, segment.label, Toast.LENGTH_SHORT).apply {
setGravity(Gravity.TOP, 0, view.top + view.height / 2)
}.show()
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.opt_stats, menu)
return super.onCreateOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_clear -> {
showClearConfirmDialog()
true
}
else -> super.onOptionsItemSelected(item)
}
}
private fun showClearConfirmDialog() {
MaterialAlertDialogBuilder(this, DIALOG_THEME_CENTERED)
.setMessage(R.string.clear_stats_confirm)
.setTitle(R.string.clear_stats)
.setIcon(R.drawable.ic_delete)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.clear) { _, _ ->
viewModel.clear()
}.show()
}
}

View File

@@ -3,12 +3,18 @@ package org.koitharu.kotatsu.stats.ui
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.plus
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseViewModel
import org.koitharu.kotatsu.core.ui.util.ReversibleAction
import org.koitharu.kotatsu.core.util.ext.MutableEventFlow
import org.koitharu.kotatsu.core.util.ext.call
import org.koitharu.kotatsu.stats.data.StatsRepository
import org.koitharu.kotatsu.stats.domain.StatsRecord
import javax.inject.Inject
@HiltViewModel
@@ -16,7 +22,20 @@ class StatsViewModel @Inject constructor(
private val repository: StatsRepository,
) : BaseViewModel() {
val readingStats = flow {
emit(repository.getReadingStats())
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Lazily, emptyList())
val onActionDone = MutableEventFlow<ReversibleAction>()
val readingStats = MutableStateFlow<List<StatsRecord>>(emptyList())
init {
launchLoadingJob(Dispatchers.Default) {
readingStats.value = repository.getReadingStats()
}
}
fun clear() {
launchLoadingJob(Dispatchers.Default) {
repository.clearStats()
readingStats.value = emptyList()
onActionDone.call(ReversibleAction(R.string.stats_cleared, null))
}
}
}

View File

@@ -98,6 +98,9 @@ class PieChartView @JvmOverloads constructor(
}
override fun onDown(e: MotionEvent): Boolean {
if (onSegmentClickListener == null) {
return false
}
val segment = findSegmentIndex(e.x, e.y)
if (segment != hightlightedSegment) {
hightlightedSegment = segment

View File

@@ -26,6 +26,21 @@
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progressBar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="gone"
app:hideAnimationBehavior="outward"
app:layout_constraintBottom_toBottomOf="@id/appbar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/appbar"
app:showAnimationBehavior="inward"
app:trackCornerRadius="0dp"
tools:visibility="visible" />
<org.koitharu.kotatsu.stats.ui.views.PieChartView
android:id="@+id/chart"
android:layout_width="0dp"

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_clear"
android:title="@string/clear_stats"
android:titleCondensed="@string/clear"
app:showAsAction="never" />
</menu>

View File

@@ -608,4 +608,7 @@
<string name="other_manga">Other manga</string>
<string name="less_than_minute">Less than a minute</string>
<string name="statistics">Statistics</string>
<string name="clear_stats">Clear statistics</string>
<string name="stats_cleared">Statistics cleared</string>
<string name="clear_stats_confirm">Do you really want to clear all reading statistics? This action cannot be undone.</string>
</resources>