Clearing stats

master
Koitharu 2 years ago
parent 101d357eff
commit 096f5b15dc
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

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

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

@ -1,19 +1,28 @@
package org.koitharu.kotatsu.stats.ui package org.koitharu.kotatsu.stats.ui
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.BaseFragment import org.koitharu.kotatsu.core.ui.BaseFragment
import org.koitharu.kotatsu.core.ui.BaseListAdapter import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener 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.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.databinding.ActivityStatsBinding
import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.details.ui.DetailsActivity
import org.koitharu.kotatsu.list.ui.adapter.ListItemType 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 import org.koitharu.kotatsu.stats.ui.views.PieChartView
@AndroidEntryPoint @AndroidEntryPoint
class StatsActivity : BaseActivity<ActivityStatsBinding>(), OnListItemClickListener<Manga> { class StatsActivity : BaseActivity<ActivityStatsBinding>(), OnListItemClickListener<Manga>,
PieChartView.OnSegmentClickListener {
private val viewModel: StatsViewModel by viewModels() private val viewModel: StatsViewModel by viewModels()
@ -33,6 +43,11 @@ class StatsActivity : BaseActivity<ActivityStatsBinding>(), OnListItemClickListe
val adapter = BaseListAdapter<StatsRecord>() val adapter = BaseListAdapter<StatsRecord>()
.addDelegate(ListItemType.FEED, statsAD(this)) .addDelegate(ListItemType.FEED, statsAD(this))
viewBinding.recyclerView.adapter = adapter 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) { viewModel.readingStats.observe(this) {
val sum = it.sumOf { it.duration } val sum = it.sumOf { it.duration }
viewBinding.chart.setData( viewBinding.chart.setData(
@ -54,4 +69,37 @@ class StatsActivity : BaseActivity<ActivityStatsBinding>(), OnListItemClickListe
override fun onItemClick(item: Manga, view: View) { override fun onItemClick(item: Manga, view: View) {
startActivity(DetailsActivity.newIntent(view.context, item)) 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()
}
} }

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

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

@ -26,6 +26,21 @@
</com.google.android.material.appbar.AppBarLayout> </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 <org.koitharu.kotatsu.stats.ui.views.PieChartView
android:id="@+id/chart" android:id="@+id/chart"
android:layout_width="0dp" android:layout_width="0dp"

@ -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>

@ -608,4 +608,7 @@
<string name="other_manga">Other manga</string> <string name="other_manga">Other manga</string>
<string name="less_than_minute">Less than a minute</string> <string name="less_than_minute">Less than a minute</string>
<string name="statistics">Statistics</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> </resources>

Loading…
Cancel
Save