feat: add per-widget configuration (#333)
* feat: add per-widget configuration * fix: no need to overengineer it * feat: add cache to bitmap download dfgdfg * fix: elvis has left the operation
This commit is contained in:
parent
47d05e737d
commit
f96d2ffaa5
5 changed files with 75 additions and 104 deletions
|
@ -1,33 +1,62 @@
|
|||
package ani.dantotsu.util
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.BitmapShader
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.graphics.RectF
|
||||
import android.graphics.Shader
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.collection.LruCache
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.io.InputStream
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
|
||||
class BitmapUtil {
|
||||
companion object {
|
||||
fun roundCorners(bitmap: Bitmap, cornerRadius: Float = 20f): Bitmap {
|
||||
val output = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(output)
|
||||
val paint = Paint()
|
||||
paint.isAntiAlias = true
|
||||
paint.shader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
|
||||
val rect = RectF(0f, 0f, bitmap.width.toFloat(), bitmap.height.toFloat())
|
||||
canvas.drawRoundRect(rect, cornerRadius, cornerRadius, paint)
|
||||
object BitmapUtil {
|
||||
private fun roundCorners(bitmap: Bitmap, cornerRadius: Float = 20f): Bitmap {
|
||||
val output = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(output)
|
||||
val paint = Paint()
|
||||
paint.isAntiAlias = true
|
||||
paint.shader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
|
||||
val rect = RectF(0f, 0f, bitmap.width.toFloat(), bitmap.height.toFloat())
|
||||
canvas.drawRoundRect(rect, cornerRadius, cornerRadius, paint)
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
fun convertDrawableToBitmap(drawable: Drawable, width: Int, height: Int): Bitmap {
|
||||
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(bitmap)
|
||||
drawable.setBounds(0, 0, canvas.width, canvas.height)
|
||||
drawable.draw(canvas)
|
||||
return bitmap
|
||||
return output
|
||||
}
|
||||
|
||||
private val cacheSize = (Runtime.getRuntime().maxMemory() / 1024 / 16).toInt()
|
||||
private val bitmapCache = LruCache<String, Bitmap>(cacheSize)
|
||||
|
||||
fun downloadImageAsBitmap(imageUrl: String): Bitmap? {
|
||||
var bitmap: Bitmap? = null
|
||||
|
||||
runBlocking(Dispatchers.IO) {
|
||||
val cacheName = imageUrl.substringAfterLast("/")
|
||||
bitmap = bitmapCache[cacheName]
|
||||
if (bitmap != null) return@runBlocking
|
||||
var inputStream: InputStream? = null
|
||||
var urlConnection: HttpURLConnection? = null
|
||||
try {
|
||||
val url = URL(imageUrl)
|
||||
urlConnection = url.openConnection() as HttpURLConnection
|
||||
urlConnection.requestMethod = "GET"
|
||||
urlConnection.connect()
|
||||
|
||||
if (urlConnection.responseCode == HttpURLConnection.HTTP_OK) {
|
||||
inputStream = urlConnection.inputStream
|
||||
bitmap = BitmapFactory.decodeStream(inputStream)
|
||||
bitmap?.let { bitmapCache.put(cacheName, it) }
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
inputStream?.close()
|
||||
urlConnection?.disconnect()
|
||||
}
|
||||
}
|
||||
return bitmap?.let { roundCorners(it) }
|
||||
}
|
||||
}
|
|
@ -60,7 +60,11 @@ class ProfileStatsConfigure : AppCompatActivity(),
|
|||
binding = StatisticsWidgetConfigureBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
val prefs = getSharedPreferences(ProfileStatsWidget.PREFS_NAME, Context.MODE_PRIVATE)
|
||||
appWidgetId = intent.getIntExtra(
|
||||
AppWidgetManager.EXTRA_APPWIDGET_ID,
|
||||
AppWidgetManager.INVALID_APPWIDGET_ID
|
||||
)
|
||||
val prefs = getSharedPreferences(ProfileStatsWidget.getPrefsName(appWidgetId), Context.MODE_PRIVATE)
|
||||
val topBackground = prefs.getInt(ProfileStatsWidget.PREF_BACKGROUND_COLOR, Color.parseColor("#80000000"))
|
||||
(binding.topBackgroundButton as MaterialButton).iconTint = ColorStateList.valueOf(topBackground)
|
||||
binding.topBackgroundButton.setOnClickListener {
|
||||
|
@ -192,7 +196,7 @@ class ProfileStatsConfigure : AppCompatActivity(),
|
|||
)
|
||||
val subTextColor = typedValueOutline.data
|
||||
|
||||
getSharedPreferences(ProfileStatsWidget.PREFS_NAME, Context.MODE_PRIVATE).edit().apply {
|
||||
getSharedPreferences(ProfileStatsWidget.getPrefsName(appWidgetId), Context.MODE_PRIVATE).edit().apply {
|
||||
putInt(ProfileStatsWidget.PREF_BACKGROUND_COLOR, backgroundColor)
|
||||
putInt(ProfileStatsWidget.PREF_BACKGROUND_FADE, backgroundColor)
|
||||
putInt(ProfileStatsWidget.PREF_TITLE_TEXT_COLOR, textColor)
|
||||
|
@ -204,12 +208,13 @@ class ProfileStatsConfigure : AppCompatActivity(),
|
|||
override fun onResult(dialogTag: String, which: Int, extras: Bundle): Boolean {
|
||||
if (which == SimpleDialog.OnDialogResultListener.BUTTON_POSITIVE) {
|
||||
if (!isMonetEnabled) {
|
||||
val prefs = getSharedPreferences(
|
||||
ProfileStatsWidget.getPrefsName(appWidgetId),
|
||||
Context.MODE_PRIVATE
|
||||
)
|
||||
when (dialogTag) {
|
||||
ProfileStatsWidget.PREF_BACKGROUND_COLOR -> {
|
||||
getSharedPreferences(
|
||||
ProfileStatsWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
prefs.edit()
|
||||
.putInt(
|
||||
ProfileStatsWidget.PREF_BACKGROUND_COLOR,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
|
@ -220,10 +225,7 @@ class ProfileStatsConfigure : AppCompatActivity(),
|
|||
}
|
||||
|
||||
ProfileStatsWidget.PREF_BACKGROUND_FADE -> {
|
||||
getSharedPreferences(
|
||||
ProfileStatsWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
prefs.edit()
|
||||
.putInt(
|
||||
ProfileStatsWidget.PREF_BACKGROUND_FADE,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
|
@ -234,10 +236,7 @@ class ProfileStatsConfigure : AppCompatActivity(),
|
|||
}
|
||||
|
||||
ProfileStatsWidget.PREF_TITLE_TEXT_COLOR -> {
|
||||
getSharedPreferences(
|
||||
ProfileStatsWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
prefs.edit()
|
||||
.putInt(
|
||||
ProfileStatsWidget.PREF_TITLE_TEXT_COLOR,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
|
@ -248,10 +247,7 @@ class ProfileStatsConfigure : AppCompatActivity(),
|
|||
}
|
||||
|
||||
ProfileStatsWidget.PREF_STATS_TEXT_COLOR -> {
|
||||
getSharedPreferences(
|
||||
ProfileStatsWidget.PREFS_NAME,
|
||||
Context.MODE_PRIVATE
|
||||
).edit()
|
||||
prefs.edit()
|
||||
.putInt(
|
||||
ProfileStatsWidget.PREF_STATS_TEXT_COLOR,
|
||||
extras.getInt(SimpleColorDialog.COLOR)
|
||||
|
|
|
@ -5,28 +5,24 @@ import android.appwidget.AppWidgetManager
|
|||
import android.appwidget.AppWidgetProvider
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.net.Uri
|
||||
import android.widget.RemoteViews
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import ani.dantotsu.MainActivity
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.profile.ProfileActivity
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.util.BitmapUtil
|
||||
import ani.dantotsu.util.BitmapUtil.Companion.downloadImageAsBitmap
|
||||
import ani.dantotsu.widgets.WidgetSizeProvider
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import tachiyomi.core.util.lang.launchIO
|
||||
import java.io.InputStream
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
|
||||
/**
|
||||
* Implementation of App Widget functionality.
|
||||
|
@ -56,32 +52,6 @@ class ProfileStatsWidget : AppWidgetProvider() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
private fun downloadImageAsBitmap(imageUrl: String): Bitmap? {
|
||||
var bitmap: Bitmap? = null
|
||||
|
||||
runBlocking(Dispatchers.IO) {
|
||||
var inputStream: InputStream? = null
|
||||
var urlConnection: HttpURLConnection? = null
|
||||
try {
|
||||
val url = URL(imageUrl)
|
||||
urlConnection = url.openConnection() as HttpURLConnection
|
||||
urlConnection.requestMethod = "GET"
|
||||
urlConnection.connect()
|
||||
|
||||
if (urlConnection.responseCode == HttpURLConnection.HTTP_OK) {
|
||||
inputStream = urlConnection.inputStream
|
||||
bitmap = BitmapFactory.decodeStream(inputStream)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
inputStream?.close()
|
||||
urlConnection?.disconnect()
|
||||
}
|
||||
}
|
||||
return bitmap?.let { BitmapUtil.roundCorners(it) }
|
||||
}
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
fun updateAppWidget(
|
||||
context: Context,
|
||||
|
@ -89,7 +59,7 @@ class ProfileStatsWidget : AppWidgetProvider() {
|
|||
appWidgetId: Int
|
||||
) {
|
||||
|
||||
val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
||||
val prefs = context.getSharedPreferences(getPrefsName(appWidgetId), Context.MODE_PRIVATE)
|
||||
val backgroundColor =
|
||||
prefs.getInt(PREF_BACKGROUND_COLOR, Color.parseColor("#80000000"))
|
||||
val backgroundFade = prefs.getInt(PREF_BACKGROUND_FADE, Color.parseColor("#00000000"))
|
||||
|
@ -120,8 +90,7 @@ class ProfileStatsWidget : AppWidgetProvider() {
|
|||
val views = RemoteViews(context.packageName, R.layout.statistics_widget).apply {
|
||||
setImageViewBitmap(
|
||||
R.id.backgroundView,
|
||||
BitmapUtil.convertDrawableToBitmap(
|
||||
gradientDrawable,
|
||||
gradientDrawable.toBitmap(
|
||||
width,
|
||||
height
|
||||
)
|
||||
|
@ -133,6 +102,7 @@ class ProfileStatsWidget : AppWidgetProvider() {
|
|||
1,
|
||||
Intent(context, ProfileStatsConfigure::class.java).apply {
|
||||
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||
data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME))
|
||||
},
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
|
@ -248,7 +218,9 @@ class ProfileStatsWidget : AppWidgetProvider() {
|
|||
}
|
||||
}
|
||||
|
||||
const val PREFS_NAME = "ani.dantotsu.widgets.ResumableWidget"
|
||||
fun getPrefsName(appWidgetId: Int): String {
|
||||
return "ani.dantotsu.widgets.Statistics.${appWidgetId}"
|
||||
}
|
||||
const val PREF_BACKGROUND_COLOR = "background_color"
|
||||
const val PREF_BACKGROUND_FADE = "background_fade"
|
||||
const val PREF_TITLE_TEXT_COLOR = "title_text_color"
|
||||
|
|
|
@ -12,6 +12,7 @@ import ani.dantotsu.connections.anilist.Anilist
|
|||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import ani.dantotsu.util.BitmapUtil.Companion.downloadImageAsBitmap
|
||||
import ani.dantotsu.util.BitmapUtil.Companion.roundCorners
|
||||
import ani.dantotsu.util.Logger
|
||||
import com.google.gson.GsonBuilder
|
||||
|
@ -183,33 +184,6 @@ class UpcomingRemoteViewsFactory(private val context: Context) :
|
|||
return rv
|
||||
}
|
||||
|
||||
private fun downloadImageAsBitmap(imageUrl: String): Bitmap? {
|
||||
var bitmap: Bitmap? = null
|
||||
var inputStream: InputStream? = null
|
||||
var urlConnection: HttpURLConnection? = null
|
||||
|
||||
try {
|
||||
val url = URL(imageUrl)
|
||||
urlConnection = url.openConnection() as HttpURLConnection
|
||||
urlConnection.requestMethod = "GET"
|
||||
urlConnection.connect()
|
||||
|
||||
if (urlConnection.responseCode == HttpURLConnection.HTTP_OK) {
|
||||
inputStream = urlConnection.inputStream
|
||||
bitmap = BitmapFactory.decodeStream(inputStream)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
inputStream?.close()
|
||||
urlConnection?.disconnect()
|
||||
}
|
||||
return bitmap?.let { roundCorners(it) }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
override fun getLoadingView(): RemoteViews {
|
||||
return RemoteViews(context.packageName, R.layout.item_upcoming_widget)
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@ import android.net.Uri
|
|||
import android.os.Bundle
|
||||
import android.widget.RemoteViews
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import ani.dantotsu.MainActivity
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.util.BitmapUtil.Companion.convertDrawableToBitmap
|
||||
import ani.dantotsu.widgets.WidgetSizeProvider
|
||||
|
||||
/**
|
||||
|
@ -97,7 +97,7 @@ class UpcomingWidget : AppWidgetProvider() {
|
|||
intentTemplate.putExtra("fromWidget", true)
|
||||
|
||||
val views = RemoteViews(context.packageName, R.layout.upcoming_widget).apply {
|
||||
setImageViewBitmap(R.id.backgroundView, convertDrawableToBitmap(gradientDrawable, width, height))
|
||||
setImageViewBitmap(R.id.backgroundView, gradientDrawable.toBitmap(width, height))
|
||||
setTextColor(R.id.text_show_title, titleTextColor)
|
||||
setTextColor(R.id.text_show_countdown, countdownTextColor)
|
||||
setTextColor(R.id.widgetTitle, titleTextColor)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue