Rework icon repository

This commit is contained in:
MM20 2021-12-02 21:49:18 +01:00
parent 2a271a41ec
commit dbd7fda7fb
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
11 changed files with 383 additions and 269 deletions

View File

@ -46,7 +46,6 @@ dependencies {
implementation(project(":search"))
implementation(project(":base"))
implementation(project(":icons"))
implementation(project(":preferences"))
implementation(project(":ktx"))
implementation(project(":badges"))

View File

@ -40,6 +40,7 @@ dependencies {
implementation(libs.androidx.core)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.palette)
implementation(libs.materialcomponents)
implementation(libs.bundles.androidx.lifecycle)
@ -50,6 +51,7 @@ dependencies {
implementation(project(":ktx"))
implementation(project(":base"))
implementation(project(":search"))
implementation(project(":applications"))
implementation(project(":crashreporter"))
}

View File

@ -54,203 +54,6 @@ class IconPackManager(
selectedIconPack = iconPack
}
fun getIcon(context: Context, activity: LauncherActivityInfo, size: Int): LauncherIcon? {
if (selectedIconPack.isEmpty()) return getDefaultIcon(context, activity)
return getFromPack(context, activity, size) ?: generateIcon(context, activity, size)
}
private fun getFromPack(
context: Context,
activity: LauncherActivityInfo,
size: Int
): LauncherIcon? {
val res = try {
context.packageManager.getResourcesForApplication(selectedIconPack)
} catch (e: PackageManager.NameNotFoundException) {
Log.e("MM20", "Icon pack package $selectedIconPack not found!")
return getDefaultIcon(context, activity)
}
val iconDao = AppDatabase.getInstance(context).iconDao()
val component = ComponentName(activity.applicationInfo.packageName, activity.name)
val icon = iconDao.getIcon(component.flattenToString(), selectedIconPack)
?: return generateIcon(context, activity, size)
if (icon.type == "calendar") {
return getIconPackCalendarIcon(context, icon.iconPack, icon.drawable ?: return null)?.also {
dynamicIconController.registerIcon(it)
}
}
val drawableName = icon.drawable
val resId = res.getIdentifier(drawableName, "drawable", selectedIconPack).takeIf { it != 0 }
?: return generateIcon(context, activity, size)
val drawable = ResourcesCompat.getDrawable(res, resId, context.theme) ?: return null
return when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && drawable is AdaptiveIconDrawable -> {
LauncherIcon(
foreground = drawable.foreground,
background = drawable.background,
foregroundScale = 1.5f,
backgroundScale = 1.5f
)
}
else -> {
LauncherIcon(
foreground = drawable,
foregroundScale = getScale(),
autoGenerateBackgroundMode = LauncherPreferences.instance.legacyIconBg.toInt()
)
}
}
}
private fun generateIcon(
context: Context,
activity: LauncherActivityInfo,
size: Int
): LauncherIcon? {
val back = getIconBack()
val upon = getIconUpon()
val mask = getIconMask()
val scale = getPackScale()
if (back == null && upon == null && mask == null) {
return getDefaultIcon(context, activity)
}
val drawable = activity.getIcon(context.resources.displayMetrics.densityDpi)
val bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
val paint = Paint()
paint.isAntiAlias = true
paint.isFilterBitmap = true
paint.isDither = true
var inBounds: Rect
var outBounds: Rect
val icon = drawable.toBitmap(width = size, height = size)
inBounds = Rect(0, 0, icon.width, icon.height)
outBounds = Rect(
(bitmap.width * (1 - scale) * 0.5).roundToInt(),
(bitmap.height * (1 - scale) * 0.5).roundToInt(),
(bitmap.width - bitmap.width * (1 - scale) * 0.5).roundToInt(),
(bitmap.height - bitmap.height * (1 - scale) * 0.5).roundToInt()
)
canvas.drawBitmap(icon, inBounds, outBounds, paint)
val pack = selectedIconPack
val pm = context.packageManager
val res = try {
pm.getResourcesForApplication(pack)
} catch (e: Resources.NotFoundException) {
return getDefaultIcon(context, activity)
}
if (mask != null) {
res.getIdentifier(mask, "drawable", pack).takeIf { it != 0 }?.let {
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OUT)
val maskDrawable = ResourcesCompat.getDrawable(res, it, null) ?: return null
val maskBmp = maskDrawable.toBitmap(size, size)
inBounds = Rect(0, 0, maskBmp.width, maskBmp.height)
outBounds = Rect(0, 0, bitmap.width, bitmap.height)
canvas.drawBitmap(maskBmp, inBounds, outBounds, paint)
}
}
if (upon != null) {
res.getIdentifier(upon, "drawable", pack).takeIf { it != 0 }?.let {
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_OVER);
val maskDrawable = ResourcesCompat.getDrawable(res, it, null) ?: return null
val maskBmp = maskDrawable.toBitmap(size, size)
inBounds = Rect(0, 0, maskBmp.width, maskBmp.height)
outBounds = Rect(0, 0, bitmap.width, bitmap.height)
canvas.drawBitmap(maskBmp, inBounds, outBounds, paint)
}
}
if (back != null) {
res.getIdentifier(back, "drawable", pack).takeIf { it != 0 }?.let {
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OVER);
val maskDrawable = ResourcesCompat.getDrawable(res, it, null) ?: return null
val maskBmp = maskDrawable.toBitmap(size, size)
inBounds = Rect(0, 0, maskBmp.width, maskBmp.height)
outBounds = Rect(0, 0, bitmap.width, bitmap.height)
canvas.drawBitmap(maskBmp, inBounds, outBounds, paint)
}
}
return LauncherIcon(
foreground = BitmapDrawable(context.resources, bitmap),
foregroundScale = getScale(),
autoGenerateBackgroundMode = LauncherPreferences.instance.legacyIconBg.toInt()
)
}
private fun getDefaultIcon(context: Context, activity: LauncherActivityInfo): LauncherIcon? {
if (activity.applicationInfo.packageName == GOOGLE_DESK_CLOCK_PACKAGE_NAME) {
getGoogleDeskClockIcon(context)?.let {
dynamicIconController.registerIcon(it)
return it
}
}
getCalendarIcon(context, activity)?.let {
dynamicIconController.registerIcon(it)
return it
}
try {
val icon = activity.getIcon(context.resources.displayMetrics.densityDpi) ?: return null
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && icon is AdaptiveIconDrawable -> {
return LauncherIcon(
foreground = icon.foreground ?: return null,
background = icon.background,
foregroundScale = 1.5f,
backgroundScale = 1.5f
)
}
else -> {
return LauncherIcon(
foreground = icon,
foregroundScale = getScale(),
autoGenerateBackgroundMode = LauncherPreferences.instance.legacyIconBg.toInt()
)
}
}
} catch (e: PackageManager.NameNotFoundException) {
return null
}
}
private fun getIconPackCalendarIcon(
context: Context,
iconPack: String,
baseIconName: String
): CalendarDynamicLauncherIcon? {
val resources = try {
context.packageManager.getResourcesForApplication(iconPack)
} catch (e: PackageManager.NameNotFoundException) {
return null
}
val drawableIds = (1..31).map {
val drawableName = baseIconName + it
val id = resources.getIdentifier(drawableName, "drawable", iconPack)
if (id == 0) return null
id
}.toIntArray()
return CalendarDynamicLauncherIcon(
context = context,
background = ColorDrawable(0),
foreground = ColorDrawable(0),
foregroundScale = 1.5f,
backgroundScale = 1.5f,
packageName = iconPack,
drawableIds = drawableIds,
autoGenerateBackgroundMode = LauncherPreferences.instance.legacyIconBg.toInt()
)
}
private fun getCalendarIcon(
context: Context,
activity: LauncherActivityInfo
@ -289,41 +92,6 @@ class IconPackManager(
)
}
private fun getGoogleDeskClockIcon(context: Context): ClockDynamicLauncherIcon? {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return null
val pm = context.packageManager
val appInfo =
pm.getApplicationInfo(GOOGLE_DESK_CLOCK_PACKAGE_NAME, PackageManager.GET_META_DATA)
?: return null
val drawable =
appInfo.metaData.getInt("com.google.android.apps.nexuslauncher.LEVEL_PER_TICK_ICON_ROUND")
val resources = pm.getResourcesForApplication(appInfo)
val baseIcon = try {
ResourcesCompat.getDrawable(resources, drawable, null) as? AdaptiveIconDrawable
?: return null
} catch (e: Resources.NotFoundException) {
return null
}
val foreground = baseIcon.foreground as? LayerDrawable ?: return null
val hourLayer =
appInfo.metaData.getInt("com.google.android.apps.nexuslauncher.HOUR_LAYER_INDEX")
val minuteLayer =
appInfo.metaData.getInt("com.google.android.apps.nexuslauncher.MINUTE_LAYER_INDEX")
val secondLayer =
appInfo.metaData.getInt("com.google.android.apps.nexuslauncher.SECOND_LAYER_INDEX")
return ClockDynamicLauncherIcon(
context = context,
background = baseIcon.background,
backgroundScale = 1.5f,
foreground = foreground,
foregroundScale = 1.5f,
badgeNumber = 0f,
hourLayer = hourLayer,
minuteLayer = minuteLayer,
secondLayer = secondLayer
)
}
private fun getScale(): Float {
return when (LauncherPreferences.instance.iconShape) {
IconShape.CIRCLE, IconShape.PLATFORM_DEFAULT -> 0.7f
@ -332,29 +100,6 @@ class IconPackManager(
}
}
private fun getIconBack(): String? {
val iconDao = AppDatabase.getInstance(context).iconDao()
val iconbacks = iconDao.getIconBacks(selectedIconPack)
return iconbacks.randomElementOrNull()
}
private fun getIconUpon(): String? {
val iconDao = AppDatabase.getInstance(context).iconDao()
val iconupons = iconDao.getIconUpons(selectedIconPack)
return iconupons.randomElementOrNull()
}
private fun getIconMask(): String? {
val iconDao = AppDatabase.getInstance(context).iconDao()
val iconmasks = iconDao.getIconMasks(selectedIconPack)
return iconmasks.randomElementOrNull()
}
private fun getPackScale(): Float {
val iconDao = AppDatabase.getInstance(context).iconDao()
return iconDao.getScale(selectedIconPack) ?: 1f
}
suspend fun getInstalledIconPacks(): List<IconPack> {
return withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).iconDao().getInstalledIconPacks().map {

View File

@ -5,6 +5,8 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.util.LruCache
import de.mm20.launcher2.icons.providers.*
import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.search.data.Searchable
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.Flow
@ -12,7 +14,8 @@ import kotlinx.coroutines.flow.flow
class IconRepository(
val context: Context,
val iconPackManager: IconPackManager
private val iconPackManager: IconPackManager,
private val dynamicIconController: DynamicIconController,
) {
private val appReceiver = object : BroadcastReceiver() {
@ -23,6 +26,10 @@ class IconRepository(
private val scope = CoroutineScope(Job() + Dispatchers.Main)
private val cache = LruCache<String, LauncherIcon>(200)
private var iconProviders: List<IconProvider> = listOf()
private lateinit var placeholderProvider: IconProvider
init {
requestIconPackListUpdate()
@ -34,9 +41,9 @@ class IconRepository(
addAction(Intent.ACTION_PACKAGE_CHANGED)
addDataScheme("package")
})
recreate()
}
private val cache = LruCache<String, LauncherIcon>(200)
fun getIcon(searchable: Searchable, size: Int): Flow<LauncherIcon> = flow {
var icon = cache.get(searchable.key)
@ -44,12 +51,19 @@ class IconRepository(
emit(icon)
return@flow
}
val placeholderIcon = withContext(Dispatchers.IO) {
searchable.getPlaceholderIcon(context)
}
emit(placeholderIcon)
icon = withContext(Dispatchers.IO) {
searchable.loadIconAsync(context, size)
icon = placeholderProvider.getIcon(searchable, size)
emit(icon)
for (provider in iconProviders) {
val ic = provider.getIcon(searchable, size)
if (ic != null) {
icon = ic
if (icon is DynamicLauncherIcon) {
dynamicIconController.registerIcon(icon)
}
break
}
}
if (icon != null) {
cache.put(searchable.key, icon)
@ -71,11 +85,20 @@ class IconRepository(
}
}
fun removeIconFromCache(searchable: Searchable) {
cache.remove(searchable.key)
}
fun recreate() {
placeholderProvider = PlaceholderIconProvider(context)
val providers = mutableListOf<IconProvider>()
fun clearCache() {
if (iconPackManager.selectedIconPack.isNotBlank()) {
providers.add(IconPackIconProvider(context, iconPackManager.selectedIconPack))
}
providers.add(GoogleClockIconProvider(context))
providers.add(CalendarIconProvider(context))
providers.add(SystemIconProvider(context))
providers.add(placeholderProvider)
cache.evictAll()
iconProviders = providers
}
}

View File

@ -6,5 +6,5 @@ import org.koin.dsl.module
val iconsModule = module {
single { DynamicIconController(androidContext()) }
single { IconPackManager(androidContext(), get()) }
single { IconRepository(androidContext(), get()) }
single { IconRepository(androidContext(), get(), get()) }
}

View File

@ -0,0 +1,50 @@
package de.mm20.launcher2.icons.providers
import android.content.ComponentName
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.drawable.ColorDrawable
import de.mm20.launcher2.icons.CalendarDynamicLauncherIcon
import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.ktx.obtainTypedArrayOrNull
import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.search.data.Application
import de.mm20.launcher2.search.data.Searchable
class CalendarIconProvider(val context: Context): IconProvider {
override suspend fun getIcon(searchable: Searchable, size: Int): LauncherIcon? {
if(searchable !is Application) return 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
}
val resources = pm.getResourcesForActivity(component)
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
if (arrayId == 0) return null
val typedArray = resources.obtainTypedArrayOrNull(arrayId) ?: return null
if (typedArray.length() != 31) {
typedArray.recycle()
return null
}
val drawableIds = IntArray(31)
for (i in 0 until 31) {
drawableIds[i] = typedArray.getResourceId(i, 0)
}
typedArray.recycle()
return CalendarDynamicLauncherIcon(
context = context,
background = ColorDrawable(0),
foreground = ColorDrawable(0),
foregroundScale = 1.5f,
backgroundScale = 1.5f,
packageName = component.packageName,
drawableIds = drawableIds,
autoGenerateBackgroundMode = LauncherPreferences.instance.legacyIconBg.toInt()
)
}
}

View File

@ -0,0 +1,58 @@
package de.mm20.launcher2.icons.providers
import android.content.Context
import android.content.pm.PackageManager
import android.content.res.Resources
import android.graphics.drawable.AdaptiveIconDrawable
import android.graphics.drawable.LayerDrawable
import android.os.Build
import androidx.core.content.res.ResourcesCompat
import de.mm20.launcher2.icons.ClockDynamicLauncherIcon
import de.mm20.launcher2.icons.IconPackManager
import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.search.data.Application
import de.mm20.launcher2.search.data.Searchable
class GoogleClockIconProvider(val context: Context) : IconProvider {
override suspend fun getIcon(searchable: Searchable, size: Int): LauncherIcon? {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return null
if (searchable !is Application) return null
if (searchable.`package` != "com.google.android.deskclock") return null
val pm = context.packageManager
val appInfo = try {
pm.getApplicationInfo(
IconPackManager.GOOGLE_DESK_CLOCK_PACKAGE_NAME,
PackageManager.GET_META_DATA
)
} catch (e: PackageManager.NameNotFoundException) {
return null
}
val drawable =
appInfo.metaData.getInt("com.google.android.apps.nexuslauncher.LEVEL_PER_TICK_ICON_ROUND")
val resources = pm.getResourcesForApplication(appInfo)
val baseIcon = try {
ResourcesCompat.getDrawable(resources, drawable, null) as? AdaptiveIconDrawable
?: return null
} catch (e: Resources.NotFoundException) {
return null
}
val foreground = baseIcon.foreground as? LayerDrawable ?: return null
val hourLayer =
appInfo.metaData.getInt("com.google.android.apps.nexuslauncher.HOUR_LAYER_INDEX")
val minuteLayer =
appInfo.metaData.getInt("com.google.android.apps.nexuslauncher.MINUTE_LAYER_INDEX")
val secondLayer =
appInfo.metaData.getInt("com.google.android.apps.nexuslauncher.SECOND_LAYER_INDEX")
return ClockDynamicLauncherIcon(
context = context,
background = baseIcon.background,
backgroundScale = 1.5f,
foreground = foreground,
foregroundScale = 1.5f,
badgeNumber = 0f,
hourLayer = hourLayer,
minuteLayer = minuteLayer,
secondLayer = secondLayer
)
}
}

View File

@ -0,0 +1,207 @@
package de.mm20.launcher2.icons.providers
import android.content.ComponentName
import android.content.Context
import android.content.pm.LauncherActivityInfo
import android.content.pm.PackageManager
import android.content.res.Resources
import android.graphics.*
import android.graphics.drawable.AdaptiveIconDrawable
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.util.Log
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.toBitmap
import de.mm20.launcher2.database.AppDatabase
import de.mm20.launcher2.icons.CalendarDynamicLauncherIcon
import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.ktx.randomElementOrNull
import de.mm20.launcher2.preferences.IconShape
import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.search.data.LauncherApp
import de.mm20.launcher2.search.data.Searchable
import kotlin.math.roundToInt
class IconPackIconProvider(val context: Context, val iconPack: String): IconProvider {
override suspend fun getIcon(searchable: Searchable, size: Int): LauncherIcon? {
if (searchable !is LauncherApp) return null
val res = try {
context.packageManager.getResourcesForApplication(iconPack)
} catch (e: PackageManager.NameNotFoundException) {
Log.e("MM20", "Icon pack package $iconPack not found!")
return null
}
val iconDao = AppDatabase.getInstance(context).iconDao()
val component = ComponentName(searchable.`package`, searchable.activity)
val icon = iconDao.getIcon(component.flattenToString(), iconPack)
?: return generateIcon(context, searchable.launcherActivityInfo, size)
if (icon.type == "calendar") {
return getIconPackCalendarIcon(context, icon.drawable ?: return null)
}
val drawableName = icon.drawable
val resId = res.getIdentifier(drawableName, "drawable", iconPack).takeIf { it != 0 }
?: return generateIcon(context, searchable.launcherActivityInfo, size)
val drawable = ResourcesCompat.getDrawable(res, resId, context.theme) ?: return null
return when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && drawable is AdaptiveIconDrawable -> {
LauncherIcon(
foreground = drawable.foreground,
background = drawable.background,
foregroundScale = 1.5f,
backgroundScale = 1.5f
)
}
else -> {
LauncherIcon(
foreground = drawable,
foregroundScale = getScale(),
autoGenerateBackgroundMode = LauncherPreferences.instance.legacyIconBg.toInt()
)
}
}
}
private fun getScale(): Float {
return when (LauncherPreferences.instance.iconShape) {
IconShape.CIRCLE, IconShape.PLATFORM_DEFAULT -> 0.7f
else -> 0.8f
}
}
private suspend fun generateIcon(
context: Context,
activity: LauncherActivityInfo,
size: Int
): LauncherIcon? {
val back = getIconBack()
val upon = getIconUpon()
val mask = getIconMask()
val scale = getPackScale()
if (back == null && upon == null && mask == null) {
return null
}
val drawable = activity.getIcon(context.resources.displayMetrics.densityDpi)
val bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
val paint = Paint()
paint.isAntiAlias = true
paint.isFilterBitmap = true
paint.isDither = true
var inBounds: Rect
var outBounds: Rect
val icon = drawable.toBitmap(width = size, height = size)
inBounds = Rect(0, 0, icon.width, icon.height)
outBounds = Rect(
(bitmap.width * (1 - scale) * 0.5).roundToInt(),
(bitmap.height * (1 - scale) * 0.5).roundToInt(),
(bitmap.width - bitmap.width * (1 - scale) * 0.5).roundToInt(),
(bitmap.height - bitmap.height * (1 - scale) * 0.5).roundToInt()
)
canvas.drawBitmap(icon, inBounds, outBounds, paint)
val pack = iconPack
val pm = context.packageManager
val res = try {
pm.getResourcesForApplication(pack)
} catch (e: Resources.NotFoundException) {
return null
}
if (mask != null) {
res.getIdentifier(mask, "drawable", pack).takeIf { it != 0 }?.let {
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OUT)
val maskDrawable = ResourcesCompat.getDrawable(res, it, null) ?: return null
val maskBmp = maskDrawable.toBitmap(size, size)
inBounds = Rect(0, 0, maskBmp.width, maskBmp.height)
outBounds = Rect(0, 0, bitmap.width, bitmap.height)
canvas.drawBitmap(maskBmp, inBounds, outBounds, paint)
}
}
if (upon != null) {
res.getIdentifier(upon, "drawable", pack).takeIf { it != 0 }?.let {
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_OVER);
val maskDrawable = ResourcesCompat.getDrawable(res, it, null) ?: return null
val maskBmp = maskDrawable.toBitmap(size, size)
inBounds = Rect(0, 0, maskBmp.width, maskBmp.height)
outBounds = Rect(0, 0, bitmap.width, bitmap.height)
canvas.drawBitmap(maskBmp, inBounds, outBounds, paint)
}
}
if (back != null) {
res.getIdentifier(back, "drawable", pack).takeIf { it != 0 }?.let {
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OVER);
val maskDrawable = ResourcesCompat.getDrawable(res, it, null) ?: return null
val maskBmp = maskDrawable.toBitmap(size, size)
inBounds = Rect(0, 0, maskBmp.width, maskBmp.height)
outBounds = Rect(0, 0, bitmap.width, bitmap.height)
canvas.drawBitmap(maskBmp, inBounds, outBounds, paint)
}
}
return LauncherIcon(
foreground = BitmapDrawable(context.resources, bitmap),
foregroundScale = getScale(),
autoGenerateBackgroundMode = LauncherPreferences.instance.legacyIconBg.toInt()
)
}
private suspend fun getIconBack(): String? {
val iconDao = AppDatabase.getInstance(context).iconDao()
val iconbacks = iconDao.getIconBacks(iconPack)
return iconbacks.randomElementOrNull()
}
private suspend fun getIconUpon(): String? {
val iconDao = AppDatabase.getInstance(context).iconDao()
val iconupons = iconDao.getIconUpons(iconPack)
return iconupons.randomElementOrNull()
}
private suspend fun getIconMask(): String? {
val iconDao = AppDatabase.getInstance(context).iconDao()
val iconmasks = iconDao.getIconMasks(iconPack)
return iconmasks.randomElementOrNull()
}
private suspend fun getPackScale(): Float {
val iconDao = AppDatabase.getInstance(context).iconDao()
return iconDao.getScale(iconPack) ?: 1f
}
private fun getIconPackCalendarIcon(
context: Context,
baseIconName: String
): CalendarDynamicLauncherIcon? {
val resources = try {
context.packageManager.getResourcesForApplication(iconPack)
} catch (e: PackageManager.NameNotFoundException) {
return null
}
val drawableIds = (1..31).map {
val drawableName = baseIconName + it
val id = resources.getIdentifier(drawableName, "drawable", iconPack)
if (id == 0) return null
id
}.toIntArray()
return CalendarDynamicLauncherIcon(
context = context,
background = ColorDrawable(0),
foreground = ColorDrawable(0),
foregroundScale = 1.5f,
backgroundScale = 1.5f,
packageName = iconPack,
drawableIds = drawableIds,
autoGenerateBackgroundMode = LauncherPreferences.instance.legacyIconBg.toInt()
)
}
}

View File

@ -0,0 +1,8 @@
package de.mm20.launcher2.icons.providers
import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.search.data.Searchable
interface IconProvider {
suspend fun getIcon(searchable: Searchable, size: Int): LauncherIcon?
}

View File

@ -0,0 +1,11 @@
package de.mm20.launcher2.icons.providers
import android.content.Context
import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.search.data.Searchable
class PlaceholderIconProvider(val context: Context) : IconProvider {
override suspend fun getIcon(searchable: Searchable, size: Int): LauncherIcon? {
return searchable.getPlaceholderIcon(context)
}
}

View File

@ -0,0 +1,11 @@
package de.mm20.launcher2.icons.providers
import android.content.Context
import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.search.data.Searchable
class SystemIconProvider(val context: Context) : IconProvider {
override suspend fun getIcon(searchable: Searchable, size: Int): LauncherIcon? {
return searchable.loadIconAsync(context, size)
}
}