From bb211d4d6a72251118c2b97a6d4f96498e95cba2 Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Sun, 24 Jul 2022 20:47:10 +0200 Subject: [PATCH] Implement custom legacy to adaptive icon transformations --- app/build.gradle.kts | 1 + .../de/mm20/launcher2/LauncherApplication.kt | 2 + .../launcher2/customattrs/CustomAttribute.kt | 3 +- .../customattrs/CustomAttributesRepository.kt | 16 ++++- .../de/mm20/launcher2/customattrs/Module.kt | 2 +- .../de/mm20/launcher2/database/AppDatabase.kt | 1 + .../mm20/launcher2/database/CustomAttrsDao.kt | 12 ++++ icons/build.gradle.kts | 1 + .../de/mm20/launcher2/icons/IconRepository.kt | 62 +++++++++++++------ .../java/de/mm20/launcher2/icons/Module.kt | 2 +- .../LegacyToAdaptiveTransformation.kt | 9 ++- settings.gradle.kts | 2 +- 12 files changed, 85 insertions(+), 28 deletions(-) create mode 100644 database/src/main/java/de/mm20/launcher2/database/CustomAttrsDao.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b04010e5..0ed17a9d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -117,6 +117,7 @@ dependencies { implementation(project(":contacts")) implementation(project(":crashreporter")) implementation(project(":currencies")) + implementation(project(":customattrs")) implementation(project(":favorites")) implementation(project(":files")) implementation(project(":g-services")) diff --git a/app/src/main/java/de/mm20/launcher2/LauncherApplication.kt b/app/src/main/java/de/mm20/launcher2/LauncherApplication.kt index dc2850e4..e9052a59 100644 --- a/app/src/main/java/de/mm20/launcher2/LauncherApplication.kt +++ b/app/src/main/java/de/mm20/launcher2/LauncherApplication.kt @@ -12,6 +12,7 @@ import de.mm20.launcher2.badges.badgesModule import de.mm20.launcher2.calculator.calculatorModule import de.mm20.launcher2.calendar.calendarModule import de.mm20.launcher2.contacts.contactsModule +import de.mm20.launcher2.customattrs.customAttrsModule import de.mm20.launcher2.debug.Debug import de.mm20.launcher2.favorites.favoritesModule import de.mm20.launcher2.files.filesModule @@ -57,6 +58,7 @@ class LauncherApplication : Application(), CoroutineScope, ImageLoaderFactory { badgesModule, calendarModule, contactsModule, + customAttrsModule, databaseModule, favoritesModule, filesModule, diff --git a/customattrs/src/main/java/de/mm20/launcher2/customattrs/CustomAttribute.kt b/customattrs/src/main/java/de/mm20/launcher2/customattrs/CustomAttribute.kt index 3bbaa718..9e4891cd 100644 --- a/customattrs/src/main/java/de/mm20/launcher2/customattrs/CustomAttribute.kt +++ b/customattrs/src/main/java/de/mm20/launcher2/customattrs/CustomAttribute.kt @@ -10,7 +10,8 @@ sealed interface CustomAttribute { fun toDatabaseEntity(key: String): CustomAttributeEntity companion object { - internal fun fromDatabaseEntity(entity: CustomAttributeEntity): CustomAttribute? { + internal fun fromDatabaseEntity(entity: CustomAttributeEntity?): CustomAttribute? { + if (entity == null) return null return when (entity.type) { CustomAttributeType.Label.value -> CustomLabel( label = entity.value diff --git a/customattrs/src/main/java/de/mm20/launcher2/customattrs/CustomAttributesRepository.kt b/customattrs/src/main/java/de/mm20/launcher2/customattrs/CustomAttributesRepository.kt index d50fcdb1..b0aa18fa 100644 --- a/customattrs/src/main/java/de/mm20/launcher2/customattrs/CustomAttributesRepository.kt +++ b/customattrs/src/main/java/de/mm20/launcher2/customattrs/CustomAttributesRepository.kt @@ -1,8 +1,22 @@ package de.mm20.launcher2.customattrs +import de.mm20.launcher2.database.AppDatabase import de.mm20.launcher2.search.data.Searchable import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map interface CustomAttributesRepository { - fun getCustomAttributes(searchable: Searchable, type: CustomAttributeType? = null): Flow> + fun getCustomIcon(searchable: Searchable): Flow +} + +internal class CustomAttributesRepositoryImpl( + private val appDatabase: AppDatabase, +) : CustomAttributesRepository { + override fun getCustomIcon(searchable: Searchable): Flow { + val dao = appDatabase.customAttrsDao() + return dao.getCustomIcon(searchable.key) + .map { + CustomAttribute.fromDatabaseEntity(it) as? CustomIcon + } + } } \ No newline at end of file diff --git a/customattrs/src/main/java/de/mm20/launcher2/customattrs/Module.kt b/customattrs/src/main/java/de/mm20/launcher2/customattrs/Module.kt index ea9b181f..6088e7db 100644 --- a/customattrs/src/main/java/de/mm20/launcher2/customattrs/Module.kt +++ b/customattrs/src/main/java/de/mm20/launcher2/customattrs/Module.kt @@ -3,5 +3,5 @@ package de.mm20.launcher2.customattrs import org.koin.dsl.module val customAttrsModule = module { - + single { CustomAttributesRepositoryImpl(get()) } } \ No newline at end of file diff --git a/database/src/main/java/de/mm20/launcher2/database/AppDatabase.kt b/database/src/main/java/de/mm20/launcher2/database/AppDatabase.kt index 85e14f14..59ea79ba 100644 --- a/database/src/main/java/de/mm20/launcher2/database/AppDatabase.kt +++ b/database/src/main/java/de/mm20/launcher2/database/AppDatabase.kt @@ -28,6 +28,7 @@ abstract class AppDatabase : RoomDatabase() { abstract fun widgetDao(): WidgetDao abstract fun currencyDao(): CurrencyDao abstract fun backupDao(): BackupRestoreDao + abstract fun customAttrsDao(): CustomAttrsDao companion object { private var _instance: AppDatabase? = null diff --git a/database/src/main/java/de/mm20/launcher2/database/CustomAttrsDao.kt b/database/src/main/java/de/mm20/launcher2/database/CustomAttrsDao.kt new file mode 100644 index 00000000..6c9def2d --- /dev/null +++ b/database/src/main/java/de/mm20/launcher2/database/CustomAttrsDao.kt @@ -0,0 +1,12 @@ +package de.mm20.launcher2.database + +import androidx.room.Dao +import androidx.room.Query +import de.mm20.launcher2.database.entities.CustomAttributeEntity +import kotlinx.coroutines.flow.Flow + +@Dao +interface CustomAttrsDao { + @Query("SELECT * FROM CustomAttributes WHERE type = 'icon' AND key = :key LIMIT 1") + fun getCustomIcon(key: String) : Flow +} \ No newline at end of file diff --git a/icons/build.gradle.kts b/icons/build.gradle.kts index 7968632f..ea116fb4 100644 --- a/icons/build.gradle.kts +++ b/icons/build.gradle.kts @@ -53,5 +53,6 @@ dependencies { implementation(project(":search")) implementation(project(":applications")) implementation(project(":crashreporter")) + implementation(project(":customattrs")) } \ No newline at end of file diff --git a/icons/src/main/java/de/mm20/launcher2/icons/IconRepository.kt b/icons/src/main/java/de/mm20/launcher2/icons/IconRepository.kt index 6a9cad25..64e26135 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/IconRepository.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/IconRepository.kt @@ -5,6 +5,9 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.util.LruCache +import de.mm20.launcher2.customattrs.AdaptifiedLegacyIcon +import de.mm20.launcher2.customattrs.CustomAttributesRepository +import de.mm20.launcher2.customattrs.CustomIcon import de.mm20.launcher2.icons.providers.* import de.mm20.launcher2.icons.transformations.LauncherIconTransformation import de.mm20.launcher2.icons.transformations.LegacyToAdaptiveTransformation @@ -19,7 +22,8 @@ import kotlinx.coroutines.launch class IconRepository( val context: Context, private val iconPackManager: IconPackManager, - private val dataStore: LauncherDataStore + private val dataStore: LauncherDataStore, + private val customAttributesRepository: CustomAttributesRepository, ) { private val appReceiver = object : BroadcastReceiver() { @@ -93,36 +97,54 @@ class IconRepository( fun getIcon(searchable: Searchable, size: Int): Flow = channelFlow { iconProviders.collectLatest { providers -> transformations.collectLatest { transformations -> - var icon = cache.get(searchable.key) - if (icon != null) { - send(icon) - return@collectLatest - } + customAttributesRepository.getCustomIcon(searchable).collectLatest { customIcon -> - val placeholder = placeholderProvider?.getIcon(searchable, size) - placeholder?.let { send(it) } + val transforms = getTransformations(customIcon) ?: transformations - for (provider in providers) { - val ic = provider.getIcon(searchable, size) - if (ic != null) { - icon = ic - break + var icon = cache.get(searchable.key + customIcon.hashCode()) + if (icon != null) { + send(icon) + return@collectLatest } - } - if (icon != null) { - if (icon is StaticLauncherIcon) { - for (transformation in transformations) { - icon = transformation.transform(icon as StaticLauncherIcon) + + val placeholder = placeholderProvider?.getIcon(searchable, size) + placeholder?.let { send(it) } + + for (provider in providers) { + val ic = provider.getIcon(searchable, size) + if (ic != null) { + icon = ic + break } } + if (icon != null) { + if (icon is StaticLauncherIcon) { + for (transformation in transforms) { + icon = transformation.transform(icon as StaticLauncherIcon) + } + } - cache.put(searchable.key, icon) - send(icon) + cache.put(searchable.key + customIcon.hashCode(), icon) + send(icon) + } } } } } + private fun getTransformations(customIcon: CustomIcon?): List? { + customIcon ?: return null + if (customIcon is AdaptifiedLegacyIcon) { + return listOf( + LegacyToAdaptiveTransformation( + foregroundScale = customIcon.fgScale, + backgroundColor = customIcon.bgColor + ) + ) + } + return null + } + fun requestIconPackListUpdate() { scope.launch { diff --git a/icons/src/main/java/de/mm20/launcher2/icons/Module.kt b/icons/src/main/java/de/mm20/launcher2/icons/Module.kt index 507cd96f..f2f7d597 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/Module.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/Module.kt @@ -5,5 +5,5 @@ import org.koin.dsl.module val iconsModule = module { single { IconPackManager(androidContext()) } - single { IconRepository(androidContext(), get(), get()) } + single { IconRepository(androidContext(), get(), get(), get()) } } \ No newline at end of file diff --git a/icons/src/main/java/de/mm20/launcher2/icons/transformations/LegacyToAdaptiveTransformation.kt b/icons/src/main/java/de/mm20/launcher2/icons/transformations/LegacyToAdaptiveTransformation.kt index 80efbb49..60d426be 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/transformations/LegacyToAdaptiveTransformation.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/transformations/LegacyToAdaptiveTransformation.kt @@ -7,13 +7,16 @@ import de.mm20.launcher2.icons.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -internal class LegacyToAdaptiveTransformation: LauncherIconTransformation { +internal class LegacyToAdaptiveTransformation( + private val foregroundScale: Float = 0.7f, + private val backgroundColor: Int = 1, +): LauncherIconTransformation { override suspend fun transform(icon: StaticLauncherIcon): StaticLauncherIcon { if (icon.backgroundLayer !is TransparentLayer) return icon - val bgColor = extractColor(icon.foregroundLayer) + val bgColor = if (backgroundColor == 1) extractColor(icon.foregroundLayer) else backgroundColor return StaticLauncherIcon( - foregroundLayer = scale(icon.foregroundLayer, 0.7f), + foregroundLayer = scale(icon.foregroundLayer, foregroundScale), backgroundLayer = ColorLayer(bgColor) ) } diff --git a/settings.gradle.kts b/settings.gradle.kts index 56c90284..5ddafaef 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -60,7 +60,7 @@ dependencyResolutionManagement { listOf("kotlin.stdlib", "kotlinx.coroutines.core", "kotlinx.coroutines.android") ) - version("androidx.compose.compiler", "1.2.0") + version("androidx.compose.compiler", "1.3.0-beta01") alias("androidx.compose.runtime") .to("androidx.compose.runtime", "runtime") .version("1.2.0-rc03")