diff --git a/app/src/main/java/io/github/wulkanowy/di/AppModule.kt b/app/src/main/java/io/github/wulkanowy/di/AppModule.kt index 272cd94a..64ec1cbc 100644 --- a/app/src/main/java/io/github/wulkanowy/di/AppModule.kt +++ b/app/src/main/java/io/github/wulkanowy/di/AppModule.kt @@ -1,5 +1,6 @@ package io.github.wulkanowy.di +import android.appwidget.AppWidgetManager import android.content.Context import com.firebase.jobdispatcher.FirebaseJobDispatcher import com.firebase.jobdispatcher.GooglePlayDriver @@ -37,6 +38,10 @@ internal class AppModule { @Provides fun provideFirebaseAnalyticsHelper(context: Context) = FirebaseAnalyticsHelper(FirebaseAnalytics.getInstance(context)) + @Singleton + @Provides + fun provideAppWidgetManager(context: Context) = AppWidgetManager.getInstance(context) + @Singleton @Named("isDebug") @Provides diff --git a/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetFactory.kt b/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetFactory.kt index 7210b053..ce23a11f 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetFactory.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetFactory.kt @@ -64,7 +64,7 @@ class TimetableWidgetFactory( } override fun getViewAt(position: Int): RemoteViews? { - if (position == INVALID_POSITION || lessons.getOrNull(position) == null) return null + if (position == INVALID_POSITION || lessons.getOrNull(position) === null) return null return RemoteViews(context.packageName, R.layout.item_widget_timetable).apply { lessons[position].let { diff --git a/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetProvider.kt b/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetProvider.kt index c13f9d59..79d34c70 100644 --- a/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetProvider.kt +++ b/app/src/main/java/io/github/wulkanowy/ui/widgets/timetable/TimetableWidgetProvider.kt @@ -3,9 +3,11 @@ package io.github.wulkanowy.ui.widgets.timetable import android.app.PendingIntent import android.app.PendingIntent.FLAG_UPDATE_CURRENT import android.appwidget.AppWidgetManager +import android.appwidget.AppWidgetManager.ACTION_APPWIDGET_DELETED import android.appwidget.AppWidgetManager.ACTION_APPWIDGET_UPDATE +import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_IDS -import android.appwidget.AppWidgetProvider +import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.widget.RemoteViews @@ -22,9 +24,13 @@ import io.github.wulkanowy.utils.previousSchoolDay import io.github.wulkanowy.utils.toFormattedString import io.github.wulkanowy.utils.weekDayName import org.threeten.bp.LocalDate +import org.threeten.bp.LocalDate.now import javax.inject.Inject -class TimetableWidgetProvider : AppWidgetProvider() { +class TimetableWidgetProvider : BroadcastReceiver() { + + @Inject + lateinit var appWidgetManager: AppWidgetManager @Inject lateinit var sharedPref: SharedPrefHelper @@ -42,89 +48,79 @@ class TimetableWidgetProvider : AppWidgetProvider() { const val BUTTON_PREV = "buttonPrev" const val BUTTON_RESET = "buttonReset" + + fun createWidgetKey(appWidgetId: Int) = "timetable_widget_$appWidgetId" } - override fun onUpdate(context: Context?, appWidgetManager: AppWidgetManager?, appWidgetIds: IntArray?) { - appWidgetIds?.forEach { - val widgetKey = "timetable_widget_$it" - checkSavedWidgetDate(widgetKey) - - val savedDate = LocalDate.ofEpochDay(sharedPref.getLong(widgetKey, 0)) - context?.run { - RemoteViews(packageName, R.layout.widget_timetable).apply { - setTextViewText(R.id.timetableWidgetDay, savedDate.weekDayName.capitalize()) - setTextViewText(R.id.timetableWidgetDate, savedDate.toFormattedString()) - setEmptyView(R.id.timetableWidgetList, R.id.timetableWidgetEmpty) - setRemoteAdapter(R.id.timetableWidgetList, Intent(context, TimetableWidgetService::class.java) - .apply { action = widgetKey }) - setOnClickPendingIntent(R.id.timetableWidgetNext, createNavIntent(context, it, it, appWidgetIds, BUTTON_NEXT)) - setOnClickPendingIntent(R.id.timetableWidgetPrev, createNavIntent(context, -it, it, appWidgetIds, BUTTON_PREV)) - createNavIntent(context, Int.MAX_VALUE, it, appWidgetIds, BUTTON_RESET).let { intent -> - setOnClickPendingIntent(R.id.timetableWidgetDate, intent) - setOnClickPendingIntent(R.id.timetableWidgetDay, intent) - } - setPendingIntentTemplate(R.id.timetableWidgetList, - PendingIntent.getActivity(context, 1, MainActivity.getStartIntent(context).apply { - putExtra(EXTRA_START_MENU_INDEX, 3) - }, FLAG_UPDATE_CURRENT)) - - }.also { view -> - appWidgetManager?.apply { - notifyAppWidgetViewDataChanged(it, R.id.timetableWidgetList) - updateAppWidget(it, view) - } - } - } - } - } - - override fun onReceive(context: Context?, intent: Intent?) { + override fun onReceive(context: Context, intent: Intent) { AndroidInjection.inject(this, context) - intent?.let { - val widgetKey = "timetable_widget_${it.getIntExtra(EXTRA_TOGGLED_WIDGET_ID, 0)}" - it.getStringExtra(EXTRA_BUTTON_TYPE).let { button -> - when (button) { - BUTTON_NEXT -> { - LocalDate.ofEpochDay(sharedPref.getLong(widgetKey, 0)).nextSchoolDay - .let { date -> sharedPref.putLong(widgetKey, date.toEpochDay(), true) } - } - BUTTON_PREV -> { - LocalDate.ofEpochDay(sharedPref.getLong(widgetKey, 0)).previousSchoolDay - .let { date -> sharedPref.putLong(widgetKey, date.toEpochDay(), true) } - } - BUTTON_RESET -> sharedPref.putLong(widgetKey, LocalDate.now().nextOrSameSchoolDay.toEpochDay(), true) - } - button?.also { btn -> - if (btn.isNotBlank()) { - analytics.logEvent("changed_timetable_widget_day", "button" to button) - } - } + when (intent.action) { + ACTION_APPWIDGET_UPDATE -> onUpdate(context, intent) + ACTION_APPWIDGET_DELETED -> onDelete(intent) + } + } + + private fun onUpdate(context: Context, intent: Intent) { + if (intent.getStringExtra(EXTRA_BUTTON_TYPE) === null) { + intent.getIntArrayExtra(EXTRA_APPWIDGET_IDS).forEach { appWidgetId -> + updateWidget(context, appWidgetId, now().nextOrSameSchoolDay) + } + } else { + val buttonType = intent.getStringExtra(EXTRA_BUTTON_TYPE) + val toggledWidgetId = intent.getIntExtra(EXTRA_TOGGLED_WIDGET_ID, 0) + val savedDate = LocalDate.ofEpochDay(sharedPref.getLong(createWidgetKey(toggledWidgetId), 0)) + val date = when (buttonType) { + BUTTON_RESET -> now().nextOrSameSchoolDay + BUTTON_NEXT -> savedDate.nextSchoolDay + BUTTON_PREV -> savedDate.previousSchoolDay + else -> now().nextOrSameSchoolDay + } + if (!buttonType.isNullOrBlank()) analytics.logEvent("changed_timetable_widget_day", "button" to buttonType) + updateWidget(context, toggledWidgetId, date) + } + } + + private fun onDelete(intent: Intent) { + intent.getIntExtra(EXTRA_APPWIDGET_ID, 0).let { + if (it != 0) sharedPref.delete(createWidgetKey(it)) + } + } + + private fun updateWidget(context: Context, appWidgetId: Int, date: LocalDate) { + RemoteViews(context.packageName, R.layout.widget_timetable).apply { + setEmptyView(R.id.timetableWidgetList, R.id.timetableWidgetEmpty) + setTextViewText(R.id.timetableWidgetDay, date.weekDayName.capitalize()) + setTextViewText(R.id.timetableWidgetDate, date.toFormattedString()) + setRemoteAdapter(R.id.timetableWidgetList, Intent(context, TimetableWidgetService::class.java) + .apply { action = createWidgetKey(appWidgetId) }) + setOnClickPendingIntent(R.id.timetableWidgetNext, createNavIntent(context, appWidgetId, appWidgetId, BUTTON_NEXT)) + setOnClickPendingIntent(R.id.timetableWidgetPrev, createNavIntent(context, -appWidgetId, appWidgetId, BUTTON_PREV)) + createNavIntent(context, Int.MAX_VALUE, appWidgetId, BUTTON_RESET).also { + setOnClickPendingIntent(R.id.timetableWidgetDate, it) + setOnClickPendingIntent(R.id.timetableWidgetDay, it) + } + setPendingIntentTemplate(R.id.timetableWidgetList, + PendingIntent.getActivity(context, 1, MainActivity.getStartIntent(context).apply { + putExtra(EXTRA_START_MENU_INDEX, 3) + }, FLAG_UPDATE_CURRENT)) + }.also { + sharedPref.putLong(createWidgetKey(appWidgetId), date.toEpochDay(), true) + appWidgetManager.apply { + notifyAppWidgetViewDataChanged(appWidgetId, R.id.timetableWidgetList) + updateAppWidget(appWidgetId, it) } } - super.onReceive(context, intent) } - override fun onDeleted(context: Context?, appWidgetIds: IntArray?) { - appWidgetIds?.forEach { - sharedPref.delete("timetable_widget_$it") - } - } - - private fun createNavIntent(context: Context, code: Int, widgetId: Int, widgetIds: IntArray, buttonType: String): PendingIntent { + private fun createNavIntent(context: Context, code: Int, appWidgetId: Int, buttonType: String): PendingIntent { return PendingIntent.getBroadcast(context, code, Intent(context, TimetableWidgetProvider::class.java).apply { action = ACTION_APPWIDGET_UPDATE - putExtra(EXTRA_APPWIDGET_IDS, widgetIds) putExtra(EXTRA_BUTTON_TYPE, buttonType) - putExtra(EXTRA_TOGGLED_WIDGET_ID, widgetId) + putExtra(EXTRA_TOGGLED_WIDGET_ID, appWidgetId) }, FLAG_UPDATE_CURRENT) } - - private fun checkSavedWidgetDate(widgetKey: String) { - sharedPref.run { - if (getLong(widgetKey, -1) == -1L) { - putLong(widgetKey, LocalDate.now().nextOrSameSchoolDay.toEpochDay(), true) - } - } - } } + + +