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.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import de.mm20.launcher2.badges.Badge
|
import de.mm20.launcher2.badges.Badge
|
||||||
|
import de.mm20.launcher2.badges.BadgeIcon
|
||||||
import de.mm20.launcher2.icons.ClockLayer
|
import de.mm20.launcher2.icons.ClockLayer
|
||||||
import de.mm20.launcher2.icons.ClockSublayer
|
import de.mm20.launcher2.icons.ClockSublayer
|
||||||
import de.mm20.launcher2.icons.ClockSublayerRole
|
import de.mm20.launcher2.icons.ClockSublayerRole
|
||||||
@ -239,12 +240,11 @@ fun ShapedLauncherIcon(
|
|||||||
val _badge = badge()
|
val _badge = badge()
|
||||||
if (_badge != null) {
|
if (_badge != null) {
|
||||||
Surface(
|
Surface(
|
||||||
shadowElevation = 1.dp,
|
|
||||||
tonalElevation = 1.dp,
|
tonalElevation = 1.dp,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(size * 0.33f)
|
.size(size * 0.33f)
|
||||||
.align(Alignment.BottomEnd),
|
.align(Alignment.BottomEnd),
|
||||||
color = MaterialTheme.colorScheme.secondary,
|
color = MaterialTheme.colorScheme.tertiary,
|
||||||
shape = CircleShape
|
shape = CircleShape
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
@ -255,37 +255,37 @@ fun ShapedLauncherIcon(
|
|||||||
val progress by animateFloatAsState(it)
|
val progress by animateFloatAsState(it)
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
modifier = Modifier.fillMaxSize(0.8f),
|
modifier = Modifier.fillMaxSize(0.8f),
|
||||||
progress = progress,
|
progress = { progress },
|
||||||
strokeWidth = size / 48,
|
strokeWidth = size / 48,
|
||||||
color = MaterialTheme.colorScheme.secondaryContainer
|
color = MaterialTheme.colorScheme.onTertiary
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val badgeIconRes = _badge.iconRes
|
|
||||||
val badgeIcon = _badge.icon
|
val badgeIcon = _badge.icon
|
||||||
|
|
||||||
val number = _badge.number
|
val number = _badge.number
|
||||||
if (badgeIconRes != null) {
|
if (badgeIcon is BadgeIcon.Vector) {
|
||||||
Image(
|
Icon(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(size / 48),
|
.padding(size / 24),
|
||||||
painter = painterResource(badgeIconRes),
|
imageVector = badgeIcon.imageVector,
|
||||||
contentDescription = null
|
contentDescription = null,
|
||||||
|
tint = MaterialTheme.colorScheme.onTertiary,
|
||||||
)
|
)
|
||||||
} else if (badgeIcon != null) {
|
} else if (badgeIcon is BadgeIcon.Drawable) {
|
||||||
Canvas(
|
Canvas(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(size / 48)
|
.padding(size / 48)
|
||||||
) {
|
) {
|
||||||
badgeIcon.setBounds(
|
badgeIcon.drawable.setBounds(
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
this.size.width.roundToInt(),
|
this.size.width.roundToInt(),
|
||||||
this.size.height.roundToInt()
|
this.size.height.roundToInt()
|
||||||
)
|
)
|
||||||
drawIntoCanvas {
|
drawIntoCanvas {
|
||||||
badgeIcon.draw(it.nativeCanvas)
|
badgeIcon.drawable.draw(it.nativeCanvas)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (number != null && number > 0 && number < 100) {
|
} 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.foundation.lazy.grid.items
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.rounded.ArrowDropDown
|
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.FilterAlt
|
||||||
import androidx.compose.material.icons.rounded.Search
|
import androidx.compose.material.icons.rounded.Search
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
@ -51,6 +52,7 @@ import androidx.compose.ui.unit.Dp
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import de.mm20.launcher2.badges.Badge
|
import de.mm20.launcher2.badges.Badge
|
||||||
|
import de.mm20.launcher2.badges.BadgeIcon
|
||||||
import de.mm20.launcher2.icons.CustomIconWithPreview
|
import de.mm20.launcher2.icons.CustomIconWithPreview
|
||||||
import de.mm20.launcher2.icons.IconPack
|
import de.mm20.launcher2.icons.IconPack
|
||||||
import de.mm20.launcher2.search.SavableSearchable
|
import de.mm20.launcher2.search.SavableSearchable
|
||||||
@ -106,22 +108,13 @@ fun CustomizeSearchableSheet(
|
|||||||
val iconSize = 64.dp
|
val iconSize = 64.dp
|
||||||
val iconSizePx = iconSize.toPixels()
|
val iconSizePx = iconSize.toPixels()
|
||||||
val icon by remember { viewModel.getIcon(iconSizePx.toInt()) }.collectAsState(null)
|
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(
|
ShapedLauncherIcon(
|
||||||
size = iconSize,
|
size = iconSize,
|
||||||
icon = { icon },
|
icon = { icon },
|
||||||
badge = {
|
badge = {
|
||||||
Badge(
|
Badge(
|
||||||
icon = badgeDrawable
|
icon = BadgeIcon(Icons.Rounded.Edit)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = Modifier.clickable {
|
modifier = Modifier.clickable {
|
||||||
|
|||||||
@ -38,7 +38,7 @@ dependencies {
|
|||||||
implementation(libs.bundles.kotlin)
|
implementation(libs.bundles.kotlin)
|
||||||
implementation(libs.androidx.core)
|
implementation(libs.androidx.core)
|
||||||
implementation(libs.androidx.appcompat)
|
implementation(libs.androidx.appcompat)
|
||||||
|
implementation(libs.androidx.compose.materialicons)
|
||||||
implementation(libs.bundles.androidx.lifecycle)
|
implementation(libs.bundles.androidx.lifecycle)
|
||||||
|
|
||||||
implementation(libs.koin.android)
|
implementation(libs.koin.android)
|
||||||
|
|||||||
@ -2,26 +2,36 @@ package de.mm20.launcher2.badges
|
|||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.util.Log
|
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 {
|
interface Badge {
|
||||||
val number: Int?
|
val number: Int?
|
||||||
val progress: Float?
|
val progress: Float?
|
||||||
val iconRes: Int?
|
val icon: BadgeIcon?
|
||||||
val icon: Drawable?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Badge(
|
fun Badge(
|
||||||
number: Int? = null,
|
number: Int? = null,
|
||||||
progress: Float? = null,
|
progress: Float? = null,
|
||||||
iconRes: Int? = null,
|
icon: BadgeIcon? = null
|
||||||
icon: Drawable? = null
|
): Badge = MutableBadge(number, progress, icon)
|
||||||
): Badge = MutableBadge(number, progress, iconRes, icon)
|
|
||||||
|
|
||||||
internal data class MutableBadge(
|
internal data class MutableBadge(
|
||||||
override var number: Int? = null,
|
override var number: Int? = null,
|
||||||
override var progress: Float? = null,
|
override var progress: Float? = null,
|
||||||
override var iconRes: Int? = null,
|
override var icon: BadgeIcon? = null
|
||||||
override var icon: Drawable? = null
|
|
||||||
): Badge
|
): Badge
|
||||||
|
|
||||||
fun Collection<Badge>.combine(): Badge? {
|
fun Collection<Badge>.combine(): Badge? {
|
||||||
@ -30,7 +40,6 @@ fun Collection<Badge>.combine(): Badge? {
|
|||||||
var progresses = 0
|
var progresses = 0
|
||||||
forEach {
|
forEach {
|
||||||
if (it.icon != null && badge.icon == null) badge.icon = it.icon
|
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 ->
|
it.number?.let { a ->
|
||||||
badge.number?.let { b -> badge.number = a + b } ?: run {
|
badge.number?.let { b -> badge.number = a + b } ?: run {
|
||||||
badge.number = a
|
badge.number = a
|
||||||
|
|||||||
@ -47,7 +47,7 @@ internal class BadgeServiceImpl(
|
|||||||
providers += NotificationBadgeProvider()
|
providers += NotificationBadgeProvider()
|
||||||
}
|
}
|
||||||
if (it.cloudFiles) {
|
if (it.cloudFiles) {
|
||||||
providers += CloudBadgeProvider()
|
providers += CloudBadgeProvider(context)
|
||||||
}
|
}
|
||||||
if (it.shortcuts) {
|
if (it.shortcuts) {
|
||||||
providers += AppShortcutBadgeProvider(context)
|
providers += AppShortcutBadgeProvider(context)
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package de.mm20.launcher2.badges.providers
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import de.mm20.launcher2.badges.Badge
|
import de.mm20.launcher2.badges.Badge
|
||||||
|
import de.mm20.launcher2.badges.BadgeIcon
|
||||||
import de.mm20.launcher2.badges.MutableBadge
|
import de.mm20.launcher2.badges.MutableBadge
|
||||||
import de.mm20.launcher2.graphics.BadgeDrawable
|
import de.mm20.launcher2.graphics.BadgeDrawable
|
||||||
import de.mm20.launcher2.search.AppShortcut
|
import de.mm20.launcher2.search.AppShortcut
|
||||||
@ -28,7 +29,7 @@ class AppShortcutBadgeProvider(
|
|||||||
} catch (e: PackageManager.NameNotFoundException) {
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
return@withContext
|
return@withContext
|
||||||
}
|
}
|
||||||
val badge = MutableBadge(icon = BadgeDrawable(context, icon))
|
val badge = MutableBadge(icon = BadgeIcon(BadgeDrawable(context, icon)))
|
||||||
send(badge)
|
send(badge)
|
||||||
}
|
}
|
||||||
} else if (packageName != null) {
|
} else if (packageName != null) {
|
||||||
@ -40,7 +41,7 @@ class AppShortcutBadgeProvider(
|
|||||||
} catch (e: PackageManager.NameNotFoundException) {
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
return@withContext
|
return@withContext
|
||||||
}
|
}
|
||||||
val badge = MutableBadge(icon = BadgeDrawable(context, icon))
|
val badge = MutableBadge(icon = BadgeIcon(BadgeDrawable(context, icon)))
|
||||||
send(badge)
|
send(badge)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
package de.mm20.launcher2.badges.providers
|
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.Badge
|
||||||
|
import de.mm20.launcher2.badges.BadgeIcon
|
||||||
import de.mm20.launcher2.badges.MutableBadge
|
import de.mm20.launcher2.badges.MutableBadge
|
||||||
import de.mm20.launcher2.search.File
|
import de.mm20.launcher2.search.File
|
||||||
import de.mm20.launcher2.search.Searchable
|
import de.mm20.launcher2.search.Searchable
|
||||||
@ -8,12 +11,14 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
|
||||||
class CloudBadgeProvider: BadgeProvider {
|
class CloudBadgeProvider(
|
||||||
|
private val context: Context
|
||||||
|
): BadgeProvider {
|
||||||
override fun getBadge(searchable: Searchable): Flow<Badge?> {
|
override fun getBadge(searchable: Searchable): Flow<Badge?> {
|
||||||
if (searchable is File) {
|
if (searchable is File) {
|
||||||
val iconResId = searchable.providerIconRes
|
val iconResId = searchable.providerIconRes
|
||||||
if (iconResId != null) {
|
if (iconResId != null) {
|
||||||
return flowOf(MutableBadge(iconRes = iconResId))
|
return flowOf(MutableBadge(icon = BadgeIcon(context.getDrawable(iconResId)!!)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return flowOf(null)
|
return flowOf(null)
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
package de.mm20.launcher2.badges.providers
|
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.Badge
|
||||||
|
import de.mm20.launcher2.badges.BadgeIcon
|
||||||
import de.mm20.launcher2.badges.R
|
import de.mm20.launcher2.badges.R
|
||||||
import de.mm20.launcher2.search.SavableSearchable
|
import de.mm20.launcher2.search.SavableSearchable
|
||||||
import de.mm20.launcher2.search.Searchable
|
import de.mm20.launcher2.search.Searchable
|
||||||
@ -33,7 +37,7 @@ class HiddenItemBadgeProvider(
|
|||||||
return hiddenItemKeys.map { keys ->
|
return hiddenItemKeys.map { keys ->
|
||||||
if (searchable.key in keys) {
|
if (searchable.key in keys) {
|
||||||
Badge(
|
Badge(
|
||||||
iconRes = R.drawable.ic_badge_hidden
|
icon = BadgeIcon(Icons.Rounded.VisibilityOff)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package de.mm20.launcher2.badges.providers
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import de.mm20.launcher2.badges.Badge
|
import de.mm20.launcher2.badges.Badge
|
||||||
|
import de.mm20.launcher2.badges.BadgeIcon
|
||||||
import de.mm20.launcher2.badges.MutableBadge
|
import de.mm20.launcher2.badges.MutableBadge
|
||||||
import de.mm20.launcher2.search.SavableSearchable
|
import de.mm20.launcher2.search.SavableSearchable
|
||||||
import de.mm20.launcher2.search.Searchable
|
import de.mm20.launcher2.search.Searchable
|
||||||
@ -16,7 +17,7 @@ class PluginBadgeProvider(private val context: Context): BadgeProvider {
|
|||||||
emit(null)
|
emit(null)
|
||||||
val icon = searchable.getProviderIcon(context)
|
val icon = searchable.getProviderIcon(context)
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
emit(MutableBadge(icon = icon))
|
emit(MutableBadge(icon = BadgeIcon(icon)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
package de.mm20.launcher2.badges.providers
|
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.Badge
|
||||||
|
import de.mm20.launcher2.badges.BadgeIcon
|
||||||
import de.mm20.launcher2.badges.MutableBadge
|
import de.mm20.launcher2.badges.MutableBadge
|
||||||
import de.mm20.launcher2.badges.R
|
import de.mm20.launcher2.badges.R
|
||||||
import de.mm20.launcher2.search.Application
|
import de.mm20.launcher2.search.Application
|
||||||
@ -14,7 +17,7 @@ class SuspendedAppsBadgeProvider : BadgeProvider, KoinComponent {
|
|||||||
|
|
||||||
override fun getBadge(searchable: Searchable): Flow<Badge?> {
|
override fun getBadge(searchable: Searchable): Flow<Badge?> {
|
||||||
return if (searchable is Application && searchable.isSuspended) {
|
return if (searchable is Application && searchable.isSuspended) {
|
||||||
flowOf(MutableBadge(iconRes = R.drawable.ic_badge_suspended))
|
flowOf(MutableBadge(icon = BadgeIcon(Icons.Rounded.HourglassBottom)))
|
||||||
} else {
|
} else {
|
||||||
flowOf(null)
|
flowOf(null)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
package de.mm20.launcher2.badges.providers
|
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.Badge
|
||||||
|
import de.mm20.launcher2.badges.BadgeIcon
|
||||||
import de.mm20.launcher2.badges.MutableBadge
|
import de.mm20.launcher2.badges.MutableBadge
|
||||||
import de.mm20.launcher2.badges.R
|
import de.mm20.launcher2.badges.R
|
||||||
import de.mm20.launcher2.search.AppProfile
|
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) {
|
if (searchable is Application && searchable.profile == AppProfile.Work || searchable is AppShortcut && searchable.profile == AppProfile.Work) {
|
||||||
emit(
|
emit(
|
||||||
MutableBadge(
|
MutableBadge(
|
||||||
iconRes = R.drawable.ic_badge_workprofile
|
icon = BadgeIcon(Icons.Rounded.Work)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user