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