Improve icon search

This commit is contained in:
MM20 2024-05-20 16:16:22 +02:00
parent bb8a0d4c0d
commit 9c5f1e971f
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
8 changed files with 298 additions and 158 deletions

View File

@ -79,14 +79,14 @@ sealed class CustomIcon : CustomAttribute {
"custom_icon_pack_icon" -> { "custom_icon_pack_icon" -> {
val legacyComponentName = payload.optString("icon").let { ComponentName.unflattenFromString(it) } val legacyComponentName = payload.optString("icon").let { ComponentName.unflattenFromString(it) }
if (legacyComponentName != null) { if (legacyComponentName != null) {
CustomIconPackIcon( LegacyCustomIconPackIcon(
iconPackageName = legacyComponentName.packageName, iconPackageName = legacyComponentName.packageName,
iconActivityName = legacyComponentName.className, iconActivityName = legacyComponentName.className,
iconPackPackage = payload.getString("icon_pack"), iconPackPackage = payload.getString("icon_pack"),
allowThemed = payload.optBoolean("allow_themed", true), allowThemed = payload.optBoolean("allow_themed", true),
) )
} else { } else {
CustomIconPackIcon( LegacyCustomIconPackIcon(
iconPackageName = payload.optString("package").takeIf { it.isNotEmpty() } ?: return null, iconPackageName = payload.optString("package").takeIf { it.isNotEmpty() } ?: return null,
iconActivityName = payload.optString("activity").takeIf { it.isNotEmpty() }, iconActivityName = payload.optString("activity").takeIf { it.isNotEmpty() },
iconPackPackage = payload.getString("icon_pack"), iconPackPackage = payload.getString("icon_pack"),
@ -94,6 +94,15 @@ sealed class CustomIcon : CustomAttribute {
) )
} }
} }
"custom_icon_pack_icon2" -> {
CustomIconPackIcon(
iconPackPackage = payload.getString("icon_pack"),
type = payload.getString("type"),
drawable = payload.optString("drawable"),
extras = payload.optString("extras").takeIf { it.isNotEmpty() },
allowThemed = payload.optBoolean("allow_themed", true),
)
}
"custom_themed_icon" -> { "custom_themed_icon" -> {
CustomThemedIcon( CustomThemedIcon(
iconPackageName = payload.getString("icon"), iconPackageName = payload.getString("icon"),
@ -116,7 +125,8 @@ sealed class CustomIcon : CustomAttribute {
} }
} }
data class CustomIconPackIcon( @Deprecated("Use CustomIconPackIcon instead")
data class LegacyCustomIconPackIcon(
val iconPackPackage: String, val iconPackPackage: String,
val iconPackageName: String, val iconPackageName: String,
val iconActivityName: String?, val iconActivityName: String?,
@ -133,6 +143,28 @@ data class CustomIconPackIcon(
} }
} }
/**
* [type], [drawable], and [extras] correspond to the fields in [IconEntity]
*/
data class CustomIconPackIcon(
val iconPackPackage: String,
val type: String,
val drawable: String?,
val extras: String?,
val allowThemed: Boolean,
): CustomIcon() {
override fun toDatabaseValue(): String {
return jsonObjectOf(
"type" to "custom_icon_pack_icon2",
"icon_pack" to iconPackPackage,
"type" to type,
"drawable" to drawable,
"extras" to extras,
"allow_themed" to allowThemed,
).toString()
}
}
data class AdaptifiedLegacyIcon( data class AdaptifiedLegacyIcon(
val fgScale: Float, val fgScale: Float,
/** /**
@ -173,7 +205,7 @@ data class CustomThemedIcon(
} }
} }
object ForceThemedIcon : CustomIcon() { data object ForceThemedIcon : CustomIcon() {
override fun toDatabaseValue(): String { override fun toDatabaseValue(): String {
return jsonObjectOf( return jsonObjectOf(
"type" to "force_themed_icon" "type" to "force_themed_icon"
@ -184,19 +216,18 @@ object ForceThemedIcon : CustomIcon() {
/** /**
* Use default icon, ignore any icon pack, themed icon or force adaptive settings. * Use default icon, ignore any icon pack, themed icon or force adaptive settings.
*/ */
object UnmodifiedSystemDefaultIcon: CustomIcon() { data object UnmodifiedSystemDefaultIcon: CustomIcon() {
override fun toDatabaseValue(): String { override fun toDatabaseValue(): String {
return jsonObjectOf( return jsonObjectOf(
"type" to "default_icon" "type" to "default_icon"
).toString() ).toString()
} }
} }
/** /**
* Use the default placeholder icon * Use the default placeholder icon
*/ */
object DefaultPlaceholderIcon: CustomIcon() { data object DefaultPlaceholderIcon: CustomIcon() {
override fun toDatabaseValue(): String { override fun toDatabaseValue(): String {
return jsonObjectOf( return jsonObjectOf(
"type" to "default_placeholder_icon" "type" to "default_placeholder_icon"

View File

@ -13,12 +13,14 @@ interface IconDao {
@Query("SELECT * FROM Icons WHERE packageName = :packageName AND (activityName = :activityName OR activityName IS NULL) AND iconPack = :iconPack AND type IN ('app', 'calendar', 'clock') ORDER BY type DESC LIMIT 1") @Query("SELECT * FROM Icons WHERE packageName = :packageName AND (activityName = :activityName OR activityName IS NULL) AND iconPack = :iconPack AND type IN ('app', 'calendar', 'clock') ORDER BY type DESC LIMIT 1")
suspend fun getIcon(packageName: String, activityName: String?, iconPack: String): IconEntity? suspend fun getIcon(packageName: String, activityName: String?, iconPack: String): IconEntity?
@Query("SELECT * FROM Icons WHERE drawable = :iconName AND iconPack = :iconPack ORDER BY type DESC LIMIT 1")
suspend fun getIcon(iconName: String, iconPack: String): IconEntity?
@Query("SELECT * FROM Icons WHERE packageName = :packageName AND (activityName = :activityName OR activityName IS NULL) AND type IN ('app', 'calendar', 'clock')") @Query("SELECT * FROM Icons WHERE packageName = :packageName AND (activityName = :activityName OR activityName IS NULL) AND type IN ('app', 'calendar', 'clock')")
suspend fun getIconsFromAllPacks(packageName: String, activityName: String): List<IconEntity> suspend fun getIconsFromAllPacks(packageName: String, activityName: String): List<IconEntity>
@Query("SELECT * FROM Icons WHERE type IN ('app', 'calendar', 'clock') AND (drawable LIKE :drawableQuery OR packageName LIKE :componentQuery OR activityName LIKE :componentQuery OR name LIKE :nameQuery) AND (:iconPack IS NULL OR iconPack = :iconPack) GROUP BY drawable ORDER BY iconPack, drawable LIMIT :limit") @Query("SELECT * FROM Icons WHERE type IN ('app', 'calendar', 'clock') AND (drawable LIKE :drawableQuery OR name LIKE :nameQuery) AND (:iconPack IS NULL OR iconPack = :iconPack) GROUP BY drawable, iconPack, type ORDER BY type DESC, iconPack, drawable LIMIT :limit")
suspend fun searchIconPackIcons( suspend fun searchIconPackIcons(
componentQuery: String,
nameQuery: String, nameQuery: String,
drawableQuery: String, drawableQuery: String,
iconPack: String?, iconPack: String?,

View File

@ -11,7 +11,7 @@ sealed interface IconPackComponent {
} }
sealed interface IconPackAppIcon: IconPackComponent { sealed interface IconPackAppIcon: IconPackComponent {
val packageName: String val packageName: String?
val activityName: String? val activityName: String?
val name: String? val name: String?
val themed: Boolean val themed: Boolean
@ -59,9 +59,9 @@ data class IconMask(
data class AppIcon( data class AppIcon(
val drawable: String, val drawable: String,
override val iconPack: String, override val iconPack: String,
override val packageName: String, override val packageName: String? = null,
override val activityName: String?, override val activityName: String? = null,
override val name: String?, override val name: String? = null,
override val themed: Boolean = false, override val themed: Boolean = false,
): IconPackComponent, IconPackAppIcon { ): IconPackComponent, IconPackAppIcon {
override fun toDatabaseEntity(): IconEntity { override fun toDatabaseEntity(): IconEntity {
@ -80,7 +80,7 @@ data class AppIcon(
data class CalendarIcon( data class CalendarIcon(
val drawables: List<String>, val drawables: List<String>,
override val iconPack: String, override val iconPack: String,
override val packageName: String, override val packageName: String?,
override val activityName: String? = null, override val activityName: String? = null,
override val name: String? = null, override val name: String? = null,
override val themed: Boolean = false, override val themed: Boolean = false,
@ -102,7 +102,7 @@ data class CalendarIcon(
data class ClockIcon( data class ClockIcon(
val drawable: String, val drawable: String,
override val iconPack: String, override val iconPack: String,
override val packageName: String, override val packageName: String? = null,
override val activityName: String? = null, override val activityName: String? = null,
override val name: String? = null, override val name: String? = null,
override val themed: Boolean, override val themed: Boolean,
@ -146,7 +146,7 @@ fun Icon(entity: IconEntity): IconPackComponent? {
"app" -> AppIcon( "app" -> AppIcon(
drawable = entity.drawable ?: return null, drawable = entity.drawable ?: return null,
iconPack = entity.iconPack, iconPack = entity.iconPack,
packageName = entity.packageName ?: return null, packageName = entity.packageName,
activityName = entity.activityName, activityName = entity.activityName,
themed = entity.themed, themed = entity.themed,
name = entity.name, name = entity.name,
@ -155,7 +155,7 @@ fun Icon(entity: IconEntity): IconPackComponent? {
drawables = entity.drawable?.split(",") ?: return null, drawables = entity.drawable?.split(",") ?: return null,
iconPack = entity.iconPack, iconPack = entity.iconPack,
themed = entity.themed, themed = entity.themed,
packageName = entity.packageName ?: return null, packageName = entity.packageName,
activityName = entity.activityName, activityName = entity.activityName,
name = entity.name, name = entity.name,
) )
@ -164,7 +164,7 @@ fun Icon(entity: IconEntity): IconPackComponent? {
ClockIcon( ClockIcon(
drawable = entity.drawable!!, drawable = entity.drawable!!,
iconPack = entity.iconPack, iconPack = entity.iconPack,
packageName = entity.packageName ?: return null, packageName = entity.packageName,
name = entity.name, name = entity.name,
activityName = entity.activityName, activityName = entity.activityName,
themed = entity.themed, themed = entity.themed,

View File

@ -112,6 +112,27 @@ class IconPackManager(
return@withContext null return@withContext null
} }
suspend fun getIcon(
iconPack: String,
icon: IconPackAppIcon,
allowThemed: Boolean,
): 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@withContext null
}
if (icon is CalendarIcon) {
return@withContext getIconPackCalendarIcon(icon, res, allowThemed)
} else if (icon is AppIcon) {
return@withContext getIconPackStaticIcon(icon, res, allowThemed)
} else if (icon is ClockIcon) {
return@withContext getIconPackClockIcon(icon, res, allowThemed)
}
return@withContext null
}
suspend fun generateIcon( suspend fun generateIcon(
context: Context, context: Context,
iconPack: String, iconPack: String,
@ -448,12 +469,11 @@ class IconPackManager(
val drawableQuery = query.replace(" ", "_").lowercase() val drawableQuery = query.replace(" ", "_").lowercase()
return iconDao.searchIconPackIcons( return iconDao.searchIconPackIcons(
drawableQuery = "%$drawableQuery%", drawableQuery = "%$drawableQuery%",
componentQuery = "%$query%",
nameQuery = "%$query%", nameQuery = "%$query%",
iconPack = iconPack?.packageName, iconPack = iconPack?.packageName,
).mapNotNull { ).mapNotNull {
IconPackAppIcon(it) IconPackAppIcon(it)
} }.distinct()
} }

View File

@ -11,6 +11,7 @@ import de.mm20.launcher2.data.customattrs.AdaptifiedLegacyIcon
import de.mm20.launcher2.data.customattrs.CustomAttributesRepository import de.mm20.launcher2.data.customattrs.CustomAttributesRepository
import de.mm20.launcher2.data.customattrs.CustomIcon import de.mm20.launcher2.data.customattrs.CustomIcon
import de.mm20.launcher2.data.customattrs.CustomIconPackIcon import de.mm20.launcher2.data.customattrs.CustomIconPackIcon
import de.mm20.launcher2.data.customattrs.LegacyCustomIconPackIcon
import de.mm20.launcher2.data.customattrs.CustomThemedIcon import de.mm20.launcher2.data.customattrs.CustomThemedIcon
import de.mm20.launcher2.data.customattrs.DefaultPlaceholderIcon import de.mm20.launcher2.data.customattrs.DefaultPlaceholderIcon
import de.mm20.launcher2.data.customattrs.ForceThemedIcon import de.mm20.launcher2.data.customattrs.ForceThemedIcon
@ -18,6 +19,7 @@ import de.mm20.launcher2.data.customattrs.UnmodifiedSystemDefaultIcon
import de.mm20.launcher2.icons.providers.CalendarIconProvider import de.mm20.launcher2.icons.providers.CalendarIconProvider
import de.mm20.launcher2.icons.providers.CompatIconProvider import de.mm20.launcher2.icons.providers.CompatIconProvider
import de.mm20.launcher2.icons.providers.CustomIconPackIconProvider import de.mm20.launcher2.icons.providers.CustomIconPackIconProvider
import de.mm20.launcher2.icons.providers.LegacyCustomIconPackIconProvider
import de.mm20.launcher2.icons.providers.CustomThemedIconProvider import de.mm20.launcher2.icons.providers.CustomThemedIconProvider
import de.mm20.launcher2.icons.providers.DynamicClockIconProvider import de.mm20.launcher2.icons.providers.DynamicClockIconProvider
import de.mm20.launcher2.icons.providers.IconPackIconProvider import de.mm20.launcher2.icons.providers.IconPackIconProvider
@ -44,7 +46,6 @@ import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class IconService( class IconService(
@ -174,6 +175,14 @@ class IconService(
) )
) )
} }
if (customIcon is LegacyCustomIconPackIcon) {
return listOf(
LegacyCustomIconPackIconProvider(
customIcon,
iconPackManager
)
)
}
if (customIcon is CustomThemedIcon) { if (customIcon is CustomThemedIcon) {
return listOf( return listOf(
CustomThemedIconProvider( CustomThemedIconProvider(
@ -288,11 +297,14 @@ class IconService(
) )
providerOptions.addAll( providerOptions.addAll(
iconPackIcons.mapNotNull { iconPackIcons.map {
val ent = it.toDatabaseEntity()
CustomIconPackIcon( CustomIconPackIcon(
iconPackPackage = it.iconPack, iconPackPackage = it.iconPack,
iconActivityName = it.activityName, type = ent.type,
iconPackageName = it.packageName, drawable = ent.drawable,
extras = ent.extras,
allowThemed = it.themed,
) )
} }
) )
@ -356,20 +368,22 @@ class IconService(
val transformations = this.transformations.first() val transformations = this.transformations.first()
val iconPackIcons = iconPackManager.searchIconPackIcon(query, iconPack).flatMap { val iconPackIcons = iconPackManager.searchIconPackIcon(query, iconPack).flatMap {
val unthemedIcon = if (it.themed) { val unthemedIcon = if (it.themed) {
iconPackManager.getIcon(it.iconPack, it.packageName, it.activityName, false) iconPackManager.getIcon(it.iconPack, it, false)
?.transform(transformations) ?.transform(transformations)
} else null } else null
val icon = iconPackManager.getIcon(it.iconPack, it.packageName, it.activityName, true) val icon = iconPackManager.getIcon(it.iconPack, it, true)
?.transform(transformations) ?.transform(transformations)
buildList<CustomIconWithPreview> { buildList {
val ent = it.toDatabaseEntity()
if (icon != null) { if (icon != null) {
add(CustomIconWithPreview( add(CustomIconWithPreview(
customIcon = CustomIconPackIcon( customIcon = CustomIconPackIcon(
iconPackPackage = it.iconPack, iconPackPackage = it.iconPack,
iconActivityName = it.activityName, type = ent.type,
iconPackageName = it.packageName, drawable = ent.drawable,
allowThemed = true extras = ent.extras,
allowThemed = true,
), ),
preview = icon preview = icon
)) ))
@ -378,9 +392,10 @@ class IconService(
add(CustomIconWithPreview( add(CustomIconWithPreview(
customIcon = CustomIconPackIcon( customIcon = CustomIconPackIcon(
iconPackPackage = it.iconPack, iconPackPackage = it.iconPack,
iconActivityName = it.activityName, type = ent.type,
iconPackageName = it.packageName, drawable = ent.drawable,
allowThemed = false extras = ent.extras,
allowThemed = false,
), ),
preview = unthemedIcon preview = unthemedIcon
)) ))

View File

@ -30,138 +30,181 @@ class AppFilterIconPackInstaller(
) : IconPackInstaller(database) { ) : IconPackInstaller(database) {
override suspend fun IconPackInstallerScope.buildIconPack(iconPack: IconPack) { override suspend fun IconPackInstallerScope.buildIconPack(iconPack: IconPack) {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
val pkgName = iconPack.packageName
try { try {
val dynamicClocks = getDynamicClockIcons(pkgName) val dynamicClocks = getDynamicClockIcons(iconPack.packageName)
val parser = getAppfilterParser(pkgName) ?: return@withContext
loop@ while (parser.next() != XmlPullParser.END_DOCUMENT) { parseAppfilterXml(iconPack, dynamicClocks)
if (parser.eventType != XmlPullParser.START_TAG) continue parseDrawableXml(iconPack, dynamicClocks)
when (parser.name) {
"item" -> {
val component = parser.getAttributeValue(null, "component")
?: continue@loop
val drawable = parser.getAttributeValue(null, "drawable")
?: continue@loop
if (component.length <= 14) continue@loop
val componentName = ComponentName.unflattenFromString(
component.substring(
14,
component.lastIndex
)
)
?: continue@loop
val name = parser.getAttributeValue(null, "name") Log.d("MM20", "Icon pack ${iconPack.packageName} has been installed successfully")
val icon = if (dynamicClocks.containsKey(drawable)) {
ClockIcon(
packageName = componentName.packageName,
activityName = componentName.shortClassName,
iconPack = pkgName,
themed = iconPack.themed,
name = name,
drawable = drawable,
config = dynamicClocks[drawable]!!,
)
} else {
AppIcon(
packageName = componentName.packageName,
activityName = componentName.shortClassName,
drawable = drawable,
iconPack = pkgName,
name = name,
themed = iconPack.themed,
)
}
addIcon(icon)
}
"calendar" -> {
val component = parser.getAttributeValue(null, "component")
?: continue@loop
val drawable = parser.getAttributeValue(null, "prefix") ?: continue@loop
if (component.length < 14) continue@loop
val componentName = ComponentName.unflattenFromString(
component.substring(
14,
component.lastIndex
)
)
?: continue@loop
val name = parser.getAttributeValue(null, "name")
val icon = CalendarIcon(
packageName = componentName.packageName,
activityName = componentName.shortClassName,
drawables = (1..31).map { "$drawable$it" },
iconPack = pkgName,
themed = iconPack.themed,
name = name,
)
addIcon(icon)
}
"iconback" -> {
for (i in 0 until parser.attributeCount) {
if (parser.getAttributeName(i).startsWith("img")) {
val drawable = parser.getAttributeValue(i)
val icon = IconBack(
drawable = drawable,
iconPack = pkgName,
)
addIcon(icon)
}
}
}
"iconupon" -> {
for (i in 0 until parser.attributeCount) {
if (parser.getAttributeName(i).startsWith("img")) {
val drawable = parser.getAttributeValue(i)
val icon = IconUpon(
drawable = drawable,
iconPack = pkgName,
)
addIcon(icon)
}
}
}
"iconmask" -> {
for (i in 0 until parser.attributeCount) {
if (parser.getAttributeName(i).startsWith("img")) {
val drawable = parser.getAttributeValue(i)
val icon = IconMask(
drawable = drawable,
iconPack = pkgName,
)
addIcon(icon)
}
}
}
"scale" -> {
val scale = parser.getAttributeValue(null, "factor")?.toFloatOrNull()
?: continue@loop
updatePackInfo { it.copy(scale = scale) }
}
}
}
parser.close()
Log.d("MM20", "Icon pack $pkgName has been installed successfully")
} catch (e: PackageManager.NameNotFoundException) { } catch (e: PackageManager.NameNotFoundException) {
Log.e("MM20", "Could not install icon pack $pkgName: package not found.") Log.e(
"MM20",
"Could not install icon pack ${iconPack.packageName}: package not found."
)
} catch (e: XmlPullParserException) { } catch (e: XmlPullParserException) {
CrashReporter.logException(e) CrashReporter.logException(e)
} }
} }
} }
private suspend fun IconPackInstallerScope.parseAppfilterXml(
iconPack: IconPack,
dynamicClocks: Map<String, ClockIconConfig>
) {
val pkgName = iconPack.packageName
val parser = getAppfilterParser(pkgName) ?: return
loop@ while (parser.next() != XmlPullParser.END_DOCUMENT) {
if (parser.eventType != XmlPullParser.START_TAG) continue
when (parser.name) {
"item" -> {
val component = parser.getAttributeValue(null, "component")
?: continue@loop
val drawable = parser.getAttributeValue(null, "drawable")
?: continue@loop
if (component.length <= 14) continue@loop
val componentName = ComponentName.unflattenFromString(
component.substring(
14,
component.lastIndex
)
)
?: continue@loop
val name = parser.getAttributeValue(null, "name")
val icon = if (dynamicClocks.containsKey(drawable)) {
ClockIcon(
packageName = componentName.packageName,
activityName = componentName.shortClassName,
iconPack = pkgName,
themed = iconPack.themed,
name = name,
drawable = drawable,
config = dynamicClocks[drawable]!!,
)
} else {
AppIcon(
packageName = componentName.packageName,
activityName = componentName.shortClassName,
drawable = drawable,
iconPack = pkgName,
name = name,
themed = iconPack.themed,
)
}
addIcon(icon)
}
"calendar" -> {
val component = parser.getAttributeValue(null, "component")
?: continue@loop
val drawable = parser.getAttributeValue(null, "prefix") ?: continue@loop
if (component.length < 14) continue@loop
val componentName = ComponentName.unflattenFromString(
component.substring(
14,
component.lastIndex
)
)
?: continue@loop
val name = parser.getAttributeValue(null, "name")
val icon = CalendarIcon(
packageName = componentName.packageName,
activityName = componentName.shortClassName,
drawables = (1..31).map { "$drawable$it" },
iconPack = pkgName,
themed = iconPack.themed,
name = name,
)
addIcon(icon)
}
"iconback" -> {
for (i in 0 until parser.attributeCount) {
if (parser.getAttributeName(i).startsWith("img")) {
val drawable = parser.getAttributeValue(i)
val icon = IconBack(
drawable = drawable,
iconPack = pkgName,
)
addIcon(icon)
}
}
}
"iconupon" -> {
for (i in 0 until parser.attributeCount) {
if (parser.getAttributeName(i).startsWith("img")) {
val drawable = parser.getAttributeValue(i)
val icon = IconUpon(
drawable = drawable,
iconPack = pkgName,
)
addIcon(icon)
}
}
}
"iconmask" -> {
for (i in 0 until parser.attributeCount) {
if (parser.getAttributeName(i).startsWith("img")) {
val drawable = parser.getAttributeValue(i)
val icon = IconMask(
drawable = drawable,
iconPack = pkgName,
)
addIcon(icon)
}
}
}
"scale" -> {
val scale = parser.getAttributeValue(null, "factor")?.toFloatOrNull()
?: continue@loop
updatePackInfo { it.copy(scale = scale) }
}
}
}
parser.close()
}
private suspend fun IconPackInstallerScope.parseDrawableXml(
iconPack: IconPack,
dynamicClocks: Map<String, ClockIconConfig>
) {
val res = context.packageManager.getResourcesForApplication(iconPack.packageName)
val xmlId = res.getIdentifier("drawable", "xml", iconPack.packageName)
if (xmlId == 0) return
val parser = res.getXml(xmlId)
loop@ while (parser.next() != XmlPullParser.END_DOCUMENT) {
if (parser.eventType != XmlPullParser.START_TAG) continue
if (parser.name == "item") {
val drawable = parser.getAttributeValue(null, "drawable") ?: continue@loop
val icon = if (dynamicClocks.containsKey(drawable)) {
ClockIcon(
iconPack = iconPack.packageName,
themed = iconPack.themed,
drawable = drawable,
config = dynamicClocks[drawable]!!,
)
} else {
AppIcon(
drawable = drawable,
iconPack = iconPack.packageName,
themed = iconPack.themed,
)
}
addIcon(icon)
}
}
parser.close()
}
private fun getDynamicClockIcons(packageName: String): Map<String, ClockIconConfig> { private fun getDynamicClockIcons(packageName: String): Map<String, ClockIconConfig> {
val parser = getAppfilterParser(packageName) ?: return emptyMap() val parser = getAppfilterParser(packageName) ?: return emptyMap()
val map = mutableMapOf<String, ClockIconConfig>() val map = mutableMapOf<String, ClockIconConfig>()
@ -190,6 +233,7 @@ class AppFilterIconPackInstaller(
) )
} }
} }
parser.close()
return map return map
} }

View File

@ -1,7 +1,8 @@
package de.mm20.launcher2.icons.providers package de.mm20.launcher2.icons.providers
import android.content.ComponentName
import de.mm20.launcher2.data.customattrs.CustomIconPackIcon import de.mm20.launcher2.data.customattrs.CustomIconPackIcon
import de.mm20.launcher2.database.entities.IconEntity
import de.mm20.launcher2.icons.IconPackAppIcon
import de.mm20.launcher2.icons.IconPackManager import de.mm20.launcher2.icons.IconPackManager
import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.SavableSearchable
@ -11,10 +12,16 @@ class CustomIconPackIconProvider(
private val iconPackManager: IconPackManager, private val iconPackManager: IconPackManager,
) : IconProvider { ) : IconProvider {
override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? { override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? {
val ent = IconEntity(
type = customIcon.type,
drawable = customIcon.drawable,
extras = customIcon.extras,
iconPack = customIcon.iconPackPackage,
)
val icon = IconPackAppIcon(ent) ?: return null
return iconPackManager.getIcon( return iconPackManager.getIcon(
customIcon.iconPackPackage, customIcon.iconPackPackage,
customIcon.iconPackageName, icon,
customIcon.iconActivityName,
customIcon.allowThemed, customIcon.allowThemed,
) )
} }

View File

@ -0,0 +1,21 @@
package de.mm20.launcher2.icons.providers
import de.mm20.launcher2.data.customattrs.LegacyCustomIconPackIcon
import de.mm20.launcher2.icons.IconPackManager
import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.search.SavableSearchable
@Deprecated("Use CustomIconPackIconProvider instead")
class LegacyCustomIconPackIconProvider(
private val customIcon: LegacyCustomIconPackIcon,
private val iconPackManager: IconPackManager,
) : IconProvider {
override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? {
return iconPackManager.getIcon(
customIcon.iconPackPackage,
customIcon.iconPackageName,
customIcon.iconActivityName,
customIcon.allowThemed,
)
}
}