mirror of https://github.com/tasks/tasks
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
222 lines
9.4 KiB
Kotlin
222 lines
9.4 KiB
Kotlin
package org.tasks.widget
|
|
|
|
import android.app.PendingIntent
|
|
import android.appwidget.AppWidgetManager
|
|
import android.appwidget.AppWidgetProvider
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.net.Uri
|
|
import android.os.Bundle
|
|
import android.view.View
|
|
import android.widget.RemoteViews
|
|
import androidx.annotation.ColorInt
|
|
import androidx.core.graphics.ColorUtils
|
|
import com.todoroo.andlib.utility.AndroidUtilities.atLeastS
|
|
import com.todoroo.astrid.api.Filter
|
|
import dagger.hilt.android.AndroidEntryPoint
|
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
|
import kotlinx.coroutines.runBlocking
|
|
import org.tasks.R
|
|
import org.tasks.dialogs.FilterPicker
|
|
import org.tasks.extensions.Context.isNightMode
|
|
import org.tasks.intents.TaskIntents
|
|
import org.tasks.preferences.DefaultFilterProvider
|
|
import org.tasks.preferences.Preferences
|
|
import org.tasks.themes.ThemeColor
|
|
import timber.log.Timber
|
|
import javax.inject.Inject
|
|
|
|
@AndroidEntryPoint
|
|
class TasksWidget : AppWidgetProvider() {
|
|
@Inject lateinit var preferences: Preferences
|
|
@Inject lateinit var defaultFilterProvider: DefaultFilterProvider
|
|
@Inject @ApplicationContext lateinit var context: Context
|
|
|
|
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
|
|
for (id in appWidgetIds) {
|
|
try {
|
|
val options = appWidgetManager.getAppWidgetOptions(id)
|
|
appWidgetManager.updateAppWidget(id, createScrollableWidget(context, id, options))
|
|
} catch (e: Exception) {
|
|
Timber.e(e)
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun onAppWidgetOptionsChanged(
|
|
context: Context,
|
|
appWidgetManager: AppWidgetManager,
|
|
appWidgetId: Int,
|
|
newOptions: Bundle?
|
|
) {
|
|
newOptions?.let {
|
|
appWidgetManager
|
|
.updateAppWidget(appWidgetId, createScrollableWidget(context, appWidgetId, it))
|
|
}
|
|
}
|
|
|
|
private fun createScrollableWidget(context: Context, id: Int, options: Bundle): RemoteViews {
|
|
val widgetPreferences = WidgetPreferences(context, preferences, id)
|
|
widgetPreferences.compact =
|
|
options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH) < COMPACT_MAX
|
|
val filterId = widgetPreferences.filterId
|
|
val color = ThemeColor(context, widgetPreferences.color)
|
|
val remoteViews = RemoteViews(context.packageName, R.layout.scrollable_widget)
|
|
if (widgetPreferences.showHeader()) {
|
|
remoteViews.setViewVisibility(R.id.widget_header, View.VISIBLE)
|
|
remoteViews.setViewVisibility(
|
|
R.id.widget_change_list,
|
|
if (widgetPreferences.showMenu()) View.VISIBLE else View.GONE
|
|
)
|
|
remoteViews.setViewVisibility(
|
|
R.id.widget_reconfigure,
|
|
if (widgetPreferences.showSettings()) View.VISIBLE else View.GONE
|
|
)
|
|
remoteViews.removeAllViews(R.id.title_container)
|
|
remoteViews.addView(
|
|
R.id.title_container,
|
|
RemoteViews(context.packageName, widgetPreferences.headerLayout)
|
|
)
|
|
val widgetPadding = context.resources.getDimension(R.dimen.widget_padding).toInt()
|
|
val widgetTitlePadding = if (widgetPreferences.showMenu()) 0 else widgetPadding
|
|
val vPad = widgetPreferences.headerSpacing
|
|
remoteViews.setViewPadding(R.id.widget_title, widgetTitlePadding, 0, 0, 0)
|
|
remoteViews.setInt(R.id.widget_title, "setTextColor", color.colorOnPrimary)
|
|
buttons.forEach {
|
|
remoteViews.setInt(it, "setColorFilter", color.colorOnPrimary)
|
|
remoteViews.setViewPadding(it, widgetPadding, vPad, widgetPadding, vPad)
|
|
}
|
|
} else {
|
|
remoteViews.setViewVisibility(R.id.widget_header, View.GONE)
|
|
}
|
|
remoteViews.setInt(
|
|
R.id.widget_header,
|
|
"setBackgroundColor",
|
|
ColorUtils.setAlphaComponent(color.primaryColor, widgetPreferences.headerOpacity))
|
|
val bgColor = getBackgroundColor(widgetPreferences.themeIndex)
|
|
remoteViews.setInt(
|
|
R.id.list_view,
|
|
"setBackgroundColor",
|
|
ColorUtils.setAlphaComponent(bgColor, widgetPreferences.rowOpacity))
|
|
remoteViews.setInt(
|
|
R.id.empty_view,
|
|
"setBackgroundColor",
|
|
ColorUtils.setAlphaComponent(bgColor, widgetPreferences.footerOpacity))
|
|
val filter = runBlocking { defaultFilterProvider.getFilterFromPreference(filterId) }
|
|
remoteViews.setTextViewText(R.id.widget_title, if (widgetPreferences.showTitle()) {
|
|
filter.title
|
|
} else {
|
|
null
|
|
})
|
|
val cacheBuster = Uri.parse("tasks://widget/" + System.currentTimeMillis())
|
|
remoteViews.setRemoteAdapter(
|
|
R.id.list_view,
|
|
Intent(context, ScrollableWidgetUpdateService::class.java)
|
|
.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id)
|
|
.setData(cacheBuster))
|
|
setRipple(
|
|
remoteViews, color, R.id.widget_button, R.id.widget_change_list, R.id.widget_reconfigure)
|
|
remoteViews.setOnClickPendingIntent(R.id.widget_title, getOpenListIntent(context, filter, id))
|
|
remoteViews.setViewVisibility(
|
|
R.id.widget_button,
|
|
if (filter.isWritable) View.VISIBLE else View.GONE
|
|
)
|
|
remoteViews.setOnClickPendingIntent(R.id.widget_button, getNewTaskIntent(context, filter, id))
|
|
remoteViews.setOnClickPendingIntent(R.id.widget_change_list, getChooseListIntent(context, filter, id))
|
|
remoteViews.setOnClickPendingIntent(
|
|
R.id.widget_reconfigure, getWidgetConfigIntent(context, id))
|
|
if (widgetPreferences.openOnFooterClick()) {
|
|
remoteViews.setOnClickPendingIntent(R.id.empty_view, getOpenListIntent(context, filter, id))
|
|
} else {
|
|
remoteViews.setOnClickPendingIntent(R.id.empty_view, null)
|
|
}
|
|
remoteViews.setPendingIntentTemplate(R.id.list_view, getPendingIntentTemplate(context))
|
|
return remoteViews
|
|
}
|
|
|
|
private fun setRipple(rv: RemoteViews, color: ThemeColor, vararg views: Int) {
|
|
val drawableRes = if (color.isDark) R.drawable.widget_ripple_circle_light else R.drawable.widget_ripple_circle_dark
|
|
for (view in views) {
|
|
rv.setInt(view, "setBackgroundResource", drawableRes)
|
|
}
|
|
}
|
|
|
|
@ColorInt
|
|
private fun getBackgroundColor(themeIndex: Int): Int {
|
|
val background: Int = when (themeIndex) {
|
|
1 -> android.R.color.black
|
|
2 -> R.color.md_background_dark
|
|
3 -> if (context.isNightMode) R.color.md_background_dark else android.R.color.white
|
|
else -> android.R.color.white
|
|
}
|
|
return context.getColor(background)
|
|
}
|
|
|
|
private fun getPendingIntentTemplate(context: Context): PendingIntent =
|
|
PendingIntent.getActivity(
|
|
context,
|
|
0,
|
|
Intent(context, WidgetClickActivity::class.java),
|
|
if (atLeastS())
|
|
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
|
else
|
|
PendingIntent.FLAG_UPDATE_CURRENT
|
|
)
|
|
|
|
private fun getOpenListIntent(context: Context, filter: Filter, widgetId: Int): PendingIntent {
|
|
val intent = TaskIntents.getTaskListIntent(context, filter)
|
|
intent.action = "open_list"
|
|
return PendingIntent.getActivity(
|
|
context,
|
|
widgetId,
|
|
intent,
|
|
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
|
)
|
|
}
|
|
|
|
private fun getNewTaskIntent(context: Context, filter: Filter, widgetId: Int): PendingIntent {
|
|
val intent = TaskIntents.getNewTaskIntent(context, filter, "widget")
|
|
intent.action = "new_task"
|
|
return PendingIntent.getActivity(
|
|
context,
|
|
widgetId,
|
|
intent,
|
|
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
|
)
|
|
}
|
|
|
|
private fun getWidgetConfigIntent(context: Context, widgetId: Int): PendingIntent {
|
|
val intent = Intent(context, WidgetConfigActivity::class.java)
|
|
intent.flags = flags
|
|
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId)
|
|
intent.action = "widget_settings"
|
|
return PendingIntent.getActivity(
|
|
context,
|
|
widgetId,
|
|
intent,
|
|
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
|
)
|
|
}
|
|
|
|
private fun getChooseListIntent(context: Context, filter: Filter, widgetId: Int): PendingIntent {
|
|
val intent = Intent(context, WidgetFilterSelectionActivity::class.java)
|
|
intent.flags = flags
|
|
intent.putExtra(FilterPicker.EXTRA_FILTER, filter)
|
|
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId)
|
|
intent.action = "choose_list"
|
|
return PendingIntent.getActivity(
|
|
context,
|
|
widgetId,
|
|
intent,
|
|
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
|
)
|
|
}
|
|
|
|
companion object {
|
|
private const val COMPACT_MAX = 275
|
|
private const val flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
|
private val buttons = intArrayOf(
|
|
R.id.widget_change_list, R.id.widget_button, R.id.widget_reconfigure
|
|
)
|
|
}
|
|
} |