151 lines
6.4 KiB
Kotlin
151 lines
6.4 KiB
Kotlin
package com.atridad.openclimb.widget
|
|
|
|
import android.app.PendingIntent
|
|
import android.appwidget.AppWidgetManager
|
|
import android.appwidget.AppWidgetProvider
|
|
import android.content.ComponentName
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.widget.RemoteViews
|
|
import com.atridad.openclimb.MainActivity
|
|
import com.atridad.openclimb.R
|
|
import com.atridad.openclimb.data.database.OpenClimbDatabase
|
|
import com.atridad.openclimb.data.repository.ClimbRepository
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.SupervisorJob
|
|
import kotlinx.coroutines.flow.first
|
|
import kotlinx.coroutines.launch
|
|
|
|
class ClimbStatsWidgetProvider : AppWidgetProvider() {
|
|
|
|
private val job = SupervisorJob()
|
|
private val coroutineScope = CoroutineScope(Dispatchers.IO + job)
|
|
|
|
override fun onUpdate(
|
|
context: Context,
|
|
appWidgetManager: AppWidgetManager,
|
|
appWidgetIds: IntArray
|
|
) {
|
|
for (appWidgetId in appWidgetIds) {
|
|
updateAppWidget(context, appWidgetManager, appWidgetId)
|
|
}
|
|
}
|
|
|
|
override fun onEnabled(context: Context) {}
|
|
|
|
override fun onDisabled(context: Context) {
|
|
job.cancel()
|
|
}
|
|
|
|
private fun updateAppWidget(
|
|
context: Context,
|
|
appWidgetManager: AppWidgetManager,
|
|
appWidgetId: Int
|
|
) {
|
|
coroutineScope.launch {
|
|
try {
|
|
val database = OpenClimbDatabase.getDatabase(context)
|
|
val repository = ClimbRepository(database, context)
|
|
|
|
// Fetch stats data
|
|
val sessions = repository.getAllSessions().first()
|
|
val problems = repository.getAllProblems().first()
|
|
val attempts = repository.getAllAttempts().first()
|
|
val gyms = repository.getAllGyms().first()
|
|
val activeSession = repository.getActiveSession()
|
|
|
|
// Calculate stats
|
|
val completedSessions = sessions.filter { it.endTime != null }
|
|
|
|
// Count problems that have been completed (have at least one successful attempt)
|
|
val completedProblems =
|
|
problems
|
|
.filter { problem ->
|
|
attempts.any { attempt ->
|
|
attempt.problemId == problem.id &&
|
|
(attempt.result ==
|
|
com.atridad.openclimb.data.model
|
|
.AttemptResult.SUCCESS ||
|
|
attempt.result ==
|
|
com.atridad.openclimb.data.model
|
|
.AttemptResult.FLASH)
|
|
}
|
|
}
|
|
.size
|
|
|
|
val favoriteGym =
|
|
sessions.groupBy { it.gymId }.maxByOrNull { it.value.size }?.let {
|
|
(gymId, _) ->
|
|
gyms.find { it.id == gymId }?.name
|
|
}
|
|
?: "No sessions yet"
|
|
|
|
launch(Dispatchers.Main) {
|
|
val views = RemoteViews(context.packageName, R.layout.widget_climb_stats)
|
|
|
|
views.setTextViewText(
|
|
R.id.widget_total_sessions,
|
|
completedSessions.size.toString()
|
|
)
|
|
views.setTextViewText(
|
|
R.id.widget_problems_completed,
|
|
completedProblems.toString()
|
|
)
|
|
views.setTextViewText(R.id.widget_total_problems, problems.size.toString())
|
|
views.setTextViewText(R.id.widget_favorite_gym, favoriteGym)
|
|
|
|
val intent = Intent(context, MainActivity::class.java)
|
|
val pendingIntent =
|
|
PendingIntent.getActivity(
|
|
context,
|
|
0,
|
|
intent,
|
|
PendingIntent.FLAG_UPDATE_CURRENT or
|
|
PendingIntent.FLAG_IMMUTABLE
|
|
)
|
|
views.setOnClickPendingIntent(R.id.widget_container, pendingIntent)
|
|
|
|
appWidgetManager.updateAppWidget(appWidgetId, views)
|
|
}
|
|
} catch (e: Exception) {
|
|
launch(Dispatchers.Main) {
|
|
val views = RemoteViews(context.packageName, R.layout.widget_climb_stats)
|
|
views.setTextViewText(R.id.widget_total_sessions, "0")
|
|
views.setTextViewText(R.id.widget_problems_completed, "0")
|
|
views.setTextViewText(R.id.widget_total_problems, "0")
|
|
views.setTextViewText(R.id.widget_favorite_gym, "No data")
|
|
|
|
val intent = Intent(context, MainActivity::class.java)
|
|
val pendingIntent =
|
|
PendingIntent.getActivity(
|
|
context,
|
|
0,
|
|
intent,
|
|
PendingIntent.FLAG_UPDATE_CURRENT or
|
|
PendingIntent.FLAG_IMMUTABLE
|
|
)
|
|
views.setOnClickPendingIntent(R.id.widget_container, pendingIntent)
|
|
|
|
appWidgetManager.updateAppWidget(appWidgetId, views)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
fun updateAllWidgets(context: Context) {
|
|
val appWidgetManager = AppWidgetManager.getInstance(context)
|
|
val componentName = ComponentName(context, ClimbStatsWidgetProvider::class.java)
|
|
val appWidgetIds = appWidgetManager.getAppWidgetIds(componentName)
|
|
|
|
val intent =
|
|
Intent(context, ClimbStatsWidgetProvider::class.java).apply {
|
|
action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
|
putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds)
|
|
}
|
|
context.sendBroadcast(intent)
|
|
}
|
|
}
|
|
}
|