From 096f5b15dc6ff15ad161cf4ef405f4a372366f12 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Thu, 29 Feb 2024 14:27:52 +0200 Subject: [PATCH] Clearing stats --- .../koitharu/kotatsu/stats/data/StatsDao.kt | 3 ++ .../kotatsu/stats/data/StatsRepository.kt | 4 ++ .../kotatsu/stats/ui/StatsActivity.kt | 50 ++++++++++++++++++- .../kotatsu/stats/ui/StatsViewModel.kt | 25 ++++++++-- .../kotatsu/stats/ui/views/PieChartView.kt | 3 ++ app/src/main/res/layout/activity_stats.xml | 15 ++++++ app/src/main/res/menu/opt_stats.xml | 12 +++++ app/src/main/res/values/strings.xml | 3 ++ 8 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 app/src/main/res/menu/opt_stats.xml 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 c629bbbbe..72223485e 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 @@ -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) } 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 eaaa89b94..43dbffbec 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 @@ -44,4 +44,8 @@ class StatsRepository @Inject constructor( } time } + + suspend fun clearStats() { + db.getStatsDao().clear() + } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/StatsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/StatsActivity.kt index bd95442ef..5759771b2 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/StatsActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/StatsActivity.kt @@ -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(), OnListItemClickListener { +class StatsActivity : BaseActivity(), OnListItemClickListener, + PieChartView.OnSegmentClickListener { private val viewModel: StatsViewModel by viewModels() @@ -33,6 +43,11 @@ class StatsActivity : BaseActivity(), OnListItemClickListe val adapter = BaseListAdapter() .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(), 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() + } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/StatsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/StatsViewModel.kt index 2188dca80..7904d7c24 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/StatsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/StatsViewModel.kt @@ -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() + val readingStats = MutableStateFlow>(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)) + } + } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/views/PieChartView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/views/PieChartView.kt index 30fad194a..526728ccc 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/views/PieChartView.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/stats/ui/views/PieChartView.kt @@ -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 diff --git a/app/src/main/res/layout/activity_stats.xml b/app/src/main/res/layout/activity_stats.xml index b33e94aa3..e02466630 100644 --- a/app/src/main/res/layout/activity_stats.xml +++ b/app/src/main/res/layout/activity_stats.xml @@ -26,6 +26,21 @@ + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a2d905ab8..bd2f9b5b4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -608,4 +608,7 @@ Other manga Less than a minute Statistics + Clear statistics + Statistics cleared + Do you really want to clear all reading statistics? This action cannot be undone.