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) {
|
if (settings.themedIcons) {
|
||||||
providers.add(ThemedIconProvider(iconPackManager))
|
providers.add(ThemedIconProvider(iconPackManager))
|
||||||
}
|
}
|
||||||
providers.add(GoogleClockIconProvider(context))
|
providers.add(GoogleClockIconProvider(context, settings.themedIcons))
|
||||||
providers.add(CalendarIconProvider(context, settings.themedIcons))
|
providers.add(CalendarIconProvider(context, settings.themedIcons))
|
||||||
if (!isAtLeastApiLevel(33)) {
|
if (!isAtLeastApiLevel(33)) {
|
||||||
providers.add(CompatIconProvider(context, settings.themedIcons))
|
providers.add(CompatIconProvider(context, settings.themedIcons))
|
||||||
|
|||||||
@ -4,15 +4,21 @@ import android.content.res.Resources
|
|||||||
import android.content.res.XmlResourceParser
|
import android.content.res.XmlResourceParser
|
||||||
import android.graphics.drawable.AdaptiveIconDrawable
|
import android.graphics.drawable.AdaptiveIconDrawable
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.graphics.drawable.LayerDrawable
|
||||||
|
import android.graphics.drawable.RotateDrawable
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.Xml
|
import android.util.Xml
|
||||||
import android.view.InflateException
|
import android.view.InflateException
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
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.ColorLayer
|
||||||
import de.mm20.launcher2.icons.StaticIconLayer
|
import de.mm20.launcher2.icons.StaticIconLayer
|
||||||
import de.mm20.launcher2.icons.StaticLauncherIcon
|
import de.mm20.launcher2.icons.StaticLauncherIcon
|
||||||
|
import de.mm20.launcher2.icons.TintedClockLayer
|
||||||
import de.mm20.launcher2.icons.TintedIconLayer
|
import de.mm20.launcher2.icons.TintedIconLayer
|
||||||
import de.mm20.launcher2.ktx.isAtLeastApiLevel
|
import de.mm20.launcher2.ktx.isAtLeastApiLevel
|
||||||
import de.mm20.launcher2.ktx.skipToNextTag
|
import de.mm20.launcher2.ktx.skipToNextTag
|
||||||
@ -36,6 +42,19 @@ data class AdaptiveIconDrawableCompat(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun from(resources: Resources, resId: Int): 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
|
var xmlParser: XmlResourceParser? = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -126,7 +145,60 @@ data class AdaptiveIconDrawableCompat(
|
|||||||
|
|
||||||
fun AdaptiveIconDrawableCompat.toLauncherIcon(
|
fun AdaptiveIconDrawableCompat.toLauncherIcon(
|
||||||
themed: Boolean = false,
|
themed: Boolean = false,
|
||||||
|
clock: ClockIconConfig? = null,
|
||||||
): StaticLauncherIcon {
|
): 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) {
|
if (themed && this.monochrome != null) {
|
||||||
return StaticLauncherIcon(
|
return StaticLauncherIcon(
|
||||||
foregroundLayer = TintedIconLayer(
|
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 android.graphics.drawable.RotateDrawable
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import de.mm20.launcher2.icons.*
|
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.SavableSearchable
|
||||||
import de.mm20.launcher2.search.data.LauncherApp
|
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? {
|
override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? {
|
||||||
if (searchable !is LauncherApp) return null
|
if (searchable !is LauncherApp) return null
|
||||||
if (searchable.`package` != "com.google.android.deskclock") 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) {
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val drawable =
|
val drawableId =
|
||||||
appInfo.metaData.getInt("com.android.launcher3.LEVEL_PER_TICK_ICON_ROUND")
|
appInfo.metaData.getInt("com.android.launcher3.LEVEL_PER_TICK_ICON_ROUND")
|
||||||
val resources = pm.getResourcesForApplication(appInfo)
|
val resources = try {
|
||||||
val baseIcon = try {
|
pm.getResourcesForApplication(appInfo)
|
||||||
ResourcesCompat.getDrawable(resources, drawable, null) as? AdaptiveIconDrawable
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
?: return null
|
|
||||||
} catch (e: Resources.NotFoundException) {
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val foreground = baseIcon.foreground as? LayerDrawable ?: return null
|
|
||||||
val hourLayer =
|
val icon = AdaptiveIconDrawableCompat.from(resources, drawableId) ?: return null
|
||||||
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 defaultHour =
|
val defaultHour =
|
||||||
appInfo.metaData.getInt("com.android.launcher3.DEFAULT_HOUR")
|
appInfo.metaData.getInt("com.android.launcher3.DEFAULT_HOUR")
|
||||||
@ -48,40 +44,37 @@ class GoogleClockIconProvider(val context: Context) : IconProvider {
|
|||||||
val defaultSecond =
|
val defaultSecond =
|
||||||
appInfo.metaData.getInt("com.android.launcher3.DEFAULT_SECOND")
|
appInfo.metaData.getInt("com.android.launcher3.DEFAULT_SECOND")
|
||||||
|
|
||||||
return StaticLauncherIcon(
|
// Workaround for Google Clock themed icon because it is weird and I don't understand
|
||||||
foregroundLayer = ClockLayer(
|
// how to get the correct layers from the drawable without hardcoding them here.
|
||||||
sublayers = (0 until foreground.numberOfLayers).map {
|
val clockConfig = if (themed && searchable.`package` == "com.google.android.deskclock") {
|
||||||
val drw = foreground.getDrawable(it)
|
ClockIconConfig(
|
||||||
if (drw is RotateDrawable) {
|
hourLayer = 0,
|
||||||
drw.level = when (it) {
|
minuteLayer = 1,
|
||||||
hourLayer -> {
|
secondLayer = -1,
|
||||||
(12 - defaultHour) * 60
|
defaultHour = defaultHour,
|
||||||
}
|
defaultMinute = defaultMinute,
|
||||||
minuteLayer -> {
|
defaultSecond = defaultSecond
|
||||||
(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,
|
|
||||||
)
|
)
|
||||||
|
} 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