Implement custom legacy to adaptive icon transformations
This commit is contained in:
parent
5bd86e6f95
commit
bb211d4d6a
@ -117,6 +117,7 @@ dependencies {
|
|||||||
implementation(project(":contacts"))
|
implementation(project(":contacts"))
|
||||||
implementation(project(":crashreporter"))
|
implementation(project(":crashreporter"))
|
||||||
implementation(project(":currencies"))
|
implementation(project(":currencies"))
|
||||||
|
implementation(project(":customattrs"))
|
||||||
implementation(project(":favorites"))
|
implementation(project(":favorites"))
|
||||||
implementation(project(":files"))
|
implementation(project(":files"))
|
||||||
implementation(project(":g-services"))
|
implementation(project(":g-services"))
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import de.mm20.launcher2.badges.badgesModule
|
|||||||
import de.mm20.launcher2.calculator.calculatorModule
|
import de.mm20.launcher2.calculator.calculatorModule
|
||||||
import de.mm20.launcher2.calendar.calendarModule
|
import de.mm20.launcher2.calendar.calendarModule
|
||||||
import de.mm20.launcher2.contacts.contactsModule
|
import de.mm20.launcher2.contacts.contactsModule
|
||||||
|
import de.mm20.launcher2.customattrs.customAttrsModule
|
||||||
import de.mm20.launcher2.debug.Debug
|
import de.mm20.launcher2.debug.Debug
|
||||||
import de.mm20.launcher2.favorites.favoritesModule
|
import de.mm20.launcher2.favorites.favoritesModule
|
||||||
import de.mm20.launcher2.files.filesModule
|
import de.mm20.launcher2.files.filesModule
|
||||||
@ -57,6 +58,7 @@ class LauncherApplication : Application(), CoroutineScope, ImageLoaderFactory {
|
|||||||
badgesModule,
|
badgesModule,
|
||||||
calendarModule,
|
calendarModule,
|
||||||
contactsModule,
|
contactsModule,
|
||||||
|
customAttrsModule,
|
||||||
databaseModule,
|
databaseModule,
|
||||||
favoritesModule,
|
favoritesModule,
|
||||||
filesModule,
|
filesModule,
|
||||||
|
|||||||
@ -10,7 +10,8 @@ sealed interface CustomAttribute {
|
|||||||
fun toDatabaseEntity(key: String): CustomAttributeEntity
|
fun toDatabaseEntity(key: String): CustomAttributeEntity
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
internal fun fromDatabaseEntity(entity: CustomAttributeEntity): CustomAttribute? {
|
internal fun fromDatabaseEntity(entity: CustomAttributeEntity?): CustomAttribute? {
|
||||||
|
if (entity == null) return null
|
||||||
return when (entity.type) {
|
return when (entity.type) {
|
||||||
CustomAttributeType.Label.value -> CustomLabel(
|
CustomAttributeType.Label.value -> CustomLabel(
|
||||||
label = entity.value
|
label = entity.value
|
||||||
|
|||||||
@ -1,8 +1,22 @@
|
|||||||
package de.mm20.launcher2.customattrs
|
package de.mm20.launcher2.customattrs
|
||||||
|
|
||||||
|
import de.mm20.launcher2.database.AppDatabase
|
||||||
import de.mm20.launcher2.search.data.Searchable
|
import de.mm20.launcher2.search.data.Searchable
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
interface CustomAttributesRepository {
|
interface CustomAttributesRepository {
|
||||||
fun getCustomAttributes(searchable: Searchable, type: CustomAttributeType? = null): Flow<List<CustomAttribute>>
|
fun getCustomIcon(searchable: Searchable): Flow<CustomIcon?>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CustomAttributesRepositoryImpl(
|
||||||
|
private val appDatabase: AppDatabase,
|
||||||
|
) : CustomAttributesRepository {
|
||||||
|
override fun getCustomIcon(searchable: Searchable): Flow<CustomIcon?> {
|
||||||
|
val dao = appDatabase.customAttrsDao()
|
||||||
|
return dao.getCustomIcon(searchable.key)
|
||||||
|
.map {
|
||||||
|
CustomAttribute.fromDatabaseEntity(it) as? CustomIcon
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -3,5 +3,5 @@ package de.mm20.launcher2.customattrs
|
|||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val customAttrsModule = module {
|
val customAttrsModule = module {
|
||||||
|
single<CustomAttributesRepository> { CustomAttributesRepositoryImpl(get()) }
|
||||||
}
|
}
|
||||||
@ -28,6 +28,7 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
abstract fun widgetDao(): WidgetDao
|
abstract fun widgetDao(): WidgetDao
|
||||||
abstract fun currencyDao(): CurrencyDao
|
abstract fun currencyDao(): CurrencyDao
|
||||||
abstract fun backupDao(): BackupRestoreDao
|
abstract fun backupDao(): BackupRestoreDao
|
||||||
|
abstract fun customAttrsDao(): CustomAttrsDao
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private var _instance: AppDatabase? = null
|
private var _instance: AppDatabase? = null
|
||||||
|
|||||||
@ -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<CustomAttributeEntity?>
|
||||||
|
}
|
||||||
@ -53,5 +53,6 @@ dependencies {
|
|||||||
implementation(project(":search"))
|
implementation(project(":search"))
|
||||||
implementation(project(":applications"))
|
implementation(project(":applications"))
|
||||||
implementation(project(":crashreporter"))
|
implementation(project(":crashreporter"))
|
||||||
|
implementation(project(":customattrs"))
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -5,6 +5,9 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.util.LruCache
|
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.providers.*
|
||||||
import de.mm20.launcher2.icons.transformations.LauncherIconTransformation
|
import de.mm20.launcher2.icons.transformations.LauncherIconTransformation
|
||||||
import de.mm20.launcher2.icons.transformations.LegacyToAdaptiveTransformation
|
import de.mm20.launcher2.icons.transformations.LegacyToAdaptiveTransformation
|
||||||
@ -19,7 +22,8 @@ import kotlinx.coroutines.launch
|
|||||||
class IconRepository(
|
class IconRepository(
|
||||||
val context: Context,
|
val context: Context,
|
||||||
private val iconPackManager: IconPackManager,
|
private val iconPackManager: IconPackManager,
|
||||||
private val dataStore: LauncherDataStore
|
private val dataStore: LauncherDataStore,
|
||||||
|
private val customAttributesRepository: CustomAttributesRepository,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val appReceiver = object : BroadcastReceiver() {
|
private val appReceiver = object : BroadcastReceiver() {
|
||||||
@ -93,36 +97,54 @@ class IconRepository(
|
|||||||
fun getIcon(searchable: Searchable, size: Int): Flow<LauncherIcon> = channelFlow {
|
fun getIcon(searchable: Searchable, size: Int): Flow<LauncherIcon> = channelFlow {
|
||||||
iconProviders.collectLatest { providers ->
|
iconProviders.collectLatest { providers ->
|
||||||
transformations.collectLatest { transformations ->
|
transformations.collectLatest { transformations ->
|
||||||
var icon = cache.get(searchable.key)
|
customAttributesRepository.getCustomIcon(searchable).collectLatest { customIcon ->
|
||||||
if (icon != null) {
|
|
||||||
send(icon)
|
|
||||||
return@collectLatest
|
|
||||||
}
|
|
||||||
|
|
||||||
val placeholder = placeholderProvider?.getIcon(searchable, size)
|
val transforms = getTransformations(customIcon) ?: transformations
|
||||||
placeholder?.let { send(it) }
|
|
||||||
|
|
||||||
for (provider in providers) {
|
var icon = cache.get(searchable.key + customIcon.hashCode())
|
||||||
val ic = provider.getIcon(searchable, size)
|
if (icon != null) {
|
||||||
if (ic != null) {
|
send(icon)
|
||||||
icon = ic
|
return@collectLatest
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (icon != null) {
|
val placeholder = placeholderProvider?.getIcon(searchable, size)
|
||||||
if (icon is StaticLauncherIcon) {
|
placeholder?.let { send(it) }
|
||||||
for (transformation in transformations) {
|
|
||||||
icon = transformation.transform(icon as StaticLauncherIcon)
|
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)
|
cache.put(searchable.key + customIcon.hashCode(), icon)
|
||||||
send(icon)
|
send(icon)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getTransformations(customIcon: CustomIcon?): List<LauncherIconTransformation>? {
|
||||||
|
customIcon ?: return null
|
||||||
|
if (customIcon is AdaptifiedLegacyIcon) {
|
||||||
|
return listOf(
|
||||||
|
LegacyToAdaptiveTransformation(
|
||||||
|
foregroundScale = customIcon.fgScale,
|
||||||
|
backgroundColor = customIcon.bgColor
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun requestIconPackListUpdate() {
|
fun requestIconPackListUpdate() {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
|||||||
@ -5,5 +5,5 @@ import org.koin.dsl.module
|
|||||||
|
|
||||||
val iconsModule = module {
|
val iconsModule = module {
|
||||||
single { IconPackManager(androidContext()) }
|
single { IconPackManager(androidContext()) }
|
||||||
single { IconRepository(androidContext(), get(), get()) }
|
single { IconRepository(androidContext(), get(), get(), get()) }
|
||||||
}
|
}
|
||||||
@ -7,13 +7,16 @@ import de.mm20.launcher2.icons.*
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
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 {
|
override suspend fun transform(icon: StaticLauncherIcon): StaticLauncherIcon {
|
||||||
if (icon.backgroundLayer !is TransparentLayer) return icon
|
if (icon.backgroundLayer !is TransparentLayer) return icon
|
||||||
|
|
||||||
val bgColor = extractColor(icon.foregroundLayer)
|
val bgColor = if (backgroundColor == 1) extractColor(icon.foregroundLayer) else backgroundColor
|
||||||
return StaticLauncherIcon(
|
return StaticLauncherIcon(
|
||||||
foregroundLayer = scale(icon.foregroundLayer, 0.7f),
|
foregroundLayer = scale(icon.foregroundLayer, foregroundScale),
|
||||||
backgroundLayer = ColorLayer(bgColor)
|
backgroundLayer = ColorLayer(bgColor)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,7 +60,7 @@ dependencyResolutionManagement {
|
|||||||
listOf("kotlin.stdlib", "kotlinx.coroutines.core", "kotlinx.coroutines.android")
|
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")
|
alias("androidx.compose.runtime")
|
||||||
.to("androidx.compose.runtime", "runtime")
|
.to("androidx.compose.runtime", "runtime")
|
||||||
.version("1.2.0-rc03")
|
.version("1.2.0-rc03")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user