Skip to content

Commit

Permalink
Integrated ChangeSubscriber for DeckPickerWidget updates on study …
Browse files Browse the repository at this point in the history
…queue changes

 - Added `ChangeSubscriber` object to subscribe to `ChangeManager` and monitor changes in the study queue (`OpChanges.studyQueues`).
 - Implemented `opExecuted` in `ChangeSubscriber` to trigger `updateDeckPickerWidgets()` when relevant changes are detected.
  • Loading branch information
xenonnn4w committed Aug 22, 2024
1 parent 1f1977d commit 746944d
Showing 1 changed file with 83 additions and 0 deletions.
83 changes: 83 additions & 0 deletions AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package com.ichi2.anki

import android.app.Activity
import android.app.Application
import android.appwidget.AppWidgetManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
Expand All @@ -34,6 +36,7 @@ import androidx.core.content.edit
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.MutableLiveData
import androidx.work.Configuration
import anki.collection.OpChanges
import com.ichi2.anki.CrashReportService.sendExceptionReport
import com.ichi2.anki.analytics.UsageAnalytics
import com.ichi2.anki.browser.SharedPreferencesLastDeckIdRepository
Expand All @@ -53,11 +56,14 @@ import com.ichi2.anki.services.NotificationService
import com.ichi2.anki.ui.dialogs.ActivityAgnosticDialogs
import com.ichi2.annotations.NeedsTest
import com.ichi2.compat.CompatHelper
import com.ichi2.libanki.ChangeManager
import com.ichi2.utils.AdaptionUtil
import com.ichi2.utils.ExceptionUtil
import com.ichi2.utils.KotlinCleanup
import com.ichi2.utils.LanguageUtil
import com.ichi2.utils.Permissions
import com.ichi2.widget.DeckPickerWidget
import com.ichi2.widget.WidgetPreferences
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
Expand Down Expand Up @@ -117,6 +123,8 @@ open class AnkiDroidApp : Application(), Configuration.Provider {
// Get preferences
val preferences = this.sharedPrefs()

ChangeSubscriber.initialize(this)

CrashReportService.initialize(this)
val logType = LogType.value
when (logType) {
Expand Down Expand Up @@ -280,6 +288,81 @@ open class AnkiDroidApp : Application(), Configuration.Provider {
}
}

/**
* `ChangeSubscriber` is a singleton object that subscribes to changes in the `ChangeManager`
* and updates the Deck Picker Widgets when relevant changes occur.
*
* This object is designed to be initialized with an `Application` context, allowing it
* to manage widget updates efficiently across the application lifecycle.
*/
object ChangeSubscriber : ChangeManager.Subscriber {

/**
* Application context for accessing resources and system services.
*/
private lateinit var application: Application

/**
* Initializes the `ChangeSubscriber` with the provided [app] context and subscribes to
* the `ChangeManager`. This method must be called before any changes are detected.
*
* @param app The application context used to manage widget updates.
*/
fun initialize(app: Application) {
Timber.d("Initializing ChangeSubscriber")
application = app
ChangeManager.subscribe(this)
}

/**
* Callback method invoked when operations that affect the app state are executed.
* If relevant changes related to the study queues are detected, the Deck Picker Widgets
* are updated accordingly.
*
* @param changes The set of changes that occurred.
* @param handler An optional handler that can be used for custom processing (unused here).
*/
override fun opExecuted(changes: OpChanges, handler: Any?) {
Timber.d("ChangeSubscriber - opExecuted called with changes: $changes")
if (changes.studyQueues) {
updateDeckPickerWidgets()
} else {
Timber.d("No relevant changes to update the widget")
}
}

/**
* Updates the Deck Picker Widgets based on the current state of the application.
* It fetches the App Widget IDs and updates each widget with the associated deck IDs.
*/
private fun updateDeckPickerWidgets() {
val context = application.applicationContext
val appWidgetManager = AppWidgetManager.getInstance(context)

val provider = ComponentName(context, DeckPickerWidget::class.java)
Timber.d("Fetching appWidgetIds for provider: $provider")

val appWidgetIds = appWidgetManager.getAppWidgetIds(provider)
Timber.d("AppWidgetIds to update: ${appWidgetIds.joinToString(", ")}")

for (appWidgetId in appWidgetIds) {
val deckIds = fetchDeckIdsForWidget(appWidgetId)
DeckPickerWidget.updateWidget(context, appWidgetManager, appWidgetId, deckIds)
}
}

/**
* Fetches the selected deck IDs for the specified [appWidgetId] from the widget preferences.
*
* @param appWidgetId The ID of the widget for which to fetch the deck IDs.
* @return A `LongArray` of deck IDs associated with the widget.
*/
private fun fetchDeckIdsForWidget(appWidgetId: Int): LongArray {
val widgetPreferences = WidgetPreferences(application.applicationContext)
return widgetPreferences.getSelectedDeckIdsFromPreferencesDeckPickerWidget(appWidgetId)
}
}

companion object {

/**
Expand Down

0 comments on commit 746944d

Please sign in to comment.