Fix timetable widget automatic day switching (#267)

This commit is contained in:
Rafał Borcz 2019-03-07 16:38:34 +01:00 committed by Mikołaj Pich
parent 4f0021919c
commit 722f8d691a
3 changed files with 76 additions and 75 deletions

View File

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

View File

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

View File

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