Skip to content

Commit

Permalink
Automatically delete 'stale'/old widgets from database (#2702)
Browse files Browse the repository at this point in the history
Automatically delete stale widgets from database

 - Automatically removes widgets that are no longer bound to the widget provider but that are still in the database -> 'stale'/old widgets will no longer cause unnecessary updates
  • Loading branch information
jpelgrom committed Jul 29, 2022
1 parent 2e7c724 commit 1cf3506
Show file tree
Hide file tree
Showing 18 changed files with 59 additions and 95 deletions.
Original file line number Diff line number Diff line change
@@ -1,49 +1,17 @@
package io.homeassistant.companion.android.widgets

import android.appwidget.AppWidgetManager
import android.content.Context
import android.view.View
import android.widget.Toast
import androidx.lifecycle.lifecycleScope
import io.homeassistant.companion.android.BaseActivity
import io.homeassistant.companion.android.common.R
import io.homeassistant.companion.android.database.widget.WidgetDao
import kotlinx.coroutines.launch

abstract class BaseWidgetConfigureActivity : BaseActivity() {

protected var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID

abstract val dao: WidgetDao

protected val onDeleteWidget = View.OnClickListener { deleteConfirmation(it.context) }

private fun deleteConfirmation(context: Context) {
val builder: android.app.AlertDialog.Builder = android.app.AlertDialog.Builder(context)

builder.setTitle(R.string.confirm_delete_this_widget_title)
builder.setMessage(R.string.confirm_delete_this_widget_message)

builder.setPositiveButton(
R.string.confirm_positive
) { dialog, _ ->
lifecycleScope.launch {
dao.delete(appWidgetId)
dialog.dismiss()
finish()
}
}

builder.setNegativeButton(
R.string.confirm_negative
) { dialog, _ -> // Do nothing
dialog.dismiss()
}

val alert: android.app.AlertDialog? = builder.create()
alert?.show()
}

protected fun showAddWidgetError() {
Toast.makeText(applicationContext, R.string.widget_creation_error, Toast.LENGTH_LONG).show()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package io.homeassistant.companion.android.widgets

import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.RemoteViews
import io.homeassistant.companion.android.common.data.integration.Entity
import io.homeassistant.companion.android.common.data.integration.IntegrationRepository
Expand Down Expand Up @@ -92,7 +94,22 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
private suspend fun updateAllWidgets(
context: Context
) {
getAllWidgetIds(context).forEach {
val widgetProvider = getWidgetProvider(context)
val systemWidgetIds = AppWidgetManager.getInstance(context)
.getAppWidgetIds(widgetProvider)
.toSet()
val dbWidgetIds = getAllWidgetIds(context)

val invalidWidgetIds = dbWidgetIds.minus(systemWidgetIds)
if (invalidWidgetIds.isNotEmpty()) {
Log.i(
widgetProvider.shortClassName,
"Found widgets $invalidWidgetIds in database, but not in AppWidgetManager - sending onDeleted"
)
onDeleted(context, invalidWidgetIds.toIntArray())
}

dbWidgetIds.filter { systemWidgetIds.contains(it) }.forEach {
updateView(context, it)
}
}
Expand All @@ -108,6 +125,7 @@ abstract class BaseWidgetProvider : AppWidgetProvider() {
}
}

abstract fun getWidgetProvider(context: Context): ComponentName
abstract suspend fun getWidgetRemoteViews(context: Context, appWidgetId: Int, suggestedEntity: Entity<Map<String, Any>>? = null): RemoteViews
abstract suspend fun getAllWidgetIds(context: Context): List<Int>
abstract fun saveEntityConfiguration(context: Context, extras: Bundle?, appWidgetId: Int)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package io.homeassistant.companion.android.widgets.button
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.graphics.Color
Expand Down Expand Up @@ -85,10 +86,21 @@ class ButtonWidget : AppWidgetProvider() {

private fun updateAllWidgets(context: Context) {
mainScope.launch {
val buttonWidgetEntityList = buttonWidgetDao.getAll()
val appWidgetManager = AppWidgetManager.getInstance(context)
val systemWidgetIds = appWidgetManager.getAppWidgetIds(ComponentName(context, ButtonWidget::class.java))
val dbWidgetList = buttonWidgetDao.getAll()

val invalidWidgetIds = dbWidgetList
.filter { !systemWidgetIds.contains(it.id) }
.map { it.id }
if (invalidWidgetIds.isNotEmpty()) {
Log.i(TAG, "Found widgets $invalidWidgetIds in database, but not in AppWidgetManager - sending onDeleted")
onDeleted(context, invalidWidgetIds.toIntArray())
}

val buttonWidgetEntityList = dbWidgetList.filter { systemWidgetIds.contains(it.id) }
if (buttonWidgetEntityList.isNotEmpty()) {
Log.d(TAG, "Updating all widgets")
val appWidgetManager = AppWidgetManager.getInstance(context)
for (item in buttonWidgetEntityList) {
val views = getWidgetRemoteViews(context, item.id)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,6 @@ class ButtonWidgetConfigureActivity : BaseWidgetConfigureActivity(), IconDialog.
buttonWidget.textColor?.let { it.toColorInt() == ContextCompat.getColor(this, commonR.color.colorWidgetButtonLabelBlack) } ?: false

binding.addButton.setText(commonR.string.update_widget)
binding.deleteButton.visibility = VISIBLE
binding.deleteButton.setOnClickListener(onDeleteWidget)
} else {
binding.backgroundType.setSelection(0)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package io.homeassistant.companion.android.widgets.camera
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.net.ConnectivityManager
Expand Down Expand Up @@ -84,10 +85,21 @@ class CameraWidget : AppWidgetProvider() {

private fun updateAllWidgets(context: Context) {
mainScope.launch {
val cameraWidgetList = cameraWidgetDao.getAll()
val appWidgetManager = AppWidgetManager.getInstance(context)
val systemWidgetIds = appWidgetManager.getAppWidgetIds(ComponentName(context, CameraWidget::class.java))
val dbWidgetList = cameraWidgetDao.getAll()

val invalidWidgetIds = dbWidgetList
.filter { !systemWidgetIds.contains(it.id) }
.map { it.id }
if (invalidWidgetIds.isNotEmpty()) {
Log.i(TAG, "Found widgets $invalidWidgetIds in database, but not in AppWidgetManager - sending onDeleted")
onDeleted(context, invalidWidgetIds.toIntArray())
}

val cameraWidgetList = dbWidgetList.filter { systemWidgetIds.contains(it.id) }
if (cameraWidgetList.isNotEmpty()) {
Log.d(TAG, "Updating all widgets")
val appWidgetManager = AppWidgetManager.getInstance(context)
for (item in cameraWidgetList) {
updateAppWidget(context, item.id, appWidgetManager)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,6 @@ class CameraWidgetConfigureActivity : BaseWidgetConfigureActivity() {
if (cameraWidget != null) {
binding.widgetTextConfigEntityId.setText(cameraWidget.entityId)
binding.addButton.setText(commonR.string.update_widget)
binding.deleteButton.visibility = View.VISIBLE
binding.deleteButton.setOnClickListener(onDeleteWidget)
val entity = runBlocking {
try {
integrationUseCase.getEntity(cameraWidget.entityId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.homeassistant.companion.android.widgets.entity

import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.Color
Expand Down Expand Up @@ -46,6 +47,9 @@ class EntityWidget : BaseWidgetProvider() {
@Inject
lateinit var staticWidgetDao: StaticWidgetDao

override fun getWidgetProvider(context: Context): ComponentName =
ComponentName(context, EntityWidget::class.java)

override suspend fun getWidgetRemoteViews(context: Context, appWidgetId: Int, suggestedEntity: Entity<Map<String, Any>>?): RemoteViews {
val intent = Intent(context, EntityWidget::class.java).apply {
action = UPDATE_VIEW
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,6 @@ class EntityWidgetConfigureActivity : BaseWidgetConfigureActivity() {
staticWidget.textColor?.let { it.toColorInt() == ContextCompat.getColor(this, commonR.color.colorWidgetButtonLabelBlack) } ?: false

binding.addButton.setText(commonR.string.update_widget)
binding.deleteButton.visibility = VISIBLE
binding.deleteButton.setOnClickListener(onDeleteWidget)
} else {
binding.backgroundType.setSelection(0)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.homeassistant.companion.android.widgets.media_player_controls

import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
Expand Down Expand Up @@ -71,6 +72,9 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
@Inject
lateinit var mediaPlayCtrlWidgetDao: MediaPlayerControlsWidgetDao

override fun getWidgetProvider(context: Context): ComponentName =
ComponentName(context, MediaPlayerControlsWidget::class.java)

override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,6 @@ class MediaPlayerControlsWidgetConfigureActivity : BaseWidgetConfigureActivity()
if (entities != null)
selectedEntities.addAll(entities)
binding.addButton.setText(commonR.string.update_widget)
binding.deleteButton.visibility = View.VISIBLE
binding.deleteButton.setOnClickListener(onDeleteWidget)
}
val entityAdapter = SingleItemArrayAdapter<Entity<Any>>(this) { it?.entityId ?: "" }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.homeassistant.companion.android.widgets.template

import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.Color
Expand Down Expand Up @@ -46,6 +47,9 @@ class TemplateWidget : BaseWidgetProvider() {
}
}

override fun getWidgetProvider(context: Context): ComponentName =
ComponentName(context, TemplateWidget::class.java)

override suspend fun getAllWidgetIds(context: Context): List<Int> {
return templateWidgetDao.getAll().map { it.id }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,6 @@ class TemplateWidgetConfigureActivity : BaseWidgetConfigureActivity() {
templateWidget.textColor?.let { it.toColorInt() == ContextCompat.getColor(this, android.R.color.white) } ?: true
binding.textColorBlack.isChecked =
templateWidget.textColor?.let { it.toColorInt() == ContextCompat.getColor(this, commonR.color.colorWidgetButtonLabelBlack) } ?: false

binding.deleteButton.visibility = View.VISIBLE
binding.deleteButton.setOnClickListener(onDeleteWidget)
} else {
binding.backgroundType.setSelection(0)
}
Expand Down
9 changes: 0 additions & 9 deletions app/src/main/res/layout/widget_button_configure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -171,14 +171,5 @@
android:layout_marginTop="8dp"
android:text="@string/add_widget" />

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/delete_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="8dp"
android:visibility="gone"
android:text="@string/delete_widget" />

</LinearLayout>
</androidx.core.widget.NestedScrollView>
9 changes: 0 additions & 9 deletions app/src/main/res/layout/widget_camera_configure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,5 @@
android:layout_marginTop="8dp"
android:text="@string/add_widget" />

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/delete_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="8dp"
android:visibility="gone"
android:text="@string/delete_widget" />

</LinearLayout>
</androidx.core.widget.NestedScrollView>
8 changes: 0 additions & 8 deletions app/src/main/res/layout/widget_media_controls_configure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,5 @@
android:layout_gravity="end"
android:layout_marginTop="8dp"
android:text="@string/add_widget" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/delete_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="8dp"
android:visibility="gone"
android:text="@string/delete_widget" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
9 changes: 0 additions & 9 deletions app/src/main/res/layout/widget_static_configure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -235,15 +235,6 @@
android:layout_gravity="end"
android:layout_marginTop="8dp"
android:text="@string/add_widget" />

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/delete_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="8dp"
android:visibility="gone"
android:text="@string/delete_widget" />
</LinearLayout>

</androidx.core.widget.NestedScrollView>
9 changes: 0 additions & 9 deletions app/src/main/res/layout/widget_template_configure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,6 @@
android:layout_gravity="end"
android:layout_marginTop="8dp"
android:text="@string/add_widget" />

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/delete_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="8dp"
android:visibility="gone"
android:text="@string/delete_widget" />
</LinearLayout>

</androidx.core.widget.NestedScrollView>
3 changes: 0 additions & 3 deletions common/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,6 @@
<string name="confirm_delete_all_notification_title">Confirm deleting all notifications</string>
<string name="confirm_delete_this_notification_message">Are you sure? This cannot be undone</string>
<string name="confirm_delete_this_notification_title">Confirm deleting this notification</string>
<string name="confirm_delete_this_widget_message">Are you sure? This cannot be undone. If you accidentally deleted the wrong widget you will need to remove the bad widget from the home screen and create a new one.</string>
<string name="confirm_delete_this_widget_title">Confirm deleting this widget</string>
<string name="confirm_negative">NO</string>
<string name="confirm_positive">YES</string>
<string name="continue_on_phone">Continue on your phone</string>
Expand All @@ -138,7 +136,6 @@
<string name="delete_all_notifications">Delete all notifications from history</string>
<string name="delete_shortcut">Delete Shortcut</string>
<string name="delete_this_notification">Delete this notification from history</string>
<string name="delete_widget">Delete Widget</string>
<string name="description">Description</string>
<string name="details">Details</string>
<string name="developer_tools">Developer Tools</string>
Expand Down

0 comments on commit 1cf3506

Please sign in to comment.