diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/component/ShapedLauncherIcon.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/component/ShapedLauncherIcon.kt index a232d6f9..e2f3d474 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/component/ShapedLauncherIcon.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/component/ShapedLauncherIcon.kt @@ -60,6 +60,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import de.mm20.launcher2.badges.Badge +import de.mm20.launcher2.badges.BadgeIcon import de.mm20.launcher2.icons.ClockLayer import de.mm20.launcher2.icons.ClockSublayer import de.mm20.launcher2.icons.ClockSublayerRole @@ -239,12 +240,11 @@ fun ShapedLauncherIcon( val _badge = badge() if (_badge != null) { Surface( - shadowElevation = 1.dp, tonalElevation = 1.dp, modifier = Modifier .size(size * 0.33f) .align(Alignment.BottomEnd), - color = MaterialTheme.colorScheme.secondary, + color = MaterialTheme.colorScheme.tertiary, shape = CircleShape ) { Box( @@ -255,37 +255,37 @@ fun ShapedLauncherIcon( val progress by animateFloatAsState(it) CircularProgressIndicator( modifier = Modifier.fillMaxSize(0.8f), - progress = progress, + progress = { progress }, strokeWidth = size / 48, - color = MaterialTheme.colorScheme.secondaryContainer + color = MaterialTheme.colorScheme.onTertiary ) } - val badgeIconRes = _badge.iconRes val badgeIcon = _badge.icon val number = _badge.number - if (badgeIconRes != null) { - Image( + if (badgeIcon is BadgeIcon.Vector) { + Icon( modifier = Modifier .fillMaxSize() - .padding(size / 48), - painter = painterResource(badgeIconRes), - contentDescription = null + .padding(size / 24), + imageVector = badgeIcon.imageVector, + contentDescription = null, + tint = MaterialTheme.colorScheme.onTertiary, ) - } else if (badgeIcon != null) { + } else if (badgeIcon is BadgeIcon.Drawable) { Canvas( modifier = Modifier .fillMaxSize() .padding(size / 48) ) { - badgeIcon.setBounds( + badgeIcon.drawable.setBounds( 0, 0, this.size.width.roundToInt(), this.size.height.roundToInt() ) drawIntoCanvas { - badgeIcon.draw(it.nativeCanvas) + badgeIcon.drawable.draw(it.nativeCanvas) } } } else if (number != null && number > 0 && number < 100) { diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/CustomizeSearchableSheet.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/CustomizeSearchableSheet.kt index ef8455e2..af94dc05 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/CustomizeSearchableSheet.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/CustomizeSearchableSheet.kt @@ -20,6 +20,7 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.ArrowDropDown +import androidx.compose.material.icons.rounded.Edit import androidx.compose.material.icons.rounded.FilterAlt import androidx.compose.material.icons.rounded.Search import androidx.compose.material3.Button @@ -51,6 +52,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import de.mm20.launcher2.badges.Badge +import de.mm20.launcher2.badges.BadgeIcon import de.mm20.launcher2.icons.CustomIconWithPreview import de.mm20.launcher2.icons.IconPack import de.mm20.launcher2.search.SavableSearchable @@ -106,22 +108,13 @@ fun CustomizeSearchableSheet( val iconSize = 64.dp val iconSizePx = iconSize.toPixels() val icon by remember { viewModel.getIcon(iconSizePx.toInt()) }.collectAsState(null) - val primaryColor = MaterialTheme.colorScheme.onSecondary - val badgeDrawable = remember { - InsetDrawable( - AppCompatResources.getDrawable(context, R.drawable.ic_edit), - 8 - ).also { - it.setTint(primaryColor.toArgb()) - } - } ShapedLauncherIcon( size = iconSize, icon = { icon }, badge = { Badge( - icon = badgeDrawable + icon = BadgeIcon(Icons.Rounded.Edit) ) }, modifier = Modifier.clickable { diff --git a/services/badges/build.gradle.kts b/services/badges/build.gradle.kts index 8a1187c3..2793b180 100644 --- a/services/badges/build.gradle.kts +++ b/services/badges/build.gradle.kts @@ -38,7 +38,7 @@ dependencies { implementation(libs.bundles.kotlin) implementation(libs.androidx.core) implementation(libs.androidx.appcompat) - + implementation(libs.androidx.compose.materialicons) implementation(libs.bundles.androidx.lifecycle) implementation(libs.koin.android) diff --git a/services/badges/src/main/java/de/mm20/launcher2/badges/Badge.kt b/services/badges/src/main/java/de/mm20/launcher2/badges/Badge.kt index a91d0f40..26de8c16 100644 --- a/services/badges/src/main/java/de/mm20/launcher2/badges/Badge.kt +++ b/services/badges/src/main/java/de/mm20/launcher2/badges/Badge.kt @@ -2,26 +2,36 @@ package de.mm20.launcher2.badges import android.graphics.drawable.Drawable import android.util.Log +import androidx.compose.ui.graphics.vector.ImageVector + +sealed interface BadgeIcon { + @JvmInline + value class Drawable(val drawable: android.graphics.drawable.Drawable): BadgeIcon + + @JvmInline + value class Vector(val imageVector: ImageVector): BadgeIcon +} + +fun BadgeIcon(drawable: Drawable): BadgeIcon = BadgeIcon.Drawable(drawable) + +fun BadgeIcon(imageVector: ImageVector): BadgeIcon = BadgeIcon.Vector(imageVector) interface Badge { val number: Int? val progress: Float? - val iconRes: Int? - val icon: Drawable? + val icon: BadgeIcon? } fun Badge( number: Int? = null, progress: Float? = null, - iconRes: Int? = null, - icon: Drawable? = null -): Badge = MutableBadge(number, progress, iconRes, icon) + icon: BadgeIcon? = null +): Badge = MutableBadge(number, progress, icon) internal data class MutableBadge( override var number: Int? = null, override var progress: Float? = null, - override var iconRes: Int? = null, - override var icon: Drawable? = null + override var icon: BadgeIcon? = null ): Badge fun Collection.combine(): Badge? { @@ -30,7 +40,6 @@ fun Collection.combine(): Badge? { var progresses = 0 forEach { if (it.icon != null && badge.icon == null) badge.icon = it.icon - if (it.iconRes != null && badge.iconRes == null) badge.iconRes = it.iconRes it.number?.let { a -> badge.number?.let { b -> badge.number = a + b } ?: run { badge.number = a diff --git a/services/badges/src/main/java/de/mm20/launcher2/badges/BadgeService.kt b/services/badges/src/main/java/de/mm20/launcher2/badges/BadgeService.kt index 68890c0a..eb9ba19b 100644 --- a/services/badges/src/main/java/de/mm20/launcher2/badges/BadgeService.kt +++ b/services/badges/src/main/java/de/mm20/launcher2/badges/BadgeService.kt @@ -47,7 +47,7 @@ internal class BadgeServiceImpl( providers += NotificationBadgeProvider() } if (it.cloudFiles) { - providers += CloudBadgeProvider() + providers += CloudBadgeProvider(context) } if (it.shortcuts) { providers += AppShortcutBadgeProvider(context) diff --git a/services/badges/src/main/java/de/mm20/launcher2/badges/providers/AppShortcutBadgeProvider.kt b/services/badges/src/main/java/de/mm20/launcher2/badges/providers/AppShortcutBadgeProvider.kt index b28c0bb3..8a22e8fa 100644 --- a/services/badges/src/main/java/de/mm20/launcher2/badges/providers/AppShortcutBadgeProvider.kt +++ b/services/badges/src/main/java/de/mm20/launcher2/badges/providers/AppShortcutBadgeProvider.kt @@ -3,6 +3,7 @@ package de.mm20.launcher2.badges.providers import android.content.Context import android.content.pm.PackageManager import de.mm20.launcher2.badges.Badge +import de.mm20.launcher2.badges.BadgeIcon import de.mm20.launcher2.badges.MutableBadge import de.mm20.launcher2.graphics.BadgeDrawable import de.mm20.launcher2.search.AppShortcut @@ -28,7 +29,7 @@ class AppShortcutBadgeProvider( } catch (e: PackageManager.NameNotFoundException) { return@withContext } - val badge = MutableBadge(icon = BadgeDrawable(context, icon)) + val badge = MutableBadge(icon = BadgeIcon(BadgeDrawable(context, icon))) send(badge) } } else if (packageName != null) { @@ -40,7 +41,7 @@ class AppShortcutBadgeProvider( } catch (e: PackageManager.NameNotFoundException) { return@withContext } - val badge = MutableBadge(icon = BadgeDrawable(context, icon)) + val badge = MutableBadge(icon = BadgeIcon(BadgeDrawable(context, icon))) send(badge) } } else { diff --git a/services/badges/src/main/java/de/mm20/launcher2/badges/providers/CloudBadgeProvider.kt b/services/badges/src/main/java/de/mm20/launcher2/badges/providers/CloudBadgeProvider.kt index 934aff41..c97d7593 100644 --- a/services/badges/src/main/java/de/mm20/launcher2/badges/providers/CloudBadgeProvider.kt +++ b/services/badges/src/main/java/de/mm20/launcher2/badges/providers/CloudBadgeProvider.kt @@ -1,6 +1,9 @@ package de.mm20.launcher2.badges.providers +import android.content.Context +import androidx.compose.material.icons.Icons import de.mm20.launcher2.badges.Badge +import de.mm20.launcher2.badges.BadgeIcon import de.mm20.launcher2.badges.MutableBadge import de.mm20.launcher2.search.File import de.mm20.launcher2.search.Searchable @@ -8,12 +11,14 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf -class CloudBadgeProvider: BadgeProvider { +class CloudBadgeProvider( + private val context: Context +): BadgeProvider { override fun getBadge(searchable: Searchable): Flow { if (searchable is File) { val iconResId = searchable.providerIconRes if (iconResId != null) { - return flowOf(MutableBadge(iconRes = iconResId)) + return flowOf(MutableBadge(icon = BadgeIcon(context.getDrawable(iconResId)!!))) } } return flowOf(null) diff --git a/services/badges/src/main/java/de/mm20/launcher2/badges/providers/HiddenItemBadgeProvider.kt b/services/badges/src/main/java/de/mm20/launcher2/badges/providers/HiddenItemBadgeProvider.kt index 9a324873..37dd15b0 100644 --- a/services/badges/src/main/java/de/mm20/launcher2/badges/providers/HiddenItemBadgeProvider.kt +++ b/services/badges/src/main/java/de/mm20/launcher2/badges/providers/HiddenItemBadgeProvider.kt @@ -1,6 +1,10 @@ package de.mm20.launcher2.badges.providers +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.HourglassBottom +import androidx.compose.material.icons.rounded.VisibilityOff import de.mm20.launcher2.badges.Badge +import de.mm20.launcher2.badges.BadgeIcon import de.mm20.launcher2.badges.R import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.Searchable @@ -33,7 +37,7 @@ class HiddenItemBadgeProvider( return hiddenItemKeys.map { keys -> if (searchable.key in keys) { Badge( - iconRes = R.drawable.ic_badge_hidden + icon = BadgeIcon(Icons.Rounded.VisibilityOff) ) } else { null diff --git a/services/badges/src/main/java/de/mm20/launcher2/badges/providers/PluginBadgeProvider.kt b/services/badges/src/main/java/de/mm20/launcher2/badges/providers/PluginBadgeProvider.kt index 0745e4b0..271fd4ea 100644 --- a/services/badges/src/main/java/de/mm20/launcher2/badges/providers/PluginBadgeProvider.kt +++ b/services/badges/src/main/java/de/mm20/launcher2/badges/providers/PluginBadgeProvider.kt @@ -2,6 +2,7 @@ package de.mm20.launcher2.badges.providers import android.content.Context import de.mm20.launcher2.badges.Badge +import de.mm20.launcher2.badges.BadgeIcon import de.mm20.launcher2.badges.MutableBadge import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.Searchable @@ -16,7 +17,7 @@ class PluginBadgeProvider(private val context: Context): BadgeProvider { emit(null) val icon = searchable.getProviderIcon(context) if (icon != null) { - emit(MutableBadge(icon = icon)) + emit(MutableBadge(icon = BadgeIcon(icon))) } } } diff --git a/services/badges/src/main/java/de/mm20/launcher2/badges/providers/SuspendedAppsBadgeProvider.kt b/services/badges/src/main/java/de/mm20/launcher2/badges/providers/SuspendedAppsBadgeProvider.kt index 6dc8495d..c25fb5fa 100644 --- a/services/badges/src/main/java/de/mm20/launcher2/badges/providers/SuspendedAppsBadgeProvider.kt +++ b/services/badges/src/main/java/de/mm20/launcher2/badges/providers/SuspendedAppsBadgeProvider.kt @@ -1,6 +1,9 @@ package de.mm20.launcher2.badges.providers +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.HourglassBottom import de.mm20.launcher2.badges.Badge +import de.mm20.launcher2.badges.BadgeIcon import de.mm20.launcher2.badges.MutableBadge import de.mm20.launcher2.badges.R import de.mm20.launcher2.search.Application @@ -14,7 +17,7 @@ class SuspendedAppsBadgeProvider : BadgeProvider, KoinComponent { override fun getBadge(searchable: Searchable): Flow { return if (searchable is Application && searchable.isSuspended) { - flowOf(MutableBadge(iconRes = R.drawable.ic_badge_suspended)) + flowOf(MutableBadge(icon = BadgeIcon(Icons.Rounded.HourglassBottom))) } else { flowOf(null) } diff --git a/services/badges/src/main/java/de/mm20/launcher2/badges/providers/WorkProfileBadgeProvider.kt b/services/badges/src/main/java/de/mm20/launcher2/badges/providers/WorkProfileBadgeProvider.kt index df8e1c96..85df6db5 100644 --- a/services/badges/src/main/java/de/mm20/launcher2/badges/providers/WorkProfileBadgeProvider.kt +++ b/services/badges/src/main/java/de/mm20/launcher2/badges/providers/WorkProfileBadgeProvider.kt @@ -1,6 +1,9 @@ package de.mm20.launcher2.badges.providers +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.Work import de.mm20.launcher2.badges.Badge +import de.mm20.launcher2.badges.BadgeIcon import de.mm20.launcher2.badges.MutableBadge import de.mm20.launcher2.badges.R import de.mm20.launcher2.search.AppProfile @@ -15,7 +18,7 @@ class WorkProfileBadgeProvider : BadgeProvider { if (searchable is Application && searchable.profile == AppProfile.Work || searchable is AppShortcut && searchable.profile == AppProfile.Work) { emit( MutableBadge( - iconRes = R.drawable.ic_badge_workprofile + icon = BadgeIcon(Icons.Rounded.Work) ) ) } else {