-
-
Notifications
You must be signed in to change notification settings - Fork 674
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Better state hoisting. * Broke down compose items and removed dependant state. * Functional minus favorites.... * Favorites working, not my best solution. * Breaking more stuff down. * ktlint.
- Loading branch information
Showing
14 changed files
with
726 additions
and
673 deletions.
There are no files selected for viewing
461 changes: 5 additions & 456 deletions
461
wear/src/main/java/io/homeassistant/companion/android/home/HomeActivity.kt
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
wear/src/main/java/io/homeassistant/companion/android/home/MainViewModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package io.homeassistant.companion.android.home | ||
|
||
import androidx.compose.runtime.mutableStateListOf | ||
import androidx.lifecycle.ViewModel | ||
import androidx.lifecycle.viewModelScope | ||
import io.homeassistant.companion.android.common.data.integration.Entity | ||
import kotlinx.coroutines.launch | ||
|
||
class MainViewModel : ViewModel() { | ||
|
||
private lateinit var homePresenter: HomePresenter | ||
|
||
// TODO: This is bad, do this instead: https://stackoverflow.com/questions/46283981/android-viewmodel-additional-arguments | ||
fun init(homePresenter: HomePresenter) { | ||
this.homePresenter = homePresenter | ||
loadEntities() | ||
} | ||
|
||
var entities = mutableStateListOf<Entity<*>>() | ||
private set | ||
var favoriteEntityIds = mutableStateListOf<String>() | ||
private set | ||
|
||
fun loadEntities() { | ||
viewModelScope.launch { | ||
entities.addAll(homePresenter.getEntities()) | ||
favoriteEntityIds.addAll(homePresenter.getWearHomeFavorites()) | ||
} | ||
} | ||
|
||
fun toggleEntity(entityId: String) { | ||
viewModelScope.launch { | ||
homePresenter.onEntityClicked(entityId) | ||
val updatedEntities = homePresenter.getEntities() | ||
// This should be better.... | ||
for (i in updatedEntities.indices) { | ||
entities[i] = updatedEntities[i] | ||
} | ||
} | ||
} | ||
|
||
fun addFavorite(entityId: String) { | ||
|
||
viewModelScope.launch { | ||
favoriteEntityIds.add(entityId) | ||
homePresenter.setWearHomeFavorites(favoriteEntityIds) | ||
} | ||
} | ||
|
||
fun removeFavorite(entity: String) { | ||
|
||
viewModelScope.launch { | ||
favoriteEntityIds.remove(entity) | ||
homePresenter.setWearHomeFavorites(favoriteEntityIds) | ||
} | ||
} | ||
|
||
fun clearFavorites() { | ||
viewModelScope.launch { | ||
favoriteEntityIds.clear() | ||
homePresenter.setWearHomeFavorites(favoriteEntityIds) | ||
} | ||
} | ||
|
||
fun logout() { | ||
homePresenter.onLogoutClicked() | ||
} | ||
} |
78 changes: 78 additions & 0 deletions
78
wear/src/main/java/io/homeassistant/companion/android/home/views/EntityUi.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package io.homeassistant.companion.android.home.views | ||
|
||
import androidx.compose.foundation.layout.fillMaxWidth | ||
import androidx.compose.foundation.layout.padding | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.graphics.Color | ||
import androidx.compose.ui.platform.LocalContext | ||
import androidx.compose.ui.res.colorResource | ||
import androidx.compose.ui.text.style.TextOverflow | ||
import androidx.compose.ui.unit.dp | ||
import androidx.wear.compose.material.Chip | ||
import androidx.wear.compose.material.Text | ||
import androidx.wear.compose.material.ToggleChip | ||
import androidx.wear.compose.material.ToggleChipDefaults | ||
import com.mikepenz.iconics.compose.Image | ||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial | ||
import io.homeassistant.companion.android.R | ||
import io.homeassistant.companion.android.common.data.integration.Entity | ||
import io.homeassistant.companion.android.home.HomePresenterImpl | ||
import io.homeassistant.companion.android.util.getIcon | ||
import io.homeassistant.companion.android.util.setChipDefaults | ||
|
||
@Composable | ||
fun EntityUi( | ||
entity: Entity<*>, | ||
onEntityClicked: (String) -> Unit | ||
) { | ||
val attributes = entity.attributes as Map<*, *> | ||
val iconBitmap = getIcon(attributes["icon"] as String?, entity.entityId.split(".")[0], LocalContext.current) | ||
|
||
if (entity.entityId.split(".")[0] in HomePresenterImpl.toggleDomains) { | ||
ToggleChip( | ||
checked = entity.state == "on", | ||
onCheckedChange = { onEntityClicked(entity.entityId) }, | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.padding(bottom = 10.dp), | ||
appIcon = { Image(asset = iconBitmap ?: CommunityMaterial.Icon.cmd_cellphone) }, | ||
label = { | ||
Text( | ||
text = attributes["friendly_name"].toString(), | ||
maxLines = 2, | ||
overflow = TextOverflow.Ellipsis | ||
) | ||
}, | ||
enabled = entity.state != "unavailable", | ||
toggleIcon = { ToggleChipDefaults.SwitchIcon(entity.state == "on") }, | ||
colors = ToggleChipDefaults.toggleChipColors( | ||
checkedStartBackgroundColor = colorResource(id = R.color.colorAccent), | ||
checkedEndBackgroundColor = colorResource(id = R.color.colorAccent), | ||
uncheckedStartBackgroundColor = colorResource(id = R.color.colorAccent), | ||
uncheckedEndBackgroundColor = colorResource(id = R.color.colorAccent), | ||
checkedContentColor = Color.Black, | ||
uncheckedContentColor = Color.Black, | ||
checkedToggleIconTintColor = Color.Yellow, | ||
uncheckedToggleIconTintColor = Color.DarkGray | ||
) | ||
) | ||
} else { | ||
Chip( | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.padding(bottom = 10.dp), | ||
icon = { Image(asset = iconBitmap ?: CommunityMaterial.Icon.cmd_cellphone) }, | ||
label = { | ||
Text( | ||
text = attributes["friendly_name"].toString(), | ||
maxLines = 2, | ||
overflow = TextOverflow.Ellipsis | ||
) | ||
}, | ||
enabled = entity.state != "unavailable", | ||
onClick = { onEntityClicked(entity.entityId) }, | ||
colors = setChipDefaults() | ||
) | ||
} | ||
} |
106 changes: 106 additions & 0 deletions
106
wear/src/main/java/io/homeassistant/companion/android/home/views/HomeView.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package io.homeassistant.companion.android.home.views | ||
|
||
import androidx.compose.foundation.layout.Column | ||
import androidx.compose.foundation.layout.Spacer | ||
import androidx.compose.foundation.layout.fillMaxWidth | ||
import androidx.compose.foundation.layout.padding | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.CompositionLocalProvider | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.res.stringResource | ||
import androidx.compose.ui.text.style.TextAlign | ||
import androidx.compose.ui.unit.dp | ||
import androidx.wear.compose.material.Chip | ||
import androidx.wear.compose.material.ExperimentalWearMaterialApi | ||
import androidx.wear.compose.material.MaterialTheme | ||
import androidx.wear.compose.material.Text | ||
import androidx.wear.compose.navigation.SwipeDismissableNavHost | ||
import androidx.wear.compose.navigation.composable | ||
import androidx.wear.compose.navigation.rememberSwipeDismissableNavController | ||
import io.homeassistant.companion.android.R | ||
import io.homeassistant.companion.android.home.HomePresenterImpl | ||
import io.homeassistant.companion.android.home.MainViewModel | ||
import io.homeassistant.companion.android.util.LocalRotaryEventDispatcher | ||
import io.homeassistant.companion.android.util.RotaryEventDispatcher | ||
import io.homeassistant.companion.android.util.RotaryEventHandlerSetup | ||
import io.homeassistant.companion.android.util.SetTitle | ||
import io.homeassistant.companion.android.util.setChipDefaults | ||
|
||
private const val SCREEN_LANDING = "landing" | ||
private const val SCREEN_SETTINGS = "settings" | ||
private const val SCREEN_SET_FAVORITES = "set_favorites" | ||
|
||
@ExperimentalWearMaterialApi | ||
@Composable | ||
fun LoadHomePage( | ||
mainViewModel: MainViewModel | ||
) { | ||
|
||
val rotaryEventDispatcher = RotaryEventDispatcher() | ||
if (mainViewModel.entities.isNullOrEmpty() && mainViewModel.favoriteEntityIds.isNullOrEmpty()) { | ||
Column { | ||
Spacer( | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.padding(top = 10.dp) | ||
) | ||
SetTitle(id = R.string.loading) | ||
Chip( | ||
modifier = Modifier | ||
.padding(top = 50.dp, start = 10.dp, end = 10.dp), | ||
label = { | ||
Text( | ||
text = stringResource(R.string.loading_entities), | ||
textAlign = TextAlign.Center | ||
) | ||
}, | ||
onClick = { /* No op */ }, | ||
colors = setChipDefaults() | ||
) | ||
} | ||
} else { | ||
val swipeDismissableNavController = rememberSwipeDismissableNavController() | ||
MaterialTheme { | ||
CompositionLocalProvider( | ||
LocalRotaryEventDispatcher provides rotaryEventDispatcher | ||
) { | ||
RotaryEventHandlerSetup(rotaryEventDispatcher) | ||
SwipeDismissableNavHost( | ||
navController = swipeDismissableNavController, | ||
startDestination = SCREEN_LANDING | ||
) { | ||
composable(SCREEN_LANDING) { | ||
MainView( | ||
mainViewModel.entities, | ||
mainViewModel.favoriteEntityIds, | ||
{ mainViewModel.toggleEntity(it) }, | ||
{ swipeDismissableNavController.navigate(SCREEN_SETTINGS) }, | ||
{ mainViewModel.logout() } | ||
) | ||
} | ||
composable(SCREEN_SETTINGS) { | ||
SettingsView( | ||
mainViewModel.favoriteEntityIds, | ||
{ swipeDismissableNavController.navigate(SCREEN_SET_FAVORITES) }, | ||
{ mainViewModel.clearFavorites() } | ||
) | ||
} | ||
composable(SCREEN_SET_FAVORITES) { | ||
val validEntities = mainViewModel.entities | ||
.filter { it.entityId.split(".")[0] in HomePresenterImpl.supportedDomains } | ||
SetFavoritesView( | ||
validEntities, | ||
mainViewModel.favoriteEntityIds | ||
) { entityId, isSelected -> | ||
if (isSelected) { | ||
mainViewModel.addFavorite(entityId) | ||
} else { | ||
mainViewModel.removeFavorite(entityId) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
wear/src/main/java/io/homeassistant/companion/android/home/views/ListHeader.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package io.homeassistant.companion.android.home.views | ||
|
||
import androidx.compose.foundation.clickable | ||
import androidx.compose.foundation.layout.Row | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.graphics.Color | ||
import androidx.compose.ui.res.stringResource | ||
import androidx.wear.compose.material.ListHeader | ||
import androidx.wear.compose.material.Text | ||
|
||
@Composable | ||
fun ListHeader( | ||
stringId: Int, | ||
expanded: Boolean, | ||
onExpandChanged: (Boolean) -> Unit | ||
) { | ||
ListHeader( | ||
modifier = Modifier | ||
.clickable { onExpandChanged(!expanded) } | ||
) { | ||
Row { | ||
Text( | ||
text = stringResource(id = stringId) + if (expanded) " -" else " +", | ||
color = Color.White | ||
) | ||
} | ||
} | ||
} |
Oops, something went wrong.