mirror of
https://github.com/home-assistant/android
synced 2024-10-15 12:32:54 +00:00
Add new option to only show favorites on home screen (#3276)
* Add new option to only show favorites on home screen * Review comments * Review comments
This commit is contained in:
parent
ef1f386ad0
commit
047abe93ba
|
@ -13,4 +13,6 @@ interface WearPrefsRepository {
|
|||
suspend fun setWearHapticFeedback(enabled: Boolean)
|
||||
suspend fun getWearToastConfirmation(): Boolean
|
||||
suspend fun setWearToastConfirmation(enabled: Boolean)
|
||||
suspend fun getWearFavoritesOnly(): Boolean
|
||||
suspend fun setWearFavoritesOnly(enabled: Boolean)
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ class WearPrefsRepositoryImpl @Inject constructor(
|
|||
private const val PREF_TILE_TEMPLATE_REFRESH_INTERVAL = "tile_template_refresh_interval"
|
||||
private const val PREF_WEAR_HAPTIC_FEEDBACK = "wear_haptic_feedback"
|
||||
private const val PREF_WEAR_TOAST_CONFIRMATION = "wear_toast_confirmation"
|
||||
private const val PREF_WEAR_FAVORITES_ONLY = "wear_favorites_only"
|
||||
}
|
||||
|
||||
init {
|
||||
|
@ -101,4 +102,12 @@ class WearPrefsRepositoryImpl @Inject constructor(
|
|||
override suspend fun setWearToastConfirmation(enabled: Boolean) {
|
||||
localStorage.putBoolean(PREF_WEAR_TOAST_CONFIRMATION, enabled)
|
||||
}
|
||||
|
||||
override suspend fun getWearFavoritesOnly(): Boolean {
|
||||
return localStorage.getBoolean(PREF_WEAR_FAVORITES_ONLY)
|
||||
}
|
||||
|
||||
override suspend fun setWearFavoritesOnly(enabled: Boolean) {
|
||||
localStorage.putBoolean(PREF_WEAR_FAVORITES_ONLY, enabled)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1015,4 +1015,5 @@
|
|||
<string name="assist">Assist</string>
|
||||
<string name="not_registered">Please launch the Home Assistant app and login before you can use the assist feature.</string>
|
||||
<string name="ha_assist">HA: Assist</string>
|
||||
<string name="only_favorites">Only Show Favorites</string>
|
||||
</resources>
|
||||
|
|
|
@ -57,9 +57,11 @@ class HomeActivity : ComponentActivity(), HomeView {
|
|||
entityUpdateJob = launch { mainViewModel.entityUpdates() }
|
||||
}
|
||||
}
|
||||
launch { mainViewModel.entityRegistryUpdates() }
|
||||
if (!mainViewModel.isFavoritesOnly) {
|
||||
launch { mainViewModel.areaUpdates() }
|
||||
launch { mainViewModel.deviceUpdates() }
|
||||
launch { mainViewModel.entityRegistryUpdates() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,4 +50,6 @@ interface HomePresenter {
|
|||
suspend fun setTemplateTileContent(content: String)
|
||||
suspend fun getTemplateTileRefreshInterval(): Int
|
||||
suspend fun setTemplateTileRefreshInterval(interval: Int)
|
||||
suspend fun getWearFavoritesOnly(): Boolean
|
||||
suspend fun setWearFavoritesOnly(enabled: Boolean)
|
||||
}
|
||||
|
|
|
@ -271,4 +271,12 @@ class HomePresenterImpl @Inject constructor(
|
|||
override suspend fun setTemplateTileRefreshInterval(interval: Int) {
|
||||
wearPrefsRepository.setTemplateTileRefreshInterval(interval)
|
||||
}
|
||||
|
||||
override suspend fun getWearFavoritesOnly(): Boolean {
|
||||
return wearPrefsRepository.getWearFavoritesOnly()
|
||||
}
|
||||
|
||||
override suspend fun setWearFavoritesOnly(enabled: Boolean) {
|
||||
wearPrefsRepository.setWearFavoritesOnly(enabled)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,11 @@ package io.homeassistant.companion.android.home
|
|||
import android.app.Application
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.snapshots.SnapshotStateList
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
|
@ -108,6 +110,8 @@ class MainViewModel @Inject constructor(
|
|||
private set
|
||||
var templateTileRefreshInterval = mutableStateOf(0)
|
||||
private set
|
||||
var isFavoritesOnly by mutableStateOf(false)
|
||||
private set
|
||||
|
||||
fun supportedDomains(): List<String> = HomePresenterImpl.supportedDomains
|
||||
|
||||
|
@ -129,6 +133,7 @@ class MainViewModel @Inject constructor(
|
|||
isShowShortcutTextEnabled.value = homePresenter.getShowShortcutText()
|
||||
templateTileContent.value = homePresenter.getTemplateTileContent()
|
||||
templateTileRefreshInterval.value = homePresenter.getTemplateTileRefreshInterval()
|
||||
isFavoritesOnly = homePresenter.getWearFavoritesOnly()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,11 +181,13 @@ class MainViewModel @Inject constructor(
|
|||
val getEntityRegistry = async { homePresenter.getEntityRegistry() }
|
||||
val getEntities = async { homePresenter.getEntities() }
|
||||
|
||||
if (!isFavoritesOnly) {
|
||||
areaRegistry = getAreaRegistry.await()?.also {
|
||||
areas.clear()
|
||||
areas.addAll(it)
|
||||
}
|
||||
deviceRegistry = getDeviceRegistry.await()
|
||||
}
|
||||
entityRegistry = getEntityRegistry.await()
|
||||
|
||||
_supportedEntities.value = getSupportedEntities()
|
||||
|
@ -189,6 +196,7 @@ class MainViewModel @Inject constructor(
|
|||
entities.clear()
|
||||
it.forEach { state -> updateEntityStates(state) }
|
||||
}
|
||||
if (!isFavoritesOnly)
|
||||
updateEntityDomains()
|
||||
}
|
||||
|
||||
|
@ -197,12 +205,13 @@ class MainViewModel @Inject constructor(
|
|||
return
|
||||
homePresenter.getEntityUpdates(supportedEntities.value)?.collect {
|
||||
updateEntityStates(it)
|
||||
if (!isFavoritesOnly)
|
||||
updateEntityDomains()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun areaUpdates() {
|
||||
if (!homePresenter.isConnected())
|
||||
if (!homePresenter.isConnected() || isFavoritesOnly)
|
||||
return
|
||||
homePresenter.getAreaRegistryUpdates()?.collect {
|
||||
areaRegistry = homePresenter.getAreaRegistry()
|
||||
|
@ -215,7 +224,7 @@ class MainViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
suspend fun deviceUpdates() {
|
||||
if (!homePresenter.isConnected())
|
||||
if (!homePresenter.isConnected() || isFavoritesOnly)
|
||||
return
|
||||
homePresenter.getDeviceRegistryUpdates()?.collect {
|
||||
deviceRegistry = homePresenter.getDeviceRegistry()
|
||||
|
@ -414,6 +423,13 @@ class MainViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun setWearFavoritesOnly(enabled: Boolean) {
|
||||
viewModelScope.launch {
|
||||
homePresenter.setWearFavoritesOnly(enabled)
|
||||
isFavoritesOnly = enabled
|
||||
}
|
||||
}
|
||||
|
||||
fun setTemplateTileRefreshInterval(interval: Int) {
|
||||
viewModelScope.launch {
|
||||
homePresenter.setTemplateTileRefreshInterval(interval)
|
||||
|
|
|
@ -59,7 +59,7 @@ fun LoadHomePage(
|
|||
},
|
||||
onRetryLoadEntitiesClicked = mainViewModel::loadEntities,
|
||||
onSettingsClicked = { swipeDismissableNavController.navigate(SCREEN_SETTINGS) },
|
||||
onTestClicked = { lists, order, filter ->
|
||||
onNavigationClicked = { lists, order, filter ->
|
||||
mainViewModel.entityLists.clear()
|
||||
mainViewModel.entityLists.putAll(lists)
|
||||
mainViewModel.entityListsOrder.clear()
|
||||
|
@ -68,8 +68,7 @@ fun LoadHomePage(
|
|||
swipeDismissableNavController.navigate(SCREEN_ENTITY_LIST)
|
||||
},
|
||||
isHapticEnabled = mainViewModel.isHapticEnabled.value,
|
||||
isToastEnabled = mainViewModel.isToastEnabled.value,
|
||||
deleteFavorite = { id -> mainViewModel.removeFavoriteEntity(id) }
|
||||
isToastEnabled = mainViewModel.isToastEnabled.value
|
||||
)
|
||||
}
|
||||
composable("$SCREEN_ENTITY_DETAIL/{entityId}") {
|
||||
|
@ -141,8 +140,10 @@ fun LoadHomePage(
|
|||
onClickLogout = { mainViewModel.logout() },
|
||||
isHapticEnabled = mainViewModel.isHapticEnabled.value,
|
||||
isToastEnabled = mainViewModel.isToastEnabled.value,
|
||||
isFavoritesOnly = mainViewModel.isFavoritesOnly,
|
||||
onHapticEnabled = { mainViewModel.setHapticEnabled(it) },
|
||||
onToastEnabled = { mainViewModel.setToastEnabled(it) }
|
||||
onToastEnabled = { mainViewModel.setToastEnabled(it) },
|
||||
setFavoritesOnly = { mainViewModel.setWearFavoritesOnly(it) }
|
||||
) { swipeDismissableNavController.navigate(SCREEN_SET_TILE_TEMPLATE) }
|
||||
}
|
||||
composable(SCREEN_SET_FAVORITES) {
|
||||
|
|
|
@ -54,10 +54,9 @@ fun MainView(
|
|||
onEntityLongClicked: (String) -> Unit,
|
||||
onRetryLoadEntitiesClicked: () -> Unit,
|
||||
onSettingsClicked: () -> Unit,
|
||||
onTestClicked: (entityLists: Map<String, List<Entity<*>>>, listOrder: List<String>, filter: (Entity<*>) -> (Boolean)) -> Unit,
|
||||
onNavigationClicked: (entityLists: Map<String, List<Entity<*>>>, listOrder: List<String>, filter: (Entity<*>) -> Boolean) -> Unit,
|
||||
isHapticEnabled: Boolean,
|
||||
isToastEnabled: Boolean,
|
||||
deleteFavorite: (String) -> Unit
|
||||
isToastEnabled: Boolean
|
||||
) {
|
||||
val scalingLazyListState: ScalingLazyListState = rememberScalingLazyListState()
|
||||
|
||||
|
@ -123,12 +122,13 @@ fun MainView(
|
|||
isHapticEnabled,
|
||||
isToastEnabled
|
||||
) { entityId -> onEntityLongClicked(entityId) }
|
||||
} ?: deleteFavorite(favoriteEntityID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mainViewModel.isFavoritesOnly) {
|
||||
when (mainViewModel.loadingState.value) {
|
||||
MainViewModel.LoadingState.LOADING -> {
|
||||
if (favoriteEntityIds.isEmpty()) {
|
||||
|
@ -201,7 +201,8 @@ fun MainView(
|
|||
}
|
||||
}
|
||||
|
||||
if (mainViewModel.entitiesByArea.values.any {
|
||||
if (
|
||||
mainViewModel.entitiesByArea.values.any {
|
||||
it.isNotEmpty() && it.any { entity ->
|
||||
mainViewModel.getCategoryForEntity(entity.entityId) == null &&
|
||||
mainViewModel.getHiddenByForEntity(entity.entityId) == null
|
||||
|
@ -226,12 +227,14 @@ fun MainView(
|
|||
Text(text = area.name)
|
||||
},
|
||||
onClick = {
|
||||
onTestClicked(
|
||||
onNavigationClicked(
|
||||
mapOf(area.name to entities),
|
||||
listOf(area.name)
|
||||
) {
|
||||
mainViewModel.getCategoryForEntity(it.entityId) == null &&
|
||||
mainViewModel.getHiddenByForEntity(it.entityId) == null
|
||||
mainViewModel.getHiddenByForEntity(
|
||||
it.entityId
|
||||
) == null
|
||||
}
|
||||
},
|
||||
colors = ChipDefaults.primaryChipColors()
|
||||
|
@ -255,19 +258,24 @@ fun MainView(
|
|||
// Buttons for each existing category
|
||||
for (domain in mainViewModel.entitiesByDomainOrder) {
|
||||
val domainEntities = mainViewModel.entitiesByDomain[domain]!!
|
||||
val domainEntitiesToShow = domainEntities.filter(domainEntitiesFilter)
|
||||
val domainEntitiesToShow =
|
||||
domainEntities.filter(domainEntitiesFilter)
|
||||
if (domainEntitiesToShow.isNotEmpty()) {
|
||||
item {
|
||||
Chip(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
icon = {
|
||||
getIcon("", domain, context)?.let { Image(asset = it) }
|
||||
getIcon(
|
||||
"",
|
||||
domain,
|
||||
context
|
||||
)?.let { Image(asset = it) }
|
||||
},
|
||||
label = {
|
||||
Text(text = mainViewModel.stringForDomain(domain)!!)
|
||||
},
|
||||
onClick = {
|
||||
onTestClicked(
|
||||
onNavigationClicked(
|
||||
mapOf(
|
||||
mainViewModel.stringForDomain(domain)!! to domainEntities
|
||||
),
|
||||
|
@ -300,9 +308,17 @@ fun MainView(
|
|||
Text(text = stringResource(commonR.string.all_entities))
|
||||
},
|
||||
onClick = {
|
||||
onTestClicked(
|
||||
mainViewModel.entitiesByDomain.mapKeys { mainViewModel.stringForDomain(it.key)!! },
|
||||
mainViewModel.entitiesByDomain.keys.map { mainViewModel.stringForDomain(it)!! }.sorted()
|
||||
onNavigationClicked(
|
||||
mainViewModel.entitiesByDomain.mapKeys {
|
||||
mainViewModel.stringForDomain(
|
||||
it.key
|
||||
)!!
|
||||
},
|
||||
mainViewModel.entitiesByDomain.keys.map {
|
||||
mainViewModel.stringForDomain(
|
||||
it
|
||||
)!!
|
||||
}.sorted()
|
||||
) { true }
|
||||
},
|
||||
colors = ChipDefaults.secondaryChipColors()
|
||||
|
@ -311,6 +327,12 @@ fun MainView(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mainViewModel.isFavoritesOnly)
|
||||
item {
|
||||
Spacer(Modifier.padding(32.dp))
|
||||
}
|
||||
|
||||
// Settings
|
||||
item {
|
||||
|
|
|
@ -68,8 +68,10 @@ fun SettingsView(
|
|||
onClickLogout: () -> Unit,
|
||||
isHapticEnabled: Boolean,
|
||||
isToastEnabled: Boolean,
|
||||
isFavoritesOnly: Boolean,
|
||||
onHapticEnabled: (Boolean) -> Unit,
|
||||
onToastEnabled: (Boolean) -> Unit,
|
||||
setFavoritesOnly: (Boolean) -> Unit,
|
||||
onClickTemplateTile: () -> Unit
|
||||
) {
|
||||
val scalingLazyListState: ScalingLazyListState = rememberScalingLazyListState()
|
||||
|
@ -105,6 +107,30 @@ fun SettingsView(
|
|||
onClick = onClearFavorites
|
||||
)
|
||||
}
|
||||
item {
|
||||
ToggleChip(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
checked = isFavoritesOnly,
|
||||
onCheckedChange = { setFavoritesOnly(it) },
|
||||
label = { Text(stringResource(commonR.string.only_favorites)) },
|
||||
enabled = favorites.isNotEmpty(),
|
||||
toggleControl = {
|
||||
Icon(
|
||||
imageVector = ToggleChipDefaults.switchIcon(isFavoritesOnly),
|
||||
contentDescription = if (isFavoritesOnly)
|
||||
stringResource(commonR.string.enabled)
|
||||
else
|
||||
stringResource(commonR.string.disabled)
|
||||
)
|
||||
},
|
||||
appIcon = {
|
||||
Image(
|
||||
asset = CommunityMaterial.Icon2.cmd_home_heart,
|
||||
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
ListHeader(
|
||||
id = commonR.string.feedback_settings
|
||||
|
@ -245,7 +271,9 @@ private fun PreviewSettingsView() {
|
|||
onClickLogout = {},
|
||||
isHapticEnabled = true,
|
||||
isToastEnabled = false,
|
||||
isFavoritesOnly = false,
|
||||
onHapticEnabled = {},
|
||||
onToastEnabled = {}
|
||||
onToastEnabled = {},
|
||||
setFavoritesOnly = {}
|
||||
) {}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue