Add support for native themed Google clock icon
This commit is contained in:
parent
23252726b0
commit
993b7f39fc
@ -109,7 +109,7 @@ class IconRepository(
|
||||
if (settings.themedIcons) {
|
||||
providers.add(ThemedIconProvider(iconPackManager))
|
||||
}
|
||||
providers.add(GoogleClockIconProvider(context))
|
||||
providers.add(GoogleClockIconProvider(context, settings.themedIcons))
|
||||
providers.add(CalendarIconProvider(context, settings.themedIcons))
|
||||
if (!isAtLeastApiLevel(33)) {
|
||||
providers.add(CompatIconProvider(context, settings.themedIcons))
|
||||
|
||||
@ -4,15 +4,21 @@ import android.content.res.Resources
|
||||
import android.content.res.XmlResourceParser
|
||||
import android.graphics.drawable.AdaptiveIconDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import android.graphics.drawable.RotateDrawable
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.util.Xml
|
||||
import android.view.InflateException
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||
import de.mm20.launcher2.icons.ClockLayer
|
||||
import de.mm20.launcher2.icons.ClockSublayer
|
||||
import de.mm20.launcher2.icons.ClockSublayerRole
|
||||
import de.mm20.launcher2.icons.ColorLayer
|
||||
import de.mm20.launcher2.icons.StaticIconLayer
|
||||
import de.mm20.launcher2.icons.StaticLauncherIcon
|
||||
import de.mm20.launcher2.icons.TintedClockLayer
|
||||
import de.mm20.launcher2.icons.TintedIconLayer
|
||||
import de.mm20.launcher2.ktx.isAtLeastApiLevel
|
||||
import de.mm20.launcher2.ktx.skipToNextTag
|
||||
@ -36,6 +42,19 @@ data class AdaptiveIconDrawableCompat(
|
||||
}
|
||||
|
||||
fun from(resources: Resources, resId: Int): AdaptiveIconDrawableCompat? {
|
||||
if (isAtLeastApiLevel(33)) {
|
||||
return try {
|
||||
val drawable = ResourcesCompat.getDrawable(resources, resId, null)
|
||||
if (drawable is AdaptiveIconDrawable) {
|
||||
from(drawable)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} catch (e: Resources.NotFoundException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
var xmlParser: XmlResourceParser? = null
|
||||
|
||||
try {
|
||||
@ -126,7 +145,60 @@ data class AdaptiveIconDrawableCompat(
|
||||
|
||||
fun AdaptiveIconDrawableCompat.toLauncherIcon(
|
||||
themed: Boolean = false,
|
||||
clock: ClockIconConfig? = null,
|
||||
): StaticLauncherIcon {
|
||||
val clockForeground = (if (themed) monochrome else foreground) as? LayerDrawable
|
||||
if (clock != null && clockForeground != null) {
|
||||
val clockLayers = (0 until clockForeground.numberOfLayers).map {
|
||||
val drw = clockForeground.getDrawable(it)
|
||||
if (drw is RotateDrawable) {
|
||||
drw.level = when (it) {
|
||||
clock.hourLayer -> {
|
||||
(12 - clock.defaultHour) * 60
|
||||
}
|
||||
|
||||
clock.minuteLayer -> {
|
||||
(60 - clock.defaultMinute)
|
||||
}
|
||||
|
||||
clock.secondLayer -> {
|
||||
(60 - clock.defaultSecond) * 10
|
||||
}
|
||||
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
ClockSublayer(
|
||||
drawable = drw,
|
||||
role = when (it) {
|
||||
clock.hourLayer -> ClockSublayerRole.Hour
|
||||
clock.minuteLayer -> ClockSublayerRole.Minute
|
||||
clock.secondLayer -> ClockSublayerRole.Second
|
||||
else -> ClockSublayerRole.Static
|
||||
}
|
||||
)
|
||||
}
|
||||
if (themed) {
|
||||
return StaticLauncherIcon(
|
||||
foregroundLayer = TintedClockLayer(
|
||||
sublayers = clockLayers,
|
||||
scale = 1f,
|
||||
),
|
||||
backgroundLayer = ColorLayer(),
|
||||
)
|
||||
}
|
||||
return StaticLauncherIcon(
|
||||
foregroundLayer = ClockLayer(
|
||||
sublayers = clockLayers,
|
||||
scale = 1.5f,
|
||||
),
|
||||
backgroundLayer = StaticIconLayer(
|
||||
icon = this.background,
|
||||
scale = 1.5f,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (themed && this.monochrome != null) {
|
||||
return StaticLauncherIcon(
|
||||
foregroundLayer = TintedIconLayer(
|
||||
@ -147,4 +219,13 @@ fun AdaptiveIconDrawableCompat.toLauncherIcon(
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class ClockIconConfig(
|
||||
val hourLayer: Int,
|
||||
val minuteLayer: Int,
|
||||
val secondLayer: Int,
|
||||
val defaultHour: Int,
|
||||
val defaultMinute: Int,
|
||||
val defaultSecond: Int,
|
||||
)
|
||||
@ -8,10 +8,13 @@ import android.graphics.drawable.LayerDrawable
|
||||
import android.graphics.drawable.RotateDrawable
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import de.mm20.launcher2.icons.*
|
||||
import de.mm20.launcher2.icons.compat.AdaptiveIconDrawableCompat
|
||||
import de.mm20.launcher2.icons.compat.ClockIconConfig
|
||||
import de.mm20.launcher2.icons.compat.toLauncherIcon
|
||||
import de.mm20.launcher2.search.SavableSearchable
|
||||
import de.mm20.launcher2.search.data.LauncherApp
|
||||
|
||||
class GoogleClockIconProvider(val context: Context) : IconProvider {
|
||||
class GoogleClockIconProvider(val context: Context, private val themed: Boolean) : IconProvider {
|
||||
override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? {
|
||||
if (searchable !is LauncherApp) return null
|
||||
if (searchable.`package` != "com.google.android.deskclock") return null
|
||||
@ -24,22 +27,15 @@ class GoogleClockIconProvider(val context: Context) : IconProvider {
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
return null
|
||||
}
|
||||
val drawable =
|
||||
val drawableId =
|
||||
appInfo.metaData.getInt("com.android.launcher3.LEVEL_PER_TICK_ICON_ROUND")
|
||||
val resources = pm.getResourcesForApplication(appInfo)
|
||||
val baseIcon = try {
|
||||
ResourcesCompat.getDrawable(resources, drawable, null) as? AdaptiveIconDrawable
|
||||
?: return null
|
||||
} catch (e: Resources.NotFoundException) {
|
||||
val resources = try {
|
||||
pm.getResourcesForApplication(appInfo)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
return null
|
||||
}
|
||||
val foreground = baseIcon.foreground as? LayerDrawable ?: return null
|
||||
val hourLayer =
|
||||
appInfo.metaData.getInt("com.android.launcher3.HOUR_LAYER_INDEX")
|
||||
val minuteLayer =
|
||||
appInfo.metaData.getInt("com.android.launcher3.MINUTE_LAYER_INDEX")
|
||||
val secondLayer =
|
||||
appInfo.metaData.getInt("com.android.launcher3.SECOND_LAYER_INDEX")
|
||||
|
||||
val icon = AdaptiveIconDrawableCompat.from(resources, drawableId) ?: return null
|
||||
|
||||
val defaultHour =
|
||||
appInfo.metaData.getInt("com.android.launcher3.DEFAULT_HOUR")
|
||||
@ -48,40 +44,37 @@ class GoogleClockIconProvider(val context: Context) : IconProvider {
|
||||
val defaultSecond =
|
||||
appInfo.metaData.getInt("com.android.launcher3.DEFAULT_SECOND")
|
||||
|
||||
return StaticLauncherIcon(
|
||||
foregroundLayer = ClockLayer(
|
||||
sublayers = (0 until foreground.numberOfLayers).map {
|
||||
val drw = foreground.getDrawable(it)
|
||||
if (drw is RotateDrawable) {
|
||||
drw.level = when (it) {
|
||||
hourLayer -> {
|
||||
(12 - defaultHour) * 60
|
||||
}
|
||||
minuteLayer -> {
|
||||
(60 - defaultMinute)
|
||||
}
|
||||
secondLayer -> {
|
||||
(60 - defaultSecond) * 10
|
||||
}
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
ClockSublayer(
|
||||
drawable = drw,
|
||||
role = when (it) {
|
||||
hourLayer -> ClockSublayerRole.Hour
|
||||
minuteLayer -> ClockSublayerRole.Minute
|
||||
secondLayer -> ClockSublayerRole.Second
|
||||
else -> ClockSublayerRole.Static
|
||||
}
|
||||
)
|
||||
},
|
||||
scale = 1.5f,
|
||||
),
|
||||
backgroundLayer = StaticIconLayer(
|
||||
icon = baseIcon.background,
|
||||
scale = 1.5f,
|
||||
// Workaround for Google Clock themed icon because it is weird and I don't understand
|
||||
// how to get the correct layers from the drawable without hardcoding them here.
|
||||
val clockConfig = if (themed && searchable.`package` == "com.google.android.deskclock") {
|
||||
ClockIconConfig(
|
||||
hourLayer = 0,
|
||||
minuteLayer = 1,
|
||||
secondLayer = -1,
|
||||
defaultHour = defaultHour,
|
||||
defaultMinute = defaultMinute,
|
||||
defaultSecond = defaultSecond
|
||||
)
|
||||
} else {
|
||||
val hourLayer =
|
||||
appInfo.metaData.getInt("com.android.launcher3.HOUR_LAYER_INDEX", -1)
|
||||
val minuteLayer =
|
||||
appInfo.metaData.getInt("com.android.launcher3.MINUTE_LAYER_INDEX", -1)
|
||||
val secondLayer =
|
||||
appInfo.metaData.getInt("com.android.launcher3.SECOND_LAYER_INDEX", -1)
|
||||
ClockIconConfig(
|
||||
hourLayer = hourLayer,
|
||||
minuteLayer = minuteLayer,
|
||||
secondLayer = secondLayer,
|
||||
defaultHour = defaultHour,
|
||||
defaultMinute = defaultMinute,
|
||||
defaultSecond = defaultSecond
|
||||
)
|
||||
}
|
||||
|
||||
return icon.toLauncherIcon(
|
||||
themed = themed,
|
||||
clock = clockConfig
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user