Skip to content

Commit ee33d75

Browse files
committed
Remove friendly name usage in auto screens
1 parent 45808fe commit ee33d75

8 files changed

Lines changed: 142 additions & 236 deletions

File tree

app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/DomainChecks.kt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package io.homeassistant.companion.android.util.vehicle
22

33
import io.homeassistant.companion.android.common.R
44
import io.homeassistant.companion.android.common.data.integration.Entity
5-
import io.homeassistant.companion.android.common.data.integration.supportsAlarmControlPanelArmAway
5+
import io.homeassistant.companion.android.common.data.integration.display.EntityDisplayItem
66

77
val SUPPORTED_DOMAINS_WITH_STRING = mapOf(
88
"alarm_control_panel" to R.string.alarm_control_panels,
@@ -46,8 +46,4 @@ fun canNavigate(entity: Entity): Boolean {
4646
)
4747
}
4848

49-
fun alarmHasNoCode(entity: Entity): Boolean {
50-
return entity.domain == "alarm_control_panel" &&
51-
entity.attributes["code_format"] as? String == null &&
52-
entity.supportsAlarmControlPanelArmAway()
53-
}
49+
fun canNavigate(entity: EntityDisplayItem): Boolean = entity.domain in MAP_DOMAINS && entity.coordinates != null

app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/TemplateComponents.kt

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,11 @@ import com.mikepenz.iconics.utils.toAndroidIconCompat
1919
import io.homeassistant.companion.android.common.R
2020
import io.homeassistant.companion.android.common.data.integration.Entity
2121
import io.homeassistant.companion.android.common.data.integration.IntegrationRepository
22+
import io.homeassistant.companion.android.common.data.integration.display.EntityDisplayState
2223
import io.homeassistant.companion.android.common.data.integration.getIcon
2324
import io.homeassistant.companion.android.common.data.prefs.PrefsRepository
2425
import io.homeassistant.companion.android.common.data.servers.ServerManager
25-
import io.homeassistant.companion.android.common.data.websocket.impl.entities.EntityRegistryResponse
2626
import io.homeassistant.companion.android.common.util.capitalize
27-
import io.homeassistant.companion.android.util.RegistriesDataHandler
2827
import io.homeassistant.companion.android.vehicle.ChangeServerScreen
2928
import io.homeassistant.companion.android.vehicle.DomainListScreen
3029
import io.homeassistant.companion.android.vehicle.EntityGridVehicleScreen
@@ -93,8 +92,7 @@ fun getNavigationGridItem(
9392
carContext: CarContext,
9493
screenManager: ScreenManager,
9594
integrationRepositoryProvider: suspend () -> IntegrationRepository,
96-
allEntities: Flow<Map<String, Entity>>,
97-
entityRegistry: List<EntityRegistryResponse>?,
95+
entitiesState: Flow<EntityDisplayState>,
9896
): GridItem.Builder {
9997
return GridItem.Builder().apply {
10098
setTitle(carContext.getString(R.string.aa_navigation))
@@ -116,14 +114,9 @@ fun getNavigationGridItem(
116114
MapVehicleScreen(
117115
carContext,
118116
integrationRepositoryProvider,
119-
allEntities.map {
120-
it.values.filter { entity ->
121-
entity.domain in MAP_DOMAINS &&
122-
RegistriesDataHandler.getHiddenByForEntity(
123-
entity.entityId,
124-
entityRegistry,
125-
) == null
126-
}
117+
entitiesState.map { state ->
118+
(state as? EntityDisplayState.Loaded)?.entities.orEmpty()
119+
.filter { it.domain in MAP_DOMAINS && !it.isHidden }
127120
},
128121
),
129122
)
@@ -139,8 +132,7 @@ fun getDomainList(
139132
serverManager: ServerManager,
140133
serverId: StateFlow<Int>,
141134
prefsRepository: PrefsRepository,
142-
allEntities: Flow<Map<String, Entity>>,
143-
entityRegistry: List<EntityRegistryResponse>?,
135+
entitiesState: Flow<EntityDisplayState>,
144136
lifecycleScope: LifecycleCoroutineScope,
145137
): ItemList.Builder {
146138
val listBuilder = ItemList.Builder()
@@ -158,14 +150,9 @@ fun getDomainList(
158150
LocalDateTime.now(),
159151
).getIcon()
160152

161-
val entityList = allEntities.map {
162-
it.values.filter { entity ->
163-
entity.domain == domain &&
164-
RegistriesDataHandler.getHiddenByForEntity(
165-
entity.entityId,
166-
entityRegistry,
167-
) == null
168-
}
153+
val entityList = entitiesState.map { state ->
154+
(state as? EntityDisplayState.Loaded)?.entities.orEmpty()
155+
.filter { it.domain == domain && !it.isHidden }
169156
}
170157
var domainIsEmpty = false
171158
lifecycleScope.launch {
@@ -200,10 +187,9 @@ fun getDomainList(
200187
prefsRepository,
201188
{ serverManager.integrationRepository(serverId.value) },
202189
friendlyDomain,
203-
entityRegistry,
204190
domains,
205191
entityList,
206-
allEntities,
192+
entitiesState,
207193
),
208194
)
209195
}
@@ -223,9 +209,8 @@ fun getDomainsGridItem(
223209
screenManager: ScreenManager,
224210
serverManager: ServerManager,
225211
serverId: StateFlow<Int>,
226-
allEntities: Flow<Map<String, Entity>>,
212+
entitiesState: Flow<EntityDisplayState>,
227213
prefsRepository: PrefsRepository,
228-
entityRegistry: List<EntityRegistryResponse>?,
229214
): GridItem.Builder {
230215
return GridItem.Builder().apply {
231216
setTitle(carContext.getString(R.string.all_entities))
@@ -248,9 +233,8 @@ fun getDomainsGridItem(
248233
carContext,
249234
serverManager,
250235
serverId,
251-
allEntities,
236+
entitiesState,
252237
prefsRepository,
253-
entityRegistry,
254238
),
255239
)
256240
}

app/src/main/kotlin/io/homeassistant/companion/android/vehicle/DomainListScreen.kt

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ import androidx.car.app.model.Template
88
import androidx.lifecycle.lifecycleScope
99
import io.homeassistant.companion.android.BuildConfig
1010
import io.homeassistant.companion.android.common.R
11-
import io.homeassistant.companion.android.common.data.integration.Entity
11+
import io.homeassistant.companion.android.common.data.integration.display.EntityDisplayState
1212
import io.homeassistant.companion.android.common.data.prefs.PrefsRepository
1313
import io.homeassistant.companion.android.common.data.servers.ServerManager
14-
import io.homeassistant.companion.android.common.data.websocket.impl.entities.EntityRegistryResponse
1514
import io.homeassistant.companion.android.common.util.isAutomotive
1615
import io.homeassistant.companion.android.util.vehicle.SUPPORTED_DOMAINS
1716
import io.homeassistant.companion.android.util.vehicle.getDomainList
@@ -27,9 +26,8 @@ class DomainListScreen(
2726
carContext: CarContext,
2827
val serverManager: ServerManager,
2928
private val serverId: StateFlow<Int>,
30-
private val allEntities: Flow<Map<String, Entity>>,
29+
private val entitiesState: Flow<EntityDisplayState>,
3130
private val prefsRepository: PrefsRepository,
32-
private val entityRegistry: List<EntityRegistryResponse>?,
3331
) : BaseVehicleScreen(carContext) {
3432

3533
private val domains = mutableSetOf<String>()
@@ -41,8 +39,9 @@ class DomainListScreen(
4139

4240
init {
4341
lifecycleScope.launch {
44-
allEntities.collect { entities ->
45-
val newDomains = entities.values
42+
entitiesState.collect { state ->
43+
if (state !is EntityDisplayState.Loaded) return@collect
44+
val newDomains = state.entities
4645
.map { it.domain }
4746
.distinct()
4847
.filter { it in SUPPORTED_DOMAINS }
@@ -65,8 +64,7 @@ class DomainListScreen(
6564
serverManager,
6665
serverId,
6766
prefsRepository,
68-
allEntities,
69-
entityRegistry,
67+
entitiesState,
7068
lifecycleScope,
7169
)
7270

app/src/main/kotlin/io/homeassistant/companion/android/vehicle/EntityGridVehicleScreen.kt

Lines changed: 35 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,16 @@ import com.mikepenz.iconics.IconicsDrawable
2020
import com.mikepenz.iconics.utils.sizeDp
2121
import com.mikepenz.iconics.utils.toAndroidIconCompat
2222
import io.homeassistant.companion.android.common.R
23-
import io.homeassistant.companion.android.common.data.integration.Entity
2423
import io.homeassistant.companion.android.common.data.integration.EntityExt
2524
import io.homeassistant.companion.android.common.data.integration.IntegrationRepository
26-
import io.homeassistant.companion.android.common.data.integration.friendlyName
27-
import io.homeassistant.companion.android.common.data.integration.friendlyState
28-
import io.homeassistant.companion.android.common.data.integration.getIcon
29-
import io.homeassistant.companion.android.common.data.integration.isActive
30-
import io.homeassistant.companion.android.common.data.integration.isExecuting
31-
import io.homeassistant.companion.android.common.data.integration.onPressed
25+
import io.homeassistant.companion.android.common.data.integration.display.EntityDisplayItem
26+
import io.homeassistant.companion.android.common.data.integration.display.EntityDisplayState
27+
import io.homeassistant.companion.android.common.data.integration.onEntityPressed
3228
import io.homeassistant.companion.android.common.data.prefs.PrefsRepository
3329
import io.homeassistant.companion.android.common.data.servers.ServerManager
34-
import io.homeassistant.companion.android.common.data.websocket.impl.entities.EntityRegistryResponse
3530
import io.homeassistant.companion.android.util.vehicle.MAP_DOMAINS
3631
import io.homeassistant.companion.android.util.vehicle.NOT_ACTIONABLE_DOMAINS
3732
import io.homeassistant.companion.android.util.vehicle.SUPPORTED_DOMAINS
38-
import io.homeassistant.companion.android.util.vehicle.alarmHasNoCode
3933
import io.homeassistant.companion.android.util.vehicle.canNavigate
4034
import io.homeassistant.companion.android.util.vehicle.getDomainList
4135
import io.homeassistant.companion.android.util.vehicle.getDomainsGridItem
@@ -55,20 +49,15 @@ class EntityGridVehicleScreen(
5549
val prefsRepository: PrefsRepository,
5650
val integrationRepositoryProvider: suspend () -> IntegrationRepository,
5751
val title: String,
58-
private val entityRegistry: List<EntityRegistryResponse>?,
5952
private val domains: MutableSet<String>,
60-
private val entitiesFlow: Flow<List<Entity>>,
61-
private val allEntities: Flow<Map<String, Entity>>,
53+
private val entitiesFlow: Flow<List<EntityDisplayItem>>,
54+
private val entitiesState: Flow<EntityDisplayState>,
6255
) : Screen(carContext) {
6356

6457
private var loading = true
65-
var entities: List<Entity> = listOf()
58+
var entities: List<EntityDisplayItem> = listOf()
6659
private val isFavorites = title == carContext.getString(R.string.favorites)
6760

68-
// Index the registry by entity ID so each grid item can look up its options (such as the
69-
// sensor display precision) without scanning the whole registry on every render
70-
private val entityRegistryOptions = entityRegistry?.associate { it.entityId to it.options }
71-
7261
init {
7362
lifecycleScope.launch {
7463
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
@@ -92,7 +81,7 @@ class EntityGridVehicleScreen(
9281
* @param canSwitchServers If `true` and the function is called for favorites, the item limit is adjusted to keep
9382
* space for a 'Switch server' item
9483
*/
95-
fun getEntityGridItems(entities: List<Entity>, canSwitchServers: Boolean): ItemList.Builder {
84+
fun getEntityGridItems(entities: List<EntityDisplayItem>, canSwitchServers: Boolean): ItemList.Builder {
9685
val listBuilder = if (entities.isNotEmpty()) {
9786
createEntityGrid(entities, canSwitchServers)
9887
} else {
@@ -103,8 +92,7 @@ class EntityGridVehicleScreen(
10392
serverManager,
10493
serverId,
10594
prefsRepository,
106-
allEntities,
107-
entityRegistry,
95+
entitiesState,
10896
lifecycleScope,
10997
)
11098
}
@@ -114,8 +102,7 @@ class EntityGridVehicleScreen(
114102
carContext,
115103
screenManager,
116104
integrationRepositoryProvider,
117-
allEntities,
118-
entityRegistry,
105+
entitiesState,
119106
).build(),
120107
)
121108
if (domains.isNotEmpty()) {
@@ -125,9 +112,8 @@ class EntityGridVehicleScreen(
125112
screenManager,
126113
serverManager,
127114
serverId,
128-
allEntities,
115+
entitiesState,
129116
prefsRepository,
130-
entityRegistry,
131117
).build(),
132118
)
133119
}
@@ -149,50 +135,51 @@ class EntityGridVehicleScreen(
149135
}.build()
150136
}
151137

152-
private fun createEntityGrid(entities: List<Entity>, canSwitchServers: Boolean): ItemList.Builder {
138+
private fun createEntityGrid(entities: List<EntityDisplayItem>, canSwitchServers: Boolean): ItemList.Builder {
153139
val listBuilder = ItemList.Builder()
154140
val manager = carContext.getCarService(ConstraintManager::class.java)
155141
val gridLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID)
156142
val extraGrid = if (canSwitchServers) 3 else 2
157-
entities.forEachIndexed { index, entity ->
143+
entities.forEachIndexed { index, displayed ->
158144
if (index >= (gridLimit - if (isFavorites) extraGrid else 0)) {
159145
Timber.i("Grid limit ($gridLimit) reached, not adding more entities (${entities.size}) for $title ")
160146
return@forEachIndexed
161147
}
162-
val icon = entity.getIcon()
163148
val gridItem =
164149
GridItem.Builder()
165150
.setLoading(false)
166-
.setTitle(entity.friendlyName.ifEmpty { entity.entityId })
167-
.setText(entity.friendlyState(carContext, options = entityRegistryOptions?.get(entity.entityId)))
151+
.setTitle(displayed.name)
152+
.setText(displayed.state.resolve(carContext))
168153

169-
if (entity.isExecuting()) {
170-
gridItem.setLoading(entity.isExecuting())
154+
if (displayed.isExecuting) {
155+
gridItem.setLoading(displayed.isExecuting)
171156
} else {
172-
if (entity.domain !in NOT_ACTIONABLE_DOMAINS || canNavigate(entity) || alarmHasNoCode(entity)) {
157+
if (displayed.domain !in NOT_ACTIONABLE_DOMAINS ||
158+
canNavigate(displayed) ||
159+
displayed.alarm?.hasNoCode == true
160+
) {
173161
gridItem
174162
.setOnClickListener {
175-
Timber.i("${entity.entityId} clicked")
176-
when (entity.domain) {
163+
Timber.i("${displayed.entityId} clicked")
164+
when (displayed.domain) {
177165
in MAP_DOMAINS -> {
178-
val attrs = entity.attributes as? Map<*, *>
179-
if (attrs != null) {
180-
val lat = attrs["latitude"] as? Double
181-
val lon = attrs["longitude"] as? Double
182-
if (lat != null && lon != null) {
183-
val intent = Intent(
184-
CarContext.ACTION_NAVIGATE,
185-
"geo:$lat,$lon".toUri(),
186-
)
187-
carContext.startCarApp(intent)
188-
}
166+
displayed.coordinates?.let { coordinates ->
167+
val intent = Intent(
168+
CarContext.ACTION_NAVIGATE,
169+
"geo:${coordinates.latitude},${coordinates.longitude}".toUri(),
170+
)
171+
carContext.startCarApp(intent)
189172
}
190173
}
191174

192175
in SUPPORTED_DOMAINS -> {
193176
lifecycleScope.launch {
194177
try {
195-
entity.onPressed(integrationRepositoryProvider())
178+
onEntityPressed(
179+
entityId = displayed.entityId,
180+
currentState = displayed.rawState,
181+
integrationRepository = integrationRepositoryProvider(),
182+
)
196183
} catch (e: CancellationException) {
197184
throw e
198185
} catch (e: Exception) {
@@ -211,12 +198,12 @@ class EntityGridVehicleScreen(
211198
gridItem
212199
.setImage(
213200
CarIcon.Builder(
214-
IconicsDrawable(carContext, icon).apply {
201+
IconicsDrawable(carContext, displayed.icon).apply {
215202
sizeDp = 64
216203
}.toAndroidIconCompat(),
217204
)
218205
.setTint(
219-
if (entity.isActive() && entity.domain in EntityExt.STATE_COLORED_DOMAINS) {
206+
if (displayed.isActive && displayed.domain in EntityExt.STATE_COLORED_DOMAINS) {
220207
CarColor.createCustom(
221208
carContext.getColor(R.color.colorYellow),
222209
carContext.getColor(R.color.colorYellow),

0 commit comments

Comments
 (0)