Optimize icon loading
This commit is contained in:
parent
6ea9751535
commit
1241067357
@ -90,26 +90,26 @@ class IconPackManager(
|
||||
packageName: String,
|
||||
activityName: String?,
|
||||
allowThemed: Boolean = true
|
||||
): LauncherIcon? {
|
||||
): LauncherIcon? = withContext(Dispatchers.IO) {
|
||||
val res = try {
|
||||
context.packageManager.getResourcesForApplication(iconPack)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
Log.e("MM20", "Icon pack package $iconPack not found!")
|
||||
return null
|
||||
return@withContext null
|
||||
}
|
||||
val activity = activityName?.let { ComponentName(packageName, it) }?.shortClassName
|
||||
val iconDao = appDatabase.iconDao()
|
||||
val icon = iconDao.getIcon(packageName, activity, iconPack)?.let { IconPackAppIcon(it) }
|
||||
?: return null
|
||||
?: return@withContext null
|
||||
|
||||
if (icon is CalendarIcon) {
|
||||
return getIconPackCalendarIcon(icon, res, allowThemed)
|
||||
return@withContext getIconPackCalendarIcon(icon, res, allowThemed)
|
||||
} else if (icon is AppIcon) {
|
||||
return getIconPackStaticIcon(icon, res, allowThemed)
|
||||
return@withContext getIconPackStaticIcon(icon, res, allowThemed)
|
||||
} else if (icon is ClockIcon) {
|
||||
return getIconPackClockIcon(icon, res, allowThemed)
|
||||
return@withContext getIconPackClockIcon(icon, res, allowThemed)
|
||||
}
|
||||
return null
|
||||
return@withContext null
|
||||
}
|
||||
|
||||
suspend fun generateIcon(
|
||||
@ -117,14 +117,14 @@ class IconPackManager(
|
||||
iconPack: String,
|
||||
baseIcon: Drawable,
|
||||
size: Int
|
||||
): LauncherIcon? {
|
||||
): LauncherIcon? = withContext(Dispatchers.IO) {
|
||||
val back = getIconBack(iconPack)
|
||||
val upon = getIconUpon(iconPack)
|
||||
val mask = getIconMask(iconPack)
|
||||
val scale = getPackScale(iconPack)
|
||||
|
||||
if (back == null && upon == null && mask == null) {
|
||||
return null
|
||||
return@withContext null
|
||||
}
|
||||
|
||||
val bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888)
|
||||
@ -155,18 +155,18 @@ class IconPackManager(
|
||||
val res = try {
|
||||
pm.getResourcesForApplication(pack)
|
||||
} catch (e: Resources.NotFoundException) {
|
||||
return null
|
||||
return@withContext null
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
return null
|
||||
return@withContext null
|
||||
}
|
||||
|
||||
if (mask != null) {
|
||||
res.getIdentifier(mask, "drawable", pack).takeIf { it != 0 }?.let {
|
||||
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OUT)
|
||||
val maskDrawable = try {
|
||||
ResourcesCompat.getDrawable(res, it, null) ?: return null
|
||||
ResourcesCompat.getDrawable(res, it, null) ?: return@withContext null
|
||||
} catch (e: Resources.NotFoundException) {
|
||||
return null
|
||||
return@withContext null
|
||||
}
|
||||
val maskBmp = maskDrawable.toBitmap(size, size)
|
||||
inBounds = Rect(0, 0, maskBmp.width, maskBmp.height)
|
||||
@ -178,9 +178,9 @@ class IconPackManager(
|
||||
res.getIdentifier(upon, "drawable", pack).takeIf { it != 0 }?.let {
|
||||
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)
|
||||
val maskDrawable = try {
|
||||
ResourcesCompat.getDrawable(res, it, null) ?: return null
|
||||
ResourcesCompat.getDrawable(res, it, null) ?: return@withContext null
|
||||
} catch (e: Resources.NotFoundException) {
|
||||
return null
|
||||
return@withContext null
|
||||
}
|
||||
val maskBmp = maskDrawable.toBitmap(size, size)
|
||||
inBounds = Rect(0, 0, maskBmp.width, maskBmp.height)
|
||||
@ -192,9 +192,9 @@ class IconPackManager(
|
||||
res.getIdentifier(back, "drawable", pack).takeIf { it != 0 }?.let {
|
||||
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OVER)
|
||||
val maskDrawable = try {
|
||||
ResourcesCompat.getDrawable(res, it, null) ?: return null
|
||||
ResourcesCompat.getDrawable(res, it, null) ?: return@withContext null
|
||||
} catch (e: Resources.NotFoundException) {
|
||||
return null
|
||||
return@withContext null
|
||||
}
|
||||
val maskBmp = maskDrawable.toBitmap(size, size)
|
||||
inBounds = Rect(0, 0, maskBmp.width, maskBmp.height)
|
||||
@ -203,7 +203,7 @@ class IconPackManager(
|
||||
}
|
||||
}
|
||||
|
||||
return StaticLauncherIcon(
|
||||
return@withContext StaticLauncherIcon(
|
||||
foregroundLayer = StaticIconLayer(
|
||||
icon = BitmapDrawable(context.resources, bitmap),
|
||||
scale = 1f,
|
||||
|
||||
@ -42,6 +42,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.channelFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
@ -138,30 +139,25 @@ class IconService(
|
||||
}
|
||||
|
||||
|
||||
fun getIcon(searchable: SavableSearchable, size: Int): Flow<LauncherIcon> = channelFlow {
|
||||
iconProviders.collectLatest { providers ->
|
||||
transformations.collectLatest { transformations ->
|
||||
customAttributesRepository.getCustomIcon(searchable).collectLatest { customIcon ->
|
||||
|
||||
val provs = getProviders(customIcon) + providers
|
||||
val transforms = getTransformations(customIcon) ?: transformations
|
||||
|
||||
var icon = cache.get(searchable.key + customIcon.hashCode())
|
||||
if (icon != null) {
|
||||
send(icon)
|
||||
return@collectLatest
|
||||
}
|
||||
|
||||
icon = provs.getFirstIcon(searchable, size)
|
||||
|
||||
if (icon != null) {
|
||||
icon = icon.transform(transforms)
|
||||
|
||||
cache.put(searchable.key + customIcon.hashCode(), icon)
|
||||
send(icon)
|
||||
}
|
||||
}
|
||||
fun getIcon(searchable: SavableSearchable, size: Int): Flow<LauncherIcon> {
|
||||
val customIcon = customAttributesRepository.getCustomIcon(searchable)
|
||||
return combine(iconProviders, transformations, customIcon) { providers, transformations, ci ->
|
||||
var icon = cache.get(searchable.key + customIcon.hashCode())
|
||||
if (icon != null) {
|
||||
return@combine icon
|
||||
}
|
||||
|
||||
val provs = if (ci != null) getProviders(ci) + providers else providers
|
||||
val transforms = getTransformations(ci) ?: transformations
|
||||
|
||||
icon = provs.getFirstIcon(searchable, size)
|
||||
|
||||
if (icon != null) {
|
||||
icon = icon.transform(transforms)
|
||||
|
||||
cache.put(searchable.key + customIcon.hashCode(), icon)
|
||||
}
|
||||
return@combine icon
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,39 +8,41 @@ import de.mm20.launcher2.icons.LauncherIcon
|
||||
import de.mm20.launcher2.ktx.obtainTypedArrayOrNull
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
import de.mm20.launcher2.search.data.LauncherApp
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class CalendarIconProvider(val context: Context, val themed: Boolean): IconProvider {
|
||||
override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? {
|
||||
if(searchable !is LauncherApp) return null
|
||||
override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? = withContext(Dispatchers.IO) {
|
||||
if(searchable !is LauncherApp) return@withContext null
|
||||
val component = ComponentName(searchable.`package`, searchable.activity)
|
||||
val pm = context.packageManager
|
||||
val ai = try {
|
||||
pm.getActivityInfo(component, PackageManager.GET_META_DATA)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
return null
|
||||
return@withContext null
|
||||
}
|
||||
var arrayId = ai.metaData?.getInt("com.teslacoilsw.launcher.calendarIconArray") ?: 0
|
||||
if (arrayId == 0) arrayId = ai.metaData?.getInt("com.google.android.calendar.dynamic_icons")
|
||||
?: return null
|
||||
?: return@withContext null
|
||||
if (arrayId == 0) arrayId = ai.metaData?.getInt("org.lineageos.etar.dynamic_icons")
|
||||
?: return null
|
||||
if (arrayId == 0) return null
|
||||
?: return@withContext null
|
||||
if (arrayId == 0) return@withContext null
|
||||
val resources = try {
|
||||
pm.getResourcesForActivity(component)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
return null
|
||||
return@withContext null
|
||||
}
|
||||
val typedArray = resources.obtainTypedArrayOrNull(arrayId) ?: return null
|
||||
val typedArray = resources.obtainTypedArrayOrNull(arrayId) ?: return@withContext null
|
||||
if (typedArray.length() != 31) {
|
||||
typedArray.recycle()
|
||||
return null
|
||||
return@withContext null
|
||||
}
|
||||
val drawableIds = IntArray(31)
|
||||
for (i in 0 until 31) {
|
||||
drawableIds[i] = typedArray.getResourceId(i, 0)
|
||||
}
|
||||
typedArray.recycle()
|
||||
return DynamicCalendarIcon(
|
||||
return@withContext DynamicCalendarIcon(
|
||||
resources = resources,
|
||||
resourceIds = drawableIds,
|
||||
isThemed = themed
|
||||
|
||||
@ -8,10 +8,12 @@ import de.mm20.launcher2.icons.compat.ClockIconConfig
|
||||
import de.mm20.launcher2.icons.compat.toLauncherIcon
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
import de.mm20.launcher2.search.data.LauncherApp
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class DynamicClockIconProvider(val context: Context, private val themed: Boolean) : IconProvider {
|
||||
override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? {
|
||||
if (searchable !is LauncherApp) return null
|
||||
override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? = withContext(Dispatchers.IO) {
|
||||
if (searchable !is LauncherApp) return@withContext null
|
||||
val pm = context.packageManager
|
||||
val appInfo = try {
|
||||
pm.getApplicationInfo(
|
||||
@ -19,22 +21,22 @@ class DynamicClockIconProvider(val context: Context, private val themed: Boolean
|
||||
PackageManager.GET_META_DATA
|
||||
)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
return null
|
||||
return@withContext null
|
||||
}
|
||||
|
||||
if (appInfo.metaData == null) return null
|
||||
if (appInfo.metaData == null) return@withContext null
|
||||
|
||||
val drawableId =
|
||||
appInfo.metaData.getInt("com.android.launcher3.LEVEL_PER_TICK_ICON_ROUND")
|
||||
|
||||
if (drawableId == 0) return null
|
||||
if (drawableId == 0) return@withContext null
|
||||
val resources = try {
|
||||
pm.getResourcesForApplication(appInfo)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
return null
|
||||
return@withContext null
|
||||
}
|
||||
|
||||
val icon = AdaptiveIconDrawableCompat.from(resources, drawableId) ?: return null
|
||||
val icon = AdaptiveIconDrawableCompat.from(resources, drawableId) ?: return@withContext null
|
||||
|
||||
val defaultHour =
|
||||
appInfo.metaData.getInt("com.android.launcher3.DEFAULT_HOUR")
|
||||
@ -71,7 +73,7 @@ class DynamicClockIconProvider(val context: Context, private val themed: Boolean
|
||||
)
|
||||
}
|
||||
|
||||
return icon.toLauncherIcon(
|
||||
return@withContext icon.toLauncherIcon(
|
||||
themed = themed,
|
||||
clock = clockConfig
|
||||
)
|
||||
|
||||
@ -35,13 +35,13 @@ internal class LegacyToAdaptiveTransformation(
|
||||
|
||||
if (layer is StaticIconLayer) {
|
||||
val drawable = layer.icon
|
||||
val bitmap = if (drawable is BitmapDrawable) {
|
||||
drawable.bitmap
|
||||
} else {
|
||||
drawable.toBitmap(48, 48)
|
||||
}
|
||||
|
||||
val palette = withContext(Dispatchers.Default) {
|
||||
val bitmap = if (drawable is BitmapDrawable) {
|
||||
drawable.bitmap
|
||||
} else {
|
||||
drawable.toBitmap(48, 48)
|
||||
}
|
||||
Palette.from(bitmap).generate()
|
||||
}
|
||||
return palette.getDominantColor(0)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user