Skip to content

Commit e06167f

Browse files
videclaude
andauthored
feat: add Überturbine 20" wheel for Model 3 and fix widget image parity (vide#185)
Add missing W32D (Überturbine 20" Gunpowder) wheel assets for Legacy Model 3 in all 7 colors. The API reports "UberTurbine20Gunpowder" which was not mapped, causing a fallback to the default 18" Aero wheels. Also fix the widget showing different wheels than the main app: the widget now reads the user's image override from SettingsDataStore (same source as the dashboard) so both always display the same car picture. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 7072f16 commit e06167f

12 files changed

Lines changed: 36 additions & 6 deletions

File tree

118 KB
Loading
107 KB
Loading
126 KB
Loading
125 KB
Loading
133 KB
Loading
133 KB
Loading
124 KB
Loading

app/src/main/java/com/matedroid/domain/model/CarImageResolver.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ object CarImageResolver {
131131
"aeroturbine19" to "W39B",
132132
"stiletto19" to "W39B",
133133
"sport19" to "W39B",
134+
"uberturbine20" to "W32D",
134135
"performance20" to "W32P",
135136
"19" to "W39B",
136137
"20" to "W32P",
@@ -522,6 +523,7 @@ object CarImageResolver {
522523
"W38B" to "18\" Aero",
523524
"W39B" to "19\" Sport",
524525
"W32P" to "20\" Performance",
526+
"W32D" to "20\" Überturbine",
525527
// Highland Model 3
526528
"W38A" to "18\" Photon",
527529
"W30P" to "20\" Performance",
@@ -548,7 +550,7 @@ object CarImageResolver {
548550

549551
// Available wheel codes per variant
550552
private val VARIANT_WHEELS = mapOf(
551-
"m3" to listOf("W38B", "W39B", "W32P"),
553+
"m3" to listOf("W38B", "W39B", "W32P", "W32D"),
552554
"m3h" to listOf("W38A"),
553555
"m3hp" to listOf("W30P"),
554556
"my" to listOf("WY18B", "WY19B", "WY20P"),

app/src/main/java/com/matedroid/widget/CarWidget.kt

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ class CarWidget : GlanceAppWidget() {
106106
val CHARGER_CURRENT_KEY = intPreferencesKey("charger_current") // -1 if null
107107
val AC_PHASES_KEY = intPreferencesKey("ac_phases") // -1 if null
108108
val SENTRY_EVENT_COUNT_KEY = intPreferencesKey("sentry_event_count") // 0 = none
109+
val IMAGE_OVERRIDE_VARIANT_KEY = stringPreferencesKey("image_override_variant")
110+
val IMAGE_OVERRIDE_WHEEL_KEY = stringPreferencesKey("image_override_wheel")
109111
}
110112

111113
override val stateDefinition: GlanceStateDefinition<*> = PreferencesGlanceStateDefinition
@@ -360,6 +362,13 @@ class CarWidget : GlanceAppWidget() {
360362
this[CHARGER_CURRENT_KEY] = data.chargerActualCurrent ?: -1
361363
this[AC_PHASES_KEY] = data.acPhases ?: -1
362364
this[SENTRY_EVENT_COUNT_KEY] = data.sentryEventCount
365+
if (data.imageOverride != null) {
366+
this[IMAGE_OVERRIDE_VARIANT_KEY] = data.imageOverride.variant
367+
this[IMAGE_OVERRIDE_WHEEL_KEY] = data.imageOverride.wheelCode
368+
} else {
369+
remove(IMAGE_OVERRIDE_VARIANT_KEY)
370+
remove(IMAGE_OVERRIDE_WHEEL_KEY)
371+
}
363372
}
364373
}
365374
update(context, glanceId)
@@ -391,6 +400,8 @@ class CarWidget : GlanceAppWidget() {
391400
val model = prefs[MODEL_KEY]
392401
val trimBadging = prefs[TRIM_BADGING_KEY]
393402
val wheelType = prefs[WHEEL_TYPE_KEY]
403+
val overrideVariant = prefs[IMAGE_OVERRIDE_VARIANT_KEY]
404+
val overrideWheel = prefs[IMAGE_OVERRIDE_WHEEL_KEY]
394405
val state = prefs[STATE_KEY]
395406
val isLocked = prefs[IS_LOCKED_KEY] ?: false
396407
val sentryMode = prefs[SENTRY_MODE_KEY] ?: false
@@ -428,7 +439,7 @@ class CarWidget : GlanceAppWidget() {
428439
// The larger scale factor ensures neither dimension is left uncovered;
429440
// overflow is clipped by the canvas bounds. The status bar, scrim and
430441
// progress bar are all drawn on top, so no space needs to be reserved.
431-
val carBitmap = loadCarBitmap(context, model, exteriorColor, wheelType, trimBadging)
442+
val carBitmap = loadCarBitmap(context, model, exteriorColor, wheelType, trimBadging, overrideVariant, overrideWheel)
432443
if (carBitmap != null) {
433444
val scaleByWidth = width.toFloat() / carBitmap.width
434445
val scaleByHeight = height.toFloat() / carBitmap.height
@@ -679,9 +690,16 @@ class CarWidget : GlanceAppWidget() {
679690
model: String?,
680691
exteriorColor: String?,
681692
wheelType: String?,
682-
trimBadging: String?
693+
trimBadging: String?,
694+
overrideVariant: String? = null,
695+
overrideWheel: String? = null
683696
): Bitmap? {
684-
val assetPath = CarImageResolver.getAssetPath(model, exteriorColor, wheelType, trimBadging)
697+
val colorCode = CarImageResolver.mapColor(exteriorColor)
698+
val assetPath = if (overrideVariant != null && overrideWheel != null) {
699+
CarImageResolver.getAssetPathForOverride(overrideVariant, colorCode, overrideWheel)
700+
} else {
701+
CarImageResolver.getAssetPath(model, exteriorColor, wheelType, trimBadging)
702+
}
685703
return try {
686704
context.assets.open(assetPath).use { BitmapFactory.decodeStream(it) }
687705
} catch (_: IOException) {

app/src/main/java/com/matedroid/widget/CarWidgetDisplayData.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.matedroid.widget
22

33
import com.matedroid.data.api.models.CarData
44
import com.matedroid.data.api.models.CarStatus
5+
import com.matedroid.data.local.CarImageOverride
56

67
/**
78
* Data class encapsulating all fields shown on the dashboard battery card.
@@ -40,6 +41,8 @@ data class CarWidgetDisplayData(
4041
val chargerActualCurrent: Int?,
4142
val acPhases: Int?,
4243
val sentryEventCount: Int = 0,
44+
// --- Image override (from car image picker) ---
45+
val imageOverride: CarImageOverride? = null,
4346
) {
4447
companion object {
4548
fun from(carData: CarData, status: CarStatus): CarWidgetDisplayData {

0 commit comments

Comments
 (0)