From a111776e3940bdcdd5526a7c0e78d3ba1034bba5 Mon Sep 17 00:00:00 2001 From: Daniel Shokouhi Date: Mon, 31 Jul 2023 12:14:58 -0700 Subject: [PATCH] Allow binary sensors and sensors to be added to driving favorites (#3732) * Allow binary sensors and sensors to be added to driving favorites * Ensure sensors can still be navigated to * Review comments --- .../vehicle/ManageAndroidAutoViewModel.kt | 10 +--- .../vehicle/views/AndroidAutoFavoritesView.kt | 12 +---- .../android/util/vehicle/DomainChecks.kt | 44 +++++++++++++++ .../android/util/vehicle/GridItems.kt | 5 +- .../android/vehicle/DomainListScreen.kt | 3 +- .../vehicle/EntityGridVehicleScreen.kt | 54 ++++++++++++------- .../android/vehicle/MainVehicleScreen.kt | 21 +------- 7 files changed, 88 insertions(+), 61 deletions(-) create mode 100755 app/src/main/java/io/homeassistant/companion/android/util/vehicle/DomainChecks.kt diff --git a/app/src/main/java/io/homeassistant/companion/android/settings/vehicle/ManageAndroidAutoViewModel.kt b/app/src/main/java/io/homeassistant/companion/android/settings/vehicle/ManageAndroidAutoViewModel.kt index 30e80de6927..f2b798d3483 100755 --- a/app/src/main/java/io/homeassistant/companion/android/settings/vehicle/ManageAndroidAutoViewModel.kt +++ b/app/src/main/java/io/homeassistant/companion/android/settings/vehicle/ManageAndroidAutoViewModel.kt @@ -12,10 +12,9 @@ import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import io.homeassistant.companion.android.common.data.integration.Entity -import io.homeassistant.companion.android.common.data.integration.domain import io.homeassistant.companion.android.common.data.prefs.PrefsRepository import io.homeassistant.companion.android.common.data.servers.ServerManager -import io.homeassistant.companion.android.vehicle.MainVehicleScreen +import io.homeassistant.companion.android.util.vehicle.isVehicleDomain import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.launch @@ -46,12 +45,7 @@ class ManageAndroidAutoViewModel @Inject constructor( entities[it.id] = try { serverManager.integrationRepository(it.id).getEntities().orEmpty() .filter { - it.domain in MainVehicleScreen.SUPPORTED_DOMAINS || - ( - it.domain in MainVehicleScreen.MAP_DOMAINS && - ((it.attributes as? Map<*, *>)?.get("latitude") as? Double != null) && - ((it.attributes as? Map<*, *>)?.get("longitude") as? Double != null) - ) + isVehicleDomain(it) } } catch (e: Exception) { Log.e(TAG, "Couldn't load entities for server", e) diff --git a/app/src/main/java/io/homeassistant/companion/android/settings/vehicle/views/AndroidAutoFavoritesView.kt b/app/src/main/java/io/homeassistant/companion/android/settings/vehicle/views/AndroidAutoFavoritesView.kt index a2b430d434e..642b4ce3c1a 100755 --- a/app/src/main/java/io/homeassistant/companion/android/settings/vehicle/views/AndroidAutoFavoritesView.kt +++ b/app/src/main/java/io/homeassistant/companion/android/settings/vehicle/views/AndroidAutoFavoritesView.kt @@ -18,14 +18,13 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import io.homeassistant.companion.android.common.data.integration.Entity -import io.homeassistant.companion.android.common.data.integration.domain import io.homeassistant.companion.android.common.data.integration.friendlyName import io.homeassistant.companion.android.database.server.Server import io.homeassistant.companion.android.settings.vehicle.ManageAndroidAutoViewModel import io.homeassistant.companion.android.util.compose.FavoriteEntityRow import io.homeassistant.companion.android.util.compose.ServerExposedDropdownMenu import io.homeassistant.companion.android.util.compose.SingleEntityPicker -import io.homeassistant.companion.android.vehicle.MainVehicleScreen +import io.homeassistant.companion.android.util.vehicle.isVehicleDomain import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.burnoutcrew.reorderable.ReorderableItem @@ -55,14 +54,7 @@ fun AndroidAutoFavoritesSettings( androidAutoViewModel.sortedEntities .filter { !favoriteEntities.contains("$selectedServer-${it.entityId}") && - ( - it.domain in MainVehicleScreen.SUPPORTED_DOMAINS || - ( - it.domain in MainVehicleScreen.MAP_DOMAINS && - ((it.attributes as? Map<*, *>)?.get("latitude") as? Double != null) && - ((it.attributes as? Map<*, *>)?.get("longitude") as? Double != null) - ) - ) + isVehicleDomain(it) } .toList() } diff --git a/app/src/main/java/io/homeassistant/companion/android/util/vehicle/DomainChecks.kt b/app/src/main/java/io/homeassistant/companion/android/util/vehicle/DomainChecks.kt new file mode 100755 index 00000000000..945b12d3cba --- /dev/null +++ b/app/src/main/java/io/homeassistant/companion/android/util/vehicle/DomainChecks.kt @@ -0,0 +1,44 @@ +package io.homeassistant.companion.android.util.vehicle + +import io.homeassistant.companion.android.common.R +import io.homeassistant.companion.android.common.data.integration.Entity +import io.homeassistant.companion.android.common.data.integration.domain + +val SUPPORTED_DOMAINS_WITH_STRING = mapOf( + "button" to R.string.buttons, + "cover" to R.string.covers, + "input_boolean" to R.string.input_booleans, + "input_button" to R.string.input_buttons, + "light" to R.string.lights, + "lock" to R.string.locks, + "scene" to R.string.scenes, + "script" to R.string.scripts, + "switch" to R.string.switches +) +val SUPPORTED_DOMAINS = SUPPORTED_DOMAINS_WITH_STRING.keys + +val MAP_DOMAINS = listOf( + "device_tracker", + "person", + "sensor", + "zone" +) + +val NOT_ACTIONABLE_DOMAINS = listOf( + "binary_sensor", + "sensor" +) + +fun isVehicleDomain(entity: Entity<*>): Boolean { + return entity.domain in SUPPORTED_DOMAINS || + entity.domain in NOT_ACTIONABLE_DOMAINS || + canNavigate(entity) +} + +fun canNavigate(entity: Entity<*>): Boolean { + return ( + entity.domain in MAP_DOMAINS && + ((entity.attributes as? Map<*, *>)?.get("latitude") as? Double != null) && + ((entity.attributes as? Map<*, *>)?.get("longitude") as? Double != null) + ) +} diff --git a/app/src/main/java/io/homeassistant/companion/android/util/vehicle/GridItems.kt b/app/src/main/java/io/homeassistant/companion/android/util/vehicle/GridItems.kt index 5f6a3e4c1af..9a067f12967 100755 --- a/app/src/main/java/io/homeassistant/companion/android/util/vehicle/GridItems.kt +++ b/app/src/main/java/io/homeassistant/companion/android/util/vehicle/GridItems.kt @@ -24,7 +24,6 @@ import io.homeassistant.companion.android.common.util.capitalize import io.homeassistant.companion.android.vehicle.ChangeServerScreen import io.homeassistant.companion.android.vehicle.DomainListScreen import io.homeassistant.companion.android.vehicle.EntityGridVehicleScreen -import io.homeassistant.companion.android.vehicle.MainVehicleScreen import io.homeassistant.companion.android.vehicle.MapVehicleScreen import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow @@ -99,7 +98,7 @@ fun getNavigationGridItem( MapVehicleScreen( carContext, integrationRepository, - allEntities.map { it.values.filter { entity -> entity.domain in MainVehicleScreen.MAP_DOMAINS } } + allEntities.map { it.values.filter { entity -> entity.domain in MAP_DOMAINS } } ) ) } @@ -119,7 +118,7 @@ fun getDomainList( val listBuilder = ItemList.Builder() domains.forEach { domain -> val friendlyDomain = - MainVehicleScreen.SUPPORTED_DOMAINS_WITH_STRING[domain]?.let { carContext.getString(it) } + SUPPORTED_DOMAINS_WITH_STRING[domain]?.let { carContext.getString(it) } ?: domain.split("_").joinToString(" ") { word -> word.capitalize(Locale.getDefault()) } diff --git a/app/src/main/java/io/homeassistant/companion/android/vehicle/DomainListScreen.kt b/app/src/main/java/io/homeassistant/companion/android/vehicle/DomainListScreen.kt index acacfdc91f8..66408072037 100755 --- a/app/src/main/java/io/homeassistant/companion/android/vehicle/DomainListScreen.kt +++ b/app/src/main/java/io/homeassistant/companion/android/vehicle/DomainListScreen.kt @@ -15,6 +15,7 @@ import io.homeassistant.companion.android.common.data.integration.IntegrationRep import io.homeassistant.companion.android.common.data.integration.domain import io.homeassistant.companion.android.common.data.prefs.PrefsRepository import io.homeassistant.companion.android.common.data.servers.ServerManager +import io.homeassistant.companion.android.util.vehicle.SUPPORTED_DOMAINS import io.homeassistant.companion.android.util.vehicle.getDomainList import io.homeassistant.companion.android.util.vehicle.nativeModeActionStrip import kotlinx.coroutines.flow.Flow @@ -47,7 +48,7 @@ class DomainListScreen( val newDomains = entities.values .map { it.domain } .distinct() - .filter { it in MainVehicleScreen.SUPPORTED_DOMAINS } + .filter { it in SUPPORTED_DOMAINS } .toSet() if (newDomains.size != domains.size || newDomains != domains) { domains.clear() diff --git a/app/src/main/java/io/homeassistant/companion/android/vehicle/EntityGridVehicleScreen.kt b/app/src/main/java/io/homeassistant/companion/android/vehicle/EntityGridVehicleScreen.kt index 0cd8da088de..fa2e51dad55 100644 --- a/app/src/main/java/io/homeassistant/companion/android/vehicle/EntityGridVehicleScreen.kt +++ b/app/src/main/java/io/homeassistant/companion/android/vehicle/EntityGridVehicleScreen.kt @@ -33,6 +33,10 @@ import io.homeassistant.companion.android.common.data.integration.isExecuting import io.homeassistant.companion.android.common.data.integration.onPressed import io.homeassistant.companion.android.common.data.prefs.PrefsRepository import io.homeassistant.companion.android.common.data.servers.ServerManager +import io.homeassistant.companion.android.util.vehicle.MAP_DOMAINS +import io.homeassistant.companion.android.util.vehicle.NOT_ACTIONABLE_DOMAINS +import io.homeassistant.companion.android.util.vehicle.SUPPORTED_DOMAINS +import io.homeassistant.companion.android.util.vehicle.canNavigate import io.homeassistant.companion.android.util.vehicle.getChangeServerGridItem import io.homeassistant.companion.android.util.vehicle.getDomainList import io.homeassistant.companion.android.util.vehicle.getDomainsGridItem @@ -160,28 +164,40 @@ class EntityGridVehicleScreen( if (entity.isExecuting()) { gridItem.setLoading(entity.isExecuting()) } else { - gridItem - .setOnClickListener { - Log.i(TAG, "${entity.entityId} clicked") - if (entity.domain in MainVehicleScreen.MAP_DOMAINS) { - val attrs = entity.attributes as? Map<*, *> - if (attrs != null) { - val lat = attrs["latitude"] as? Double - val lon = attrs["longitude"] as? Double - if (lat != null && lon != null) { - val intent = Intent( - CarContext.ACTION_NAVIGATE, - Uri.parse("geo:$lat,$lon") - ) - carContext.startCarApp(intent) + if (entity.domain !in NOT_ACTIONABLE_DOMAINS || canNavigate(entity)) { + gridItem + .setOnClickListener { + Log.i(TAG, "${entity.entityId} clicked") + when (entity.domain) { + in MAP_DOMAINS -> { + val attrs = entity.attributes as? Map<*, *> + if (attrs != null) { + val lat = attrs["latitude"] as? Double + val lon = attrs["longitude"] as? Double + if (lat != null && lon != null) { + val intent = Intent( + CarContext.ACTION_NAVIGATE, + Uri.parse("geo:$lat,$lon") + ) + carContext.startCarApp(intent) + } + } + } + + in SUPPORTED_DOMAINS -> { + lifecycleScope.launch { + entity.onPressed(integrationRepository) + } + } + + else -> { + // No op } - } - } else { - lifecycleScope.launch { - entity.onPressed(integrationRepository) } } - } + } + + gridItem .setImage( CarIcon.Builder( IconicsDrawable(carContext, icon).apply { diff --git a/app/src/main/java/io/homeassistant/companion/android/vehicle/MainVehicleScreen.kt b/app/src/main/java/io/homeassistant/companion/android/vehicle/MainVehicleScreen.kt index 4d5dc3728ba..fe6ebe12ab7 100644 --- a/app/src/main/java/io/homeassistant/companion/android/vehicle/MainVehicleScreen.kt +++ b/app/src/main/java/io/homeassistant/companion/android/vehicle/MainVehicleScreen.kt @@ -18,6 +18,7 @@ import io.homeassistant.companion.android.common.data.integration.domain import io.homeassistant.companion.android.common.data.prefs.PrefsRepository import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.sensors.SensorReceiver +import io.homeassistant.companion.android.util.vehicle.SUPPORTED_DOMAINS import io.homeassistant.companion.android.util.vehicle.getChangeServerGridItem import io.homeassistant.companion.android.util.vehicle.getDomainList import io.homeassistant.companion.android.util.vehicle.getNavigationGridItem @@ -42,26 +43,6 @@ class MainVehicleScreen( companion object { private const val TAG = "MainVehicleScreen" - - val SUPPORTED_DOMAINS_WITH_STRING = mapOf( - "button" to commonR.string.buttons, - "cover" to commonR.string.covers, - "input_boolean" to commonR.string.input_booleans, - "input_button" to commonR.string.input_buttons, - "light" to commonR.string.lights, - "lock" to commonR.string.locks, - "scene" to commonR.string.scenes, - "script" to commonR.string.scripts, - "switch" to commonR.string.switches - ) - val SUPPORTED_DOMAINS = SUPPORTED_DOMAINS_WITH_STRING.keys - - val MAP_DOMAINS = listOf( - "device_tracker", - "person", - "sensor", - "zone" - ) } private var favoriteEntities = flowOf>>()