Use imageVectors in badges and fix badge icon colors
This commit is contained in:
parent
553ab2d9c2
commit
a63f434efc
@ -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) {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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<Badge>.combine(): Badge? {
|
||||
@ -30,7 +40,6 @@ fun Collection<Badge>.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
|
||||
|
||||
@ -47,7 +47,7 @@ internal class BadgeServiceImpl(
|
||||
providers += NotificationBadgeProvider()
|
||||
}
|
||||
if (it.cloudFiles) {
|
||||
providers += CloudBadgeProvider()
|
||||
providers += CloudBadgeProvider(context)
|
||||
}
|
||||
if (it.shortcuts) {
|
||||
providers += AppShortcutBadgeProvider(context)
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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<Badge?> {
|
||||
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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<Badge?> {
|
||||
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)
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user