Add missing scroll bar to remaining screens (#3895)

* Add missing scroll bar to remaining screens

* Add Scaffold to ThemeLazyColumn

* Remove unneeded variable

* Remove nested scaffold
This commit is contained in:
Daniel Shokouhi 2023-09-29 05:29:56 -07:00 committed by GitHub
parent 2f777a1379
commit a15f7b3bc4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 988 additions and 1173 deletions

View file

@ -43,8 +43,6 @@ import androidx.wear.compose.material.ButtonDefaults
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.LocalContentColor
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.Text
import androidx.wear.compose.navigation.SwipeDismissableNavHost
import androidx.wear.compose.navigation.composable
@ -55,7 +53,6 @@ import io.homeassistant.companion.android.common.R
import io.homeassistant.companion.android.common.assist.AssistViewModelBase
import io.homeassistant.companion.android.common.data.websocket.impl.entities.AssistPipelineResponse
import io.homeassistant.companion.android.conversation.ConversationViewModel
import io.homeassistant.companion.android.home.views.TimeText
import io.homeassistant.companion.android.theme.WearAppTheme
import io.homeassistant.companion.android.util.KeepScreenOn
import io.homeassistant.companion.android.views.ListHeader
@ -117,103 +114,93 @@ fun ConversationResultView(
onMicrophoneInput: () -> Unit
) {
val scrollState = rememberScalingLazyListState()
Scaffold(
positionIndicator = {
if (scrollState.isScrollInProgress) {
PositionIndicator(scalingLazyListState = scrollState)
}
},
timeText = { TimeText(scalingLazyListState = scrollState) }
) {
LaunchedEffect(conversation.size) {
scrollState.scrollToItem(
if (inputMode != AssistViewModelBase.AssistInputMode.BLOCKED) conversation.size else (conversation.size - 1)
)
}
if (hapticFeedback) {
val haptic = LocalHapticFeedback.current
LaunchedEffect("${conversation.size}.${conversation.lastOrNull()?.message?.length}") {
val message = conversation.lastOrNull() ?: return@LaunchedEffect
if (conversation.size > 1 && !message.isInput && message.message != "") {
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
}
LaunchedEffect(conversation.size) {
scrollState.scrollToItem(
if (inputMode != AssistViewModelBase.AssistInputMode.BLOCKED) conversation.size else (conversation.size - 1)
)
}
if (hapticFeedback) {
val haptic = LocalHapticFeedback.current
LaunchedEffect("${conversation.size}.${conversation.lastOrNull()?.message?.length}") {
val message = conversation.lastOrNull() ?: return@LaunchedEffect
if (conversation.size > 1 && !message.isInput && message.message != "") {
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
}
}
}
ThemeLazyColumn(state = scrollState) {
item {
if (currentPipeline != null) {
val textColor = LocalContentColor.current.copy(alpha = 0.38f) // disabled/hint alpha
Row(
modifier = Modifier
.clickable(
onClick = { onChangePipeline() },
onClickLabel = stringResource(R.string.assist_change_pipeline)
)
.padding(bottom = 4.dp)
) {
Text(
text = currentPipeline.name,
fontSize = 11.sp,
color = textColor
ThemeLazyColumn(state = scrollState) {
item {
if (currentPipeline != null) {
val textColor = LocalContentColor.current.copy(alpha = 0.38f) // disabled/hint alpha
Row(
modifier = Modifier
.clickable(
onClick = { onChangePipeline() },
onClickLabel = stringResource(R.string.assist_change_pipeline)
)
Image(
asset = CommunityMaterial.Icon.cmd_chevron_right,
.padding(bottom = 4.dp)
) {
Text(
text = currentPipeline.name,
fontSize = 11.sp,
color = textColor
)
Image(
asset = CommunityMaterial.Icon.cmd_chevron_right,
modifier = Modifier
.size(16.dp)
.padding(start = 4.dp),
colorFilter = ColorFilter.tint(textColor)
)
}
} else {
Spacer(modifier = Modifier.height(16.dp))
}
}
items(conversation) {
SpeechBubble(text = it.message, isResponse = !it.isInput)
}
if (inputMode != AssistViewModelBase.AssistInputMode.BLOCKED) {
item {
Box(
modifier = Modifier.size(64.dp),
contentAlignment = Alignment.Center
) {
val inputIsActive = inputMode == AssistViewModelBase.AssistInputMode.VOICE_ACTIVE
if (inputIsActive) {
KeepScreenOn()
val transition = rememberInfiniteTransition()
val scale by transition.animateFloat(
initialValue = 1f,
targetValue = 1.2f,
animationSpec = infiniteRepeatable(
animation = tween(600, easing = LinearEasing),
repeatMode = RepeatMode.Reverse
)
)
Box(
modifier = Modifier
.size(16.dp)
.padding(start = 4.dp),
colorFilter = ColorFilter.tint(textColor)
.size(48.dp)
.scale(scale)
.background(color = colorResource(R.color.colorSpeechText), shape = CircleShape)
.clip(CircleShape)
)
}
} else {
Spacer(modifier = Modifier.height(16.dp))
}
}
items(conversation) {
SpeechBubble(text = it.message, isResponse = !it.isInput)
}
if (inputMode != AssistViewModelBase.AssistInputMode.BLOCKED) {
item {
Box(
modifier = Modifier.size(64.dp),
contentAlignment = Alignment.Center
) {
val inputIsActive = inputMode == AssistViewModelBase.AssistInputMode.VOICE_ACTIVE
Button(
onClick = { onMicrophoneInput() },
colors =
if (inputIsActive) {
KeepScreenOn()
val transition = rememberInfiniteTransition()
val scale by transition.animateFloat(
initialValue = 1f,
targetValue = 1.2f,
animationSpec = infiniteRepeatable(
animation = tween(600, easing = LinearEasing),
repeatMode = RepeatMode.Reverse
)
)
Box(
modifier = Modifier
.size(48.dp)
.scale(scale)
.background(color = colorResource(R.color.colorSpeechText), shape = CircleShape)
.clip(CircleShape)
)
}
Button(
onClick = { onMicrophoneInput() },
colors =
if (inputIsActive) {
ButtonDefaults.secondaryButtonColors(backgroundColor = Color.Transparent, contentColor = Color.Black)
} else {
ButtonDefaults.secondaryButtonColors()
}
) {
Image(
asset = CommunityMaterial.Icon3.cmd_microphone,
contentDescription = stringResource(R.string.assist_start_listening),
colorFilter = ColorFilter.tint(LocalContentColor.current)
)
ButtonDefaults.secondaryButtonColors(backgroundColor = Color.Transparent, contentColor = Color.Black)
} else {
ButtonDefaults.secondaryButtonColors()
}
) {
Image(
asset = CommunityMaterial.Icon3.cmd_microphone,
contentDescription = stringResource(R.string.assist_start_listening),
colorFilter = ColorFilter.tint(LocalContentColor.current)
)
}
}
}

View file

@ -19,12 +19,9 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.InlineSlider
import androidx.wear.compose.material.InlineSliderDefaults
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.ToggleButton
import androidx.wear.compose.material.ToggleButtonDefaults
@ -62,116 +59,106 @@ fun DetailsPanelView(
) {
val haptic = LocalHapticFeedback.current
val context = LocalContext.current
val scalingLazyListState = rememberScalingLazyListState()
WearAppTheme {
Scaffold(
positionIndicator = {
if (scalingLazyListState.isScrollInProgress) {
PositionIndicator(scalingLazyListState = scalingLazyListState)
}
},
timeText = { TimeText(scalingLazyListState = scalingLazyListState) }
) {
ThemeLazyColumn(state = scalingLazyListState) {
val attributes = entity.attributes as Map<*, *>
ThemeLazyColumn {
val attributes = entity.attributes as Map<*, *>
item {
Row(
verticalAlignment = Alignment.CenterVertically
) {
val friendlyName = attributes["friendly_name"].toString()
Text(friendlyName)
item {
Row(
verticalAlignment = Alignment.CenterVertically
) {
val friendlyName = attributes["friendly_name"].toString()
Text(friendlyName)
if (entity.domain in EntityExt.DOMAINS_TOGGLE) {
val isChecked = entity.state in listOf("on", "locked", "open", "opening")
ToggleButton(
checked = isChecked,
onCheckedChange = {
onEntityToggled(entity.entityId, entity.state)
onEntityClickedFeedback(
isToastEnabled,
isHapticEnabled,
context,
friendlyName,
haptic
)
},
modifier = Modifier
.padding(start = 16.dp)
.size(ToggleButtonDefaults.SmallToggleButtonSize)
) {
Icon(
imageVector = ToggleChipDefaults.switchIcon(isChecked),
contentDescription = if (isChecked) {
stringResource(R.string.enabled)
} else {
stringResource(R.string.disabled)
}
if (entity.domain in EntityExt.DOMAINS_TOGGLE) {
val isChecked = entity.state in listOf("on", "locked", "open", "opening")
ToggleButton(
checked = isChecked,
onCheckedChange = {
onEntityToggled(entity.entityId, entity.state)
onEntityClickedFeedback(
isToastEnabled,
isHapticEnabled,
context,
friendlyName,
haptic
)
}
},
modifier = Modifier
.padding(start = 16.dp)
.size(ToggleButtonDefaults.SmallToggleButtonSize)
) {
Icon(
imageVector = ToggleChipDefaults.switchIcon(isChecked),
contentDescription = if (isChecked) {
stringResource(R.string.enabled)
} else {
stringResource(R.string.disabled)
}
)
}
}
}
}
if (entity.domain == "fan") {
if (entity.supportsFanSetSpeed()) {
item {
FanSpeedSlider(entity, onFanSpeedChanged, isToastEnabled, isHapticEnabled)
}
}
}
if (entity.domain == "light") {
if (entity.supportsLightBrightness()) {
item {
BrightnessSlider(entity, onBrightnessChanged, isToastEnabled, isHapticEnabled)
}
}
if (entity.domain == "fan") {
if (entity.supportsFanSetSpeed()) {
item {
FanSpeedSlider(entity, onFanSpeedChanged, isToastEnabled, isHapticEnabled)
}
if (entity.supportsLightColorTemperature() && attributes["color_mode"] == EntityExt.LIGHT_MODE_COLOR_TEMP) {
item {
ColorTempSlider(attributes, onColorTempChanged, isToastEnabled, isHapticEnabled)
}
}
if (entity.domain == "light") {
if (entity.supportsLightBrightness()) {
item {
BrightnessSlider(entity, onBrightnessChanged, isToastEnabled, isHapticEnabled)
}
}
}
if (entity.supportsLightColorTemperature() && attributes["color_mode"] == EntityExt.LIGHT_MODE_COLOR_TEMP) {
item {
ColorTempSlider(attributes, onColorTempChanged, isToastEnabled, isHapticEnabled)
}
}
}
item {
ListHeader(R.string.details)
}
item {
Text(
stringResource(R.string.state_name, entity.state),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp)
)
}
item {
val lastChanged = DateFormat.getDateTimeInstance().format(entity.lastChanged.time)
Text(
stringResource(R.string.last_changed, lastChanged),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp)
)
}
item {
val lastUpdated = DateFormat.getDateTimeInstance().format(entity.lastUpdated.time)
Text(
stringResource(R.string.last_updated, lastUpdated),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp)
)
}
item {
Text(
stringResource(R.string.entity_id_name, entity.entityId),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp)
)
}
item {
ListHeader(R.string.details)
}
item {
Text(
stringResource(R.string.state_name, entity.state),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp)
)
}
item {
val lastChanged = DateFormat.getDateTimeInstance().format(entity.lastChanged.time)
Text(
stringResource(R.string.last_changed, lastChanged),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp)
)
}
item {
val lastUpdated = DateFormat.getDateTimeInstance().format(entity.lastUpdated.time)
Text(
stringResource(R.string.last_updated, lastUpdated),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp)
)
}
item {
Text(
stringResource(R.string.entity_id_name, entity.entityId),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp)
)
}
}
}

View file

@ -7,11 +7,8 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.wear.compose.foundation.lazy.items
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.Text
import io.homeassistant.companion.android.common.data.integration.Entity
import io.homeassistant.companion.android.theme.WearAppTheme
@ -38,57 +35,47 @@ fun EntityViewList(
) {
// Remember expanded state of each header
val expandedStates = rememberExpandedStates(entityLists.keys.map { it.hashCode() })
val scalingLazyListState = rememberScalingLazyListState()
WearAppTheme {
Scaffold(
positionIndicator = {
if (scalingLazyListState.isScrollInProgress) {
PositionIndicator(scalingLazyListState = scalingLazyListState)
}
},
timeText = { TimeText(scalingLazyListState = scalingLazyListState) }
) {
ThemeLazyColumn(state = scalingLazyListState) {
for (header in entityListsOrder) {
val entities = entityLists[header].orEmpty()
if (entities.isNotEmpty()) {
item {
if (entityLists.size > 1) {
ExpandableListHeader(
string = header,
key = header.hashCode(),
expandedStates = expandedStates
)
} else {
ListHeader(header)
}
ThemeLazyColumn {
for (header in entityListsOrder) {
val entities = entityLists[header].orEmpty()
if (entities.isNotEmpty()) {
item {
if (entityLists.size > 1) {
ExpandableListHeader(
string = header,
key = header.hashCode(),
expandedStates = expandedStates
)
} else {
ListHeader(header)
}
}
if (expandedStates[header.hashCode()]!!) {
val filtered = entities.filter { entityListFilter(it) }
items(filtered, key = { it.entityId }) { entity ->
EntityUi(
entity,
onEntityClicked,
isHapticEnabled,
isToastEnabled
) { entityId -> onEntityLongClicked(entityId) }
}
if (expandedStates[header.hashCode()]!!) {
val filtered = entities.filter { entityListFilter(it) }
items(filtered, key = { it.entityId }) { entity ->
EntityUi(
entity,
onEntityClicked,
isHapticEnabled,
isToastEnabled
) { entityId -> onEntityLongClicked(entityId) }
}
if (filtered.isEmpty()) {
item {
Column {
Chip(
label = {
Text(
text = stringResource(commonR.string.loading_entities),
textAlign = TextAlign.Center
)
},
onClick = { /* No op */ },
colors = ChipDefaults.primaryChipColors()
)
}
if (filtered.isEmpty()) {
item {
Column {
Chip(
label = {
Text(
text = stringResource(commonR.string.loading_entities),
textAlign = TextAlign.Center
)
},
onClick = { /* No op */ },
colors = ChipDefaults.primaryChipColors()
)
}
}
}

View file

@ -24,13 +24,10 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.CircularProgressIndicator
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.Text
import com.mikepenz.iconics.compose.Image
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
@ -58,308 +55,295 @@ fun MainView(
isHapticEnabled: Boolean,
isToastEnabled: Boolean
) {
val scalingLazyListState = rememberScalingLazyListState()
var expandedFavorites: Boolean by rememberSaveable { mutableStateOf(true) }
val haptic = LocalHapticFeedback.current
val context = LocalContext.current
WearAppTheme {
Scaffold(
positionIndicator = {
if (scalingLazyListState.isScrollInProgress) {
PositionIndicator(scalingLazyListState = scalingLazyListState)
ThemeLazyColumn {
if (favoriteEntityIds.isNotEmpty()) {
item {
ExpandableListHeader(
string = stringResource(commonR.string.favorites),
expanded = expandedFavorites,
onExpandChanged = { expandedFavorites = it }
)
}
},
timeText = { TimeText(scalingLazyListState = scalingLazyListState) }
) {
ThemeLazyColumn(
state = scalingLazyListState
) {
if (favoriteEntityIds.isNotEmpty()) {
item {
ExpandableListHeader(
string = stringResource(commonR.string.favorites),
expanded = expandedFavorites,
onExpandChanged = { expandedFavorites = it }
)
if (expandedFavorites) {
items(favoriteEntityIds.size) { index ->
val favoriteEntityID = favoriteEntityIds[index].split(",")[0]
if (mainViewModel.entities.isEmpty()) {
// when we don't have the state of the entity, create a Chip from cache as we don't have the state yet
val cached = mainViewModel.getCachedEntity(favoriteEntityID)
Chip(
modifier = Modifier
.fillMaxWidth(),
icon = {
Image(
asset = getIcon(cached?.icon, favoriteEntityID.split(".")[0], context),
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
label = {
Text(
text = cached?.friendlyName ?: favoriteEntityID,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
},
onClick = {
onEntityClicked(favoriteEntityID, STATE_UNKNOWN)
onEntityClickedFeedback(isToastEnabled, isHapticEnabled, context, favoriteEntityID, haptic)
},
colors = ChipDefaults.secondaryChipColors()
)
} else {
mainViewModel.entities.values.toList()
.firstOrNull { it.entityId == favoriteEntityID }
?.let {
EntityUi(
mainViewModel.entities[favoriteEntityID]!!,
onEntityClicked,
isHapticEnabled,
isToastEnabled
) { entityId -> onEntityLongClicked(entityId) }
}
}
}
if (expandedFavorites) {
items(favoriteEntityIds.size) { index ->
val favoriteEntityID = favoriteEntityIds[index].split(",")[0]
if (mainViewModel.entities.isEmpty()) {
// when we don't have the state of the entity, create a Chip from cache as we don't have the state yet
val cached = mainViewModel.getCachedEntity(favoriteEntityID)
}
}
if (!mainViewModel.isFavoritesOnly) {
when (mainViewModel.loadingState.value) {
MainViewModel.LoadingState.LOADING -> {
if (favoriteEntityIds.isEmpty()) {
// Add a Spacer to prevent settings being pushed to the screen center
item { Spacer(modifier = Modifier.fillMaxWidth()) }
}
item {
val minHeight =
if (favoriteEntityIds.isEmpty()) {
LocalConfiguration.current.screenHeightDp - 64
} else {
0
}
Column(
modifier = Modifier
.heightIn(min = minHeight.dp)
.fillMaxSize()
.padding(vertical = if (favoriteEntityIds.isEmpty()) 0.dp else 32.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
ListHeader(id = commonR.string.loading)
CircularProgressIndicator()
}
}
}
MainViewModel.LoadingState.ERROR -> {
item {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
ListHeader(id = commonR.string.error_loading_entities)
Chip(
modifier = Modifier
.fillMaxWidth(),
icon = {
Image(
asset = getIcon(cached?.icon, favoriteEntityID.split(".")[0], context),
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
label = {
Text(
text = cached?.friendlyName ?: favoriteEntityID,
maxLines = 2,
overflow = TextOverflow.Ellipsis
text = stringResource(commonR.string.retry),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
},
onClick = {
onEntityClicked(favoriteEntityID, STATE_UNKNOWN)
onEntityClickedFeedback(isToastEnabled, isHapticEnabled, context, favoriteEntityID, haptic)
},
colors = ChipDefaults.secondaryChipColors()
onClick = onRetryLoadEntitiesClicked,
colors = ChipDefaults.primaryChipColors()
)
} else {
mainViewModel.entities.values.toList()
.firstOrNull { it.entityId == favoriteEntityID }
?.let {
EntityUi(
mainViewModel.entities[favoriteEntityID]!!,
onEntityClicked,
isHapticEnabled,
isToastEnabled
) { entityId -> onEntityLongClicked(entityId) }
}
Spacer(modifier = Modifier.height(32.dp))
}
}
}
}
if (!mainViewModel.isFavoritesOnly) {
when (mainViewModel.loadingState.value) {
MainViewModel.LoadingState.LOADING -> {
if (favoriteEntityIds.isEmpty()) {
// Add a Spacer to prevent settings being pushed to the screen center
item { Spacer(modifier = Modifier.fillMaxWidth()) }
}
item {
val minHeight =
if (favoriteEntityIds.isEmpty()) {
LocalConfiguration.current.screenHeightDp - 64
} else {
0
}
Column(
modifier = Modifier
.heightIn(min = minHeight.dp)
.fillMaxSize()
.padding(vertical = if (favoriteEntityIds.isEmpty()) 0.dp else 32.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
ListHeader(id = commonR.string.loading)
CircularProgressIndicator()
}
}
}
MainViewModel.LoadingState.ERROR -> {
MainViewModel.LoadingState.READY -> {
if (mainViewModel.entities.isEmpty()) {
item {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
ListHeader(id = commonR.string.error_loading_entities)
Chip(
label = {
Text(
text = stringResource(commonR.string.retry),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
},
onClick = onRetryLoadEntitiesClicked,
colors = ChipDefaults.primaryChipColors()
Text(
text = stringResource(commonR.string.no_supported_entities),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.title3,
modifier = Modifier.fillMaxWidth()
.padding(top = 32.dp)
)
Text(
text = stringResource(commonR.string.no_supported_entities_summary),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.body2,
modifier = Modifier.fillMaxWidth()
.padding(top = 8.dp)
)
Spacer(modifier = Modifier.height(32.dp))
}
}
}
MainViewModel.LoadingState.READY -> {
if (mainViewModel.entities.isEmpty()) {
item {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = stringResource(commonR.string.no_supported_entities),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.title3,
modifier = Modifier.fillMaxWidth()
.padding(top = 32.dp)
)
Text(
text = stringResource(commonR.string.no_supported_entities_summary),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.body2,
modifier = Modifier.fillMaxWidth()
.padding(top = 8.dp)
)
}
if (
mainViewModel.entitiesByArea.values.any {
it.isNotEmpty() && it.any { entity ->
mainViewModel.getCategoryForEntity(entity.entityId) == null &&
mainViewModel.getHiddenByForEntity(entity.entityId) == null
}
}
if (
mainViewModel.entitiesByArea.values.any {
it.isNotEmpty() && it.any { entity ->
mainViewModel.getCategoryForEntity(entity.entityId) == null &&
mainViewModel.getHiddenByForEntity(entity.entityId) == null
}
}
) {
item {
ListHeader(id = commonR.string.areas)
}
for (id in mainViewModel.entitiesByAreaOrder) {
val entities = mainViewModel.entitiesByArea[id]
val entitiesToShow = entities?.filter {
mainViewModel.getCategoryForEntity(it.entityId) == null &&
mainViewModel.getHiddenByForEntity(it.entityId) == null
}
if (!entitiesToShow.isNullOrEmpty()) {
val area = mainViewModel.areas.first { it.areaId == id }
item {
Chip(
modifier = Modifier.fillMaxWidth(),
label = {
Text(text = area.name)
},
onClick = {
onNavigationClicked(
mapOf(area.name to entities),
listOf(area.name)
) {
mainViewModel.getCategoryForEntity(it.entityId) == null &&
mainViewModel.getHiddenByForEntity(
it.entityId
) == null
}
},
colors = ChipDefaults.primaryChipColors()
)
}
}
}
) {
item {
ListHeader(id = commonR.string.areas)
}
val domainEntitiesFilter: (entity: Entity<*>) -> Boolean =
{
mainViewModel.getAreaForEntity(it.entityId) == null &&
mainViewModel.getCategoryForEntity(it.entityId) == null &&
for (id in mainViewModel.entitiesByAreaOrder) {
val entities = mainViewModel.entitiesByArea[id]
val entitiesToShow = entities?.filter {
mainViewModel.getCategoryForEntity(it.entityId) == null &&
mainViewModel.getHiddenByForEntity(it.entityId) == null
}
if (mainViewModel.entities.values.any(domainEntitiesFilter)) {
item {
ListHeader(id = commonR.string.more_entities)
}
}
// Buttons for each existing category
for (domain in mainViewModel.entitiesByDomainOrder) {
val domainEntities = mainViewModel.entitiesByDomain[domain]!!
val domainEntitiesToShow =
domainEntities.filter(domainEntitiesFilter)
if (domainEntitiesToShow.isNotEmpty()) {
if (!entitiesToShow.isNullOrEmpty()) {
val area = mainViewModel.areas.first { it.areaId == id }
item {
Chip(
modifier = Modifier.fillMaxWidth(),
icon = {
getIcon(
"",
domain,
context
).let { Image(asset = it) }
},
label = {
Text(text = mainViewModel.stringForDomain(domain)!!)
Text(text = area.name)
},
onClick = {
onNavigationClicked(
mapOf(
mainViewModel.stringForDomain(domain)!! to domainEntities
),
listOf(mainViewModel.stringForDomain(domain)!!),
domainEntitiesFilter
)
mapOf(area.name to entities),
listOf(area.name)
) {
mainViewModel.getCategoryForEntity(it.entityId) == null &&
mainViewModel.getHiddenByForEntity(
it.entityId
) == null
}
},
colors = ChipDefaults.primaryChipColors()
)
}
}
}
}
item {
Spacer(modifier = Modifier.height(32.dp))
val domainEntitiesFilter: (entity: Entity<*>) -> Boolean =
{
mainViewModel.getAreaForEntity(it.entityId) == null &&
mainViewModel.getCategoryForEntity(it.entityId) == null &&
mainViewModel.getHiddenByForEntity(it.entityId) == null
}
// All entities regardless of area
if (mainViewModel.entities.isNotEmpty()) {
if (mainViewModel.entities.values.any(domainEntitiesFilter)) {
item {
ListHeader(id = commonR.string.more_entities)
}
}
// Buttons for each existing category
for (domain in mainViewModel.entitiesByDomainOrder) {
val domainEntities = mainViewModel.entitiesByDomain[domain]!!
val domainEntitiesToShow =
domainEntities.filter(domainEntitiesFilter)
if (domainEntitiesToShow.isNotEmpty()) {
item {
Chip(
modifier = Modifier
.fillMaxWidth(),
modifier = Modifier.fillMaxWidth(),
icon = {
Image(
asset = CommunityMaterial.Icon.cmd_animation,
colorFilter = ColorFilter.tint(Color.White)
)
getIcon(
"",
domain,
context
).let { Image(asset = it) }
},
label = {
Text(text = stringResource(commonR.string.all_entities))
Text(text = mainViewModel.stringForDomain(domain)!!)
},
onClick = {
onNavigationClicked(
mainViewModel.entitiesByDomain.mapKeys {
mainViewModel.stringForDomain(
it.key
)!!
},
mainViewModel.entitiesByDomain.keys.map {
mainViewModel.stringForDomain(
it
)!!
}.sorted()
) { true }
mapOf(
mainViewModel.stringForDomain(domain)!! to domainEntities
),
listOf(mainViewModel.stringForDomain(domain)!!),
domainEntitiesFilter
)
},
colors = ChipDefaults.secondaryChipColors()
colors = ChipDefaults.primaryChipColors()
)
}
}
}
item {
Spacer(modifier = Modifier.height(32.dp))
}
// All entities regardless of area
if (mainViewModel.entities.isNotEmpty()) {
item {
Chip(
modifier = Modifier
.fillMaxWidth(),
icon = {
Image(
asset = CommunityMaterial.Icon.cmd_animation,
colorFilter = ColorFilter.tint(Color.White)
)
},
label = {
Text(text = stringResource(commonR.string.all_entities))
},
onClick = {
onNavigationClicked(
mainViewModel.entitiesByDomain.mapKeys {
mainViewModel.stringForDomain(
it.key
)!!
},
mainViewModel.entitiesByDomain.keys.map {
mainViewModel.stringForDomain(
it
)!!
}.sorted()
) { true }
},
colors = ChipDefaults.secondaryChipColors()
)
}
}
}
}
}
if (mainViewModel.isFavoritesOnly) {
item {
Spacer(Modifier.padding(32.dp))
}
}
// Settings
if (mainViewModel.isFavoritesOnly) {
item {
Chip(
modifier = Modifier
.fillMaxWidth(),
icon = {
Image(
asset = CommunityMaterial.Icon.cmd_cog,
colorFilter = ColorFilter.tint(Color.White)
)
},
label = {
Text(
text = stringResource(id = commonR.string.settings)
)
},
onClick = onSettingsClicked,
colors = ChipDefaults.secondaryChipColors()
)
Spacer(Modifier.padding(32.dp))
}
}
// Settings
item {
Chip(
modifier = Modifier
.fillMaxWidth(),
icon = {
Image(
asset = CommunityMaterial.Icon.cmd_cog,
colorFilter = ColorFilter.tint(Color.White)
)
},
label = {
Text(
text = stringResource(id = commonR.string.settings)
)
},
onClick = onSettingsClicked,
colors = ChipDefaults.secondaryChipColors()
)
}
}
}
}

View file

@ -8,11 +8,8 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.wear.compose.foundation.lazy.itemsIndexed
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.Text
import io.homeassistant.companion.android.database.wear.CameraTile
import io.homeassistant.companion.android.theme.WearAppTheme
@ -25,43 +22,33 @@ fun SelectCameraTileView(
tiles: List<CameraTile>,
onSelectTile: (tileId: Int) -> Unit
) {
val scalingLazyListState = rememberScalingLazyListState()
WearAppTheme {
Scaffold(
positionIndicator = {
if (scalingLazyListState.isScrollInProgress) {
PositionIndicator(scalingLazyListState = scalingLazyListState)
}
},
timeText = { TimeText(scalingLazyListState = scalingLazyListState) }
) {
ThemeLazyColumn(state = scalingLazyListState) {
ThemeLazyColumn {
item {
ListHeader(id = commonR.string.camera_tiles)
}
if (tiles.isEmpty()) {
item {
ListHeader(id = commonR.string.camera_tiles)
Text(
text = stringResource(commonR.string.camera_tile_no_tiles_yet),
textAlign = TextAlign.Center
)
}
if (tiles.isEmpty()) {
item {
Text(
text = stringResource(commonR.string.camera_tile_no_tiles_yet),
textAlign = TextAlign.Center
)
}
} else {
itemsIndexed(tiles, key = { _, item -> "tile.${item.id}" }) { index, tile ->
Chip(
modifier = Modifier.fillMaxWidth(),
label = {
Text(stringResource(commonR.string.camera_tile_n, index + 1))
},
secondaryLabel = if (tile.entityId != null) {
{ Text(tile.entityId!!) }
} else {
null
},
onClick = { onSelectTile(tile.id) },
colors = ChipDefaults.secondaryChipColors()
)
}
} else {
itemsIndexed(tiles, key = { _, item -> "tile.${item.id}" }) { index, tile ->
Chip(
modifier = Modifier.fillMaxWidth(),
label = {
Text(stringResource(commonR.string.camera_tile_n, index + 1))
},
secondaryLabel = if (tile.entityId != null) {
{ Text(tile.entityId!!) }
} else {
null
},
onClick = { onSelectTile(tile.id) },
colors = ChipDefaults.secondaryChipColors()
)
}
}
}

View file

@ -9,12 +9,9 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.wear.compose.foundation.lazy.itemsIndexed
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.ToggleChip
import androidx.wear.compose.material.ToggleChipDefaults
@ -33,76 +30,66 @@ fun SelectShortcutsTileView(
isShowShortcutTextEnabled: Boolean,
onShowShortcutTextEnabled: (Boolean) -> Unit
) {
val scalingLazyListState = rememberScalingLazyListState()
WearAppTheme {
Scaffold(
positionIndicator = {
if (scalingLazyListState.isScrollInProgress) {
PositionIndicator(scalingLazyListState = scalingLazyListState)
}
},
timeText = { TimeText(scalingLazyListState = scalingLazyListState) }
) {
ThemeLazyColumn(state = scalingLazyListState) {
item {
ListHeader(id = commonR.string.shortcut_tiles)
}
item {
ToggleChip(
modifier = Modifier.fillMaxWidth(),
checked = isShowShortcutTextEnabled,
onCheckedChange = { onShowShortcutTextEnabled(it) },
label = {
Text(stringResource(commonR.string.shortcuts_tile_text_setting))
},
appIcon = {
Image(
asset =
if (isShowShortcutTextEnabled) {
CommunityMaterial.Icon.cmd_alphabetical
} else {
CommunityMaterial.Icon.cmd_alphabetical_off
},
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
toggleControl = {
Icon(
imageVector = ToggleChipDefaults.checkboxIcon(isShowShortcutTextEnabled),
contentDescription = if (isShowShortcutTextEnabled) {
stringResource(commonR.string.show)
} else {
stringResource(commonR.string.hide)
}
)
}
)
}
item {
ListHeader(id = commonR.string.shortcuts_tile_select)
}
if (shortcutTileEntitiesCountById.isEmpty()) {
item {
Text(stringResource(commonR.string.shortcuts_tile_no_tiles_yet))
}
} else {
itemsIndexed(shortcutTileEntitiesCountById.keys.toList()) { index, shortcutsTileId ->
Chip(
modifier = Modifier
.fillMaxWidth(),
label = {
Text(stringResource(commonR.string.shortcuts_tile_n, index + 1))
ThemeLazyColumn {
item {
ListHeader(id = commonR.string.shortcut_tiles)
}
item {
ToggleChip(
modifier = Modifier.fillMaxWidth(),
checked = isShowShortcutTextEnabled,
onCheckedChange = { onShowShortcutTextEnabled(it) },
label = {
Text(stringResource(commonR.string.shortcuts_tile_text_setting))
},
appIcon = {
Image(
asset =
if (isShowShortcutTextEnabled) {
CommunityMaterial.Icon.cmd_alphabetical
} else {
CommunityMaterial.Icon.cmd_alphabetical_off
},
secondaryLabel = {
val entityCount = shortcutTileEntitiesCountById[shortcutsTileId] ?: 0
if (entityCount > 0) {
Text(pluralStringResource(commonR.plurals.n_entities, entityCount, entityCount))
}
},
onClick = { onSelectShortcutsTile(shortcutsTileId) },
colors = ChipDefaults.secondaryChipColors()
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
toggleControl = {
Icon(
imageVector = ToggleChipDefaults.checkboxIcon(isShowShortcutTextEnabled),
contentDescription = if (isShowShortcutTextEnabled) {
stringResource(commonR.string.show)
} else {
stringResource(commonR.string.hide)
}
)
}
)
}
item {
ListHeader(id = commonR.string.shortcuts_tile_select)
}
if (shortcutTileEntitiesCountById.isEmpty()) {
item {
Text(stringResource(commonR.string.shortcuts_tile_no_tiles_yet))
}
} else {
itemsIndexed(shortcutTileEntitiesCountById.keys.toList()) { index, shortcutsTileId ->
Chip(
modifier = Modifier
.fillMaxWidth(),
label = {
Text(stringResource(commonR.string.shortcuts_tile_n, index + 1))
},
secondaryLabel = {
val entityCount = shortcutTileEntitiesCountById[shortcutsTileId] ?: 0
if (entityCount > 0) {
Text(pluralStringResource(commonR.plurals.n_entities, entityCount, entityCount))
}
},
onClick = { onSelectShortcutsTile(shortcutsTileId) },
colors = ChipDefaults.secondaryChipColors()
)
}
}
}

View file

@ -11,10 +11,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.CircularProgressIndicator
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import io.homeassistant.companion.android.common.R
import io.homeassistant.companion.android.common.sensors.SensorManager
import io.homeassistant.companion.android.database.sensor.Sensor
@ -31,54 +28,42 @@ fun SensorManagerUi(
sensorManager: SensorManager,
onSensorClicked: (String, Boolean) -> Unit
) {
val scalingLazyListState = rememberScalingLazyListState()
WearAppTheme {
Scaffold(
positionIndicator = {
if (scalingLazyListState.isScrollInProgress) {
PositionIndicator(scalingLazyListState = scalingLazyListState)
}
},
timeText = { TimeText(scalingLazyListState = scalingLazyListState) }
) {
ThemeLazyColumn(
state = scalingLazyListState
) {
item {
ListHeader(id = sensorManager.name)
}
val currentSensors = allSensors?.filter { sensor ->
allAvailSensors?.firstOrNull { availableSensor ->
sensor.id == availableSensor.id
} != null
}
ThemeLazyColumn {
item {
ListHeader(id = sensorManager.name)
}
val currentSensors = allSensors?.filter { sensor ->
allAvailSensors?.firstOrNull { availableSensor ->
sensor.id == availableSensor.id
} != null
}
if (allAvailSensors?.isEmpty() == true) {
item {
Column(
modifier = Modifier
.fillMaxSize()
.padding(vertical = 32.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
ListHeader(id = R.string.loading)
CircularProgressIndicator()
}
if (allAvailSensors?.isEmpty() == true) {
item {
Column(
modifier = Modifier
.fillMaxSize()
.padding(vertical = 32.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
ListHeader(id = R.string.loading)
CircularProgressIndicator()
}
} else {
allAvailSensors?.size?.let { int ->
items(int, { allAvailSensors[it].id }) { index ->
val basicSensor = allAvailSensors[index]
val sensor = currentSensors?.firstOrNull { sensor ->
sensor.id == basicSensor.id
}
SensorUi(
sensor = sensor,
manager = sensorManager,
basicSensor = basicSensor
) { sensorId, enabled -> onSensorClicked(sensorId, enabled) }
}
} else {
allAvailSensors?.size?.let { int ->
items(int, { allAvailSensors[it].id }) { index ->
val basicSensor = allAvailSensors[index]
val sensor = currentSensors?.firstOrNull { sensor ->
sensor.id == basicSensor.id
}
SensorUi(
sensor = sensor,
manager = sensorManager,
basicSensor = basicSensor
) { sensorId, enabled -> onSensorClicked(sensorId, enabled) }
}
}
}

View file

@ -9,11 +9,8 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.Text
import io.homeassistant.companion.android.common.sensors.SensorManager
import io.homeassistant.companion.android.sensors.SensorReceiver
@ -26,39 +23,26 @@ import io.homeassistant.companion.android.common.R as commonR
fun SensorsView(
onClickSensorManager: (SensorManager) -> Unit
) {
val scalingLazyListState = rememberScalingLazyListState()
WearAppTheme {
Scaffold(
positionIndicator = {
if (scalingLazyListState.isScrollInProgress) {
PositionIndicator(scalingLazyListState = scalingLazyListState)
}
},
timeText = { TimeText(scalingLazyListState = scalingLazyListState) }
) {
val sensorManagers = getSensorManagers()
ThemeLazyColumn(
state = scalingLazyListState
) {
item {
ListHeader(id = commonR.string.sensors)
}
items(sensorManagers.size, { sensorManagers[it].name }) { index ->
val manager = sensorManagers[index]
Row {
Chip(
modifier = Modifier
.fillMaxWidth(),
colors = ChipDefaults.secondaryChipColors(),
label = {
Text(
text = stringResource(manager.name)
)
},
onClick = { onClickSensorManager(manager) }
)
}
val sensorManagers = getSensorManagers()
ThemeLazyColumn {
item {
ListHeader(id = commonR.string.sensors)
}
items(sensorManagers.size, { sensorManagers[it].name }) { index ->
val manager = sensorManagers[index]
Row {
Chip(
modifier = Modifier
.fillMaxWidth(),
colors = ChipDefaults.secondaryChipColors(),
label = {
Text(
text = stringResource(manager.name)
)
},
onClick = { onClickSensorManager(manager) }
)
}
}
}

View file

@ -6,11 +6,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.Text
import com.mikepenz.iconics.compose.Image
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
@ -34,69 +31,59 @@ fun SetCameraTileView(
onSelectEntity: () -> Unit,
onSelectRefreshInterval: () -> Unit
) {
val scalingLazyListState = rememberScalingLazyListState()
WearAppTheme {
Scaffold(
positionIndicator = {
if (scalingLazyListState.isScrollInProgress) {
PositionIndicator(scalingLazyListState = scalingLazyListState)
}
},
timeText = { TimeText(scalingLazyListState = scalingLazyListState) }
) {
ThemeLazyColumn(state = scalingLazyListState) {
item {
ListHeader(commonR.string.camera_tile)
}
item {
val entity = tile?.entityId?.let { tileEntityId ->
entities?.firstOrNull { it.entityId == tileEntityId }
}
val icon = entity?.getIcon(LocalContext.current) ?: CommunityMaterial.Icon3.cmd_video
Chip(
modifier = Modifier.fillMaxWidth(),
icon = {
Image(
asset = icon,
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
colors = ChipDefaults.secondaryChipColors(),
label = {
Text(
text = stringResource(id = R.string.choose_entity)
)
},
secondaryLabel = {
Text(entity?.friendlyName ?: tile?.entityId ?: "")
},
onClick = onSelectEntity
)
ThemeLazyColumn {
item {
ListHeader(commonR.string.camera_tile)
}
item {
val entity = tile?.entityId?.let { tileEntityId ->
entities?.firstOrNull { it.entityId == tileEntityId }
}
val icon = entity?.getIcon(LocalContext.current) ?: CommunityMaterial.Icon3.cmd_video
Chip(
modifier = Modifier.fillMaxWidth(),
icon = {
Image(
asset = icon,
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
colors = ChipDefaults.secondaryChipColors(),
label = {
Text(
text = stringResource(id = R.string.choose_entity)
)
},
secondaryLabel = {
Text(entity?.friendlyName ?: tile?.entityId ?: "")
},
onClick = onSelectEntity
)
}
item {
Chip(
modifier = Modifier.fillMaxWidth(),
icon = {
Image(
asset = CommunityMaterial.Icon3.cmd_timer_cog,
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
colors = ChipDefaults.secondaryChipColors(),
label = {
Text(
text = stringResource(id = R.string.refresh_interval)
)
},
secondaryLabel = {
Text(
intervalToString(LocalContext.current, (tile?.refreshInterval ?: DEFAULT_REFRESH_INTERVAL).toInt())
)
},
onClick = onSelectRefreshInterval
)
}
item {
Chip(
modifier = Modifier.fillMaxWidth(),
icon = {
Image(
asset = CommunityMaterial.Icon3.cmd_timer_cog,
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
colors = ChipDefaults.secondaryChipColors(),
label = {
Text(
text = stringResource(id = R.string.refresh_interval)
)
},
secondaryLabel = {
Text(
intervalToString(LocalContext.current, (tile?.refreshInterval ?: DEFAULT_REFRESH_INTERVAL).toInt())
)
},
onClick = onSelectRefreshInterval
)
}
}
}

View file

@ -8,10 +8,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.wear.compose.foundation.lazy.items
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.ToggleChip
import androidx.wear.compose.material.ToggleChipDefaults
@ -36,42 +33,29 @@ fun SetFavoritesView(
// Remember expanded state of each header
val expandedStates = rememberExpandedStates(mainViewModel.supportedDomains())
val scalingLazyListState = rememberScalingLazyListState()
WearAppTheme {
Scaffold(
positionIndicator = {
if (scalingLazyListState.isScrollInProgress) {
PositionIndicator(scalingLazyListState = scalingLazyListState)
}
},
timeText = { TimeText(scalingLazyListState = scalingLazyListState) }
) {
ThemeLazyColumn(
state = scalingLazyListState
) {
item {
ListHeader(id = commonR.string.set_favorite)
}
for (domain in mainViewModel.entitiesByDomainOrder) {
val entities = mainViewModel.entitiesByDomain[domain].orEmpty()
if (entities.isNotEmpty()) {
item {
ExpandableListHeader(
string = mainViewModel.stringForDomain(domain)!!,
key = domain,
expandedStates = expandedStates
ThemeLazyColumn {
item {
ListHeader(id = commonR.string.set_favorite)
}
for (domain in mainViewModel.entitiesByDomainOrder) {
val entities = mainViewModel.entitiesByDomain[domain].orEmpty()
if (entities.isNotEmpty()) {
item {
ExpandableListHeader(
string = mainViewModel.stringForDomain(domain)!!,
key = domain,
expandedStates = expandedStates
)
}
if (expandedStates[domain] == true) {
items(entities, key = { it.entityId }) { entity ->
FavoriteToggleChip(
entity = entity,
favoriteEntityIds = favoriteEntityIds,
onFavoriteSelected = onFavoriteSelected
)
}
if (expandedStates[domain] == true) {
items(entities, key = { it.entityId }) { entity ->
FavoriteToggleChip(
entity = entity,
favoriteEntityIds = favoriteEntityIds,
onFavoriteSelected = onFavoriteSelected
)
}
}
}
}
}

View file

@ -12,13 +12,10 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Button
import androidx.wear.compose.material.ButtonDefaults
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.Text
import com.mikepenz.iconics.compose.Image
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
@ -35,64 +32,54 @@ fun SetShortcutsTileView(
shortcutEntities: List<SimplifiedEntity>,
onShortcutEntitySelectionChange: (Int) -> Unit
) {
val scalingLazyListState = rememberScalingLazyListState()
WearAppTheme {
Scaffold(
positionIndicator = {
if (scalingLazyListState.isScrollInProgress) {
PositionIndicator(scalingLazyListState = scalingLazyListState)
}
},
timeText = { TimeText(scalingLazyListState = scalingLazyListState) }
) {
ThemeLazyColumn(state = scalingLazyListState) {
ThemeLazyColumn {
item {
ListHeader(id = commonR.string.shortcuts_choose)
}
items(shortcutEntities.size) { index ->
val iconBitmap = getIcon(
shortcutEntities[index].icon,
shortcutEntities[index].domain,
LocalContext.current
)
Chip(
modifier = Modifier
.fillMaxWidth(),
icon = {
Image(
iconBitmap,
colorFilter = ColorFilter.tint(Color.White)
)
},
label = {
Text(
text = stringResource(commonR.string.shortcut_n, index + 1)
)
},
secondaryLabel = {
Text(
text = shortcutEntities[index].friendlyName,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
},
onClick = { onShortcutEntitySelectionChange(index) },
colors = ChipDefaults.secondaryChipColors()
)
}
if (shortcutEntities.size < 7) {
item {
ListHeader(id = commonR.string.shortcuts_choose)
}
items(shortcutEntities.size) { index ->
val iconBitmap = getIcon(
shortcutEntities[index].icon,
shortcutEntities[index].domain,
LocalContext.current
)
Chip(
modifier = Modifier
.fillMaxWidth(),
icon = {
Image(
iconBitmap,
colorFilter = ColorFilter.tint(Color.White)
)
},
label = {
Text(
text = stringResource(commonR.string.shortcut_n, index + 1)
)
},
secondaryLabel = {
Text(
text = shortcutEntities[index].friendlyName,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
},
onClick = { onShortcutEntitySelectionChange(index) },
colors = ChipDefaults.secondaryChipColors()
)
}
if (shortcutEntities.size < 7) {
item {
Button(
modifier = Modifier.padding(top = 16.dp),
onClick = { onShortcutEntitySelectionChange(shortcutEntities.size) },
colors = ButtonDefaults.primaryButtonColors()
) {
Image(
CommunityMaterial.Icon3.cmd_plus_thick
)
}
Button(
modifier = Modifier.padding(top = 16.dp),
onClick = { onShortcutEntitySelectionChange(shortcutEntities.size) },
colors = ButtonDefaults.primaryButtonColors()
) {
Image(
CommunityMaterial.Icon3.cmd_plus_thick
)
}
}
}

View file

@ -10,12 +10,9 @@ import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.ToggleChip
import androidx.wear.compose.material.ToggleChipDefaults
@ -77,237 +74,224 @@ fun SettingsView(
onClickTemplateTile: () -> Unit,
onAssistantAppAllowed: (Boolean) -> Unit
) {
val scalingLazyListState = rememberScalingLazyListState()
WearAppTheme {
Scaffold(
positionIndicator = {
if (scalingLazyListState.isScrollInProgress) {
PositionIndicator(scalingLazyListState = scalingLazyListState)
}
},
timeText = { TimeText(scalingLazyListState = scalingLazyListState) }
) {
ThemeLazyColumn(
state = scalingLazyListState
) {
item {
ListHeader(id = commonR.string.favorite_settings)
}
item {
SecondarySettingsChip(
icon = CommunityMaterial.Icon3.cmd_star,
label = stringResource(commonR.string.favorite),
enabled = loadingState == MainViewModel.LoadingState.READY,
onClick = onClickSetFavorites
)
}
item {
SecondarySettingsChip(
icon = CommunityMaterial.Icon.cmd_delete,
label = stringResource(commonR.string.clear_favorites),
secondaryLabel = stringResource(commonR.string.irreversible),
enabled = favorites.isNotEmpty(),
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
)
}
item {
val haptic = LocalHapticFeedback.current
ToggleChip(
modifier = Modifier.fillMaxWidth(),
checked = isHapticEnabled,
onCheckedChange = {
onHapticEnabled(it)
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
},
label = {
Text(stringResource(commonR.string.setting_haptic_label))
},
appIcon = {
Image(
asset =
if (isHapticEnabled) {
CommunityMaterial.Icon3.cmd_watch_vibrate
} else {
CommunityMaterial.Icon3.cmd_watch_vibrate_off
},
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
toggleControl = {
Icon(
imageVector = ToggleChipDefaults.checkboxIcon(isHapticEnabled),
contentDescription = if (isHapticEnabled) {
stringResource(commonR.string.enabled)
} else {
stringResource(commonR.string.disabled)
}
)
}
)
}
item {
ToggleChip(
modifier = Modifier.fillMaxWidth(),
checked = isToastEnabled,
onCheckedChange = onToastEnabled,
label = {
Text(stringResource(commonR.string.setting_toast_label))
},
appIcon = {
Image(
asset =
if (isToastEnabled) {
CommunityMaterial.Icon3.cmd_message
} else {
CommunityMaterial.Icon3.cmd_message_off
},
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
toggleControl = {
Icon(
imageVector = ToggleChipDefaults.checkboxIcon(isToastEnabled),
contentDescription = if (isHapticEnabled) {
stringResource(commonR.string.enabled)
} else {
stringResource(commonR.string.disabled)
}
)
}
)
}
item {
ListHeader(
id = commonR.string.tile_settings
)
}
item {
SecondarySettingsChip(
icon = CommunityMaterial.Icon3.cmd_video_box,
label = stringResource(commonR.string.camera_tiles),
onClick = onClickCameraTile
)
}
item {
SecondarySettingsChip(
icon = CommunityMaterial.Icon3.cmd_star_circle_outline,
label = stringResource(commonR.string.shortcut_tiles),
onClick = onClickSetShortcuts
)
}
item {
SecondarySettingsChip(
icon = CommunityMaterial.Icon3.cmd_text_box,
label = stringResource(commonR.string.template_tile),
onClick = onClickTemplateTile
)
}
item {
ListHeader(
id = commonR.string.sensors
)
}
item {
SecondarySettingsChip(
icon = CommunityMaterial.Icon2.cmd_leak,
label = stringResource(id = commonR.string.sensor_title),
onClick = onClickSensors
)
}
item {
ListHeader(
id = commonR.string.assist
)
}
item {
ToggleChip(
modifier = Modifier.fillMaxWidth(),
checked = isAssistantAppAllowed,
onCheckedChange = onAssistantAppAllowed,
label = {
Text(stringResource(commonR.string.available_as_assistant_app))
},
appIcon = {
Image(
asset = CommunityMaterial.Icon.cmd_comment_processing_outline,
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
toggleControl = {
Icon(
imageVector = ToggleChipDefaults.switchIcon(isAssistantAppAllowed),
contentDescription = if (isFavoritesOnly) {
stringResource(commonR.string.enabled)
} else {
stringResource(commonR.string.disabled)
}
)
}
)
}
item {
ListHeader(
id = commonR.string.account
)
}
item {
Chip(
modifier = Modifier.fillMaxWidth(),
icon = {
Image(asset = CommunityMaterial.Icon.cmd_exit_run)
},
label = {
Text(
text = stringResource(id = commonR.string.logout)
)
},
onClick = onClickLogout,
colors = ChipDefaults.primaryChipColors(
backgroundColor = Color.Red,
contentColor = Color.Black
ThemeLazyColumn {
item {
ListHeader(id = commonR.string.favorite_settings)
}
item {
SecondarySettingsChip(
icon = CommunityMaterial.Icon3.cmd_star,
label = stringResource(commonR.string.favorite),
enabled = loadingState == MainViewModel.LoadingState.READY,
onClick = onClickSetFavorites
)
}
item {
SecondarySettingsChip(
icon = CommunityMaterial.Icon.cmd_delete,
label = stringResource(commonR.string.clear_favorites),
secondaryLabel = stringResource(commonR.string.irreversible),
enabled = favorites.isNotEmpty(),
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
)
}
item {
val haptic = LocalHapticFeedback.current
ToggleChip(
modifier = Modifier.fillMaxWidth(),
checked = isHapticEnabled,
onCheckedChange = {
onHapticEnabled(it)
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
},
label = {
Text(stringResource(commonR.string.setting_haptic_label))
},
appIcon = {
Image(
asset =
if (isHapticEnabled) {
CommunityMaterial.Icon3.cmd_watch_vibrate
} else {
CommunityMaterial.Icon3.cmd_watch_vibrate_off
},
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
toggleControl = {
Icon(
imageVector = ToggleChipDefaults.checkboxIcon(isHapticEnabled),
contentDescription = if (isHapticEnabled) {
stringResource(commonR.string.enabled)
} else {
stringResource(commonR.string.disabled)
}
)
}
)
}
item {
ToggleChip(
modifier = Modifier.fillMaxWidth(),
checked = isToastEnabled,
onCheckedChange = onToastEnabled,
label = {
Text(stringResource(commonR.string.setting_toast_label))
},
appIcon = {
Image(
asset =
if (isToastEnabled) {
CommunityMaterial.Icon3.cmd_message
} else {
CommunityMaterial.Icon3.cmd_message_off
},
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
toggleControl = {
Icon(
imageVector = ToggleChipDefaults.checkboxIcon(isToastEnabled),
contentDescription = if (isHapticEnabled) {
stringResource(commonR.string.enabled)
} else {
stringResource(commonR.string.disabled)
}
)
}
)
}
item {
ListHeader(
id = commonR.string.tile_settings
)
}
item {
SecondarySettingsChip(
icon = CommunityMaterial.Icon3.cmd_video_box,
label = stringResource(commonR.string.camera_tiles),
onClick = onClickCameraTile
)
}
item {
SecondarySettingsChip(
icon = CommunityMaterial.Icon3.cmd_star_circle_outline,
label = stringResource(commonR.string.shortcut_tiles),
onClick = onClickSetShortcuts
)
}
item {
SecondarySettingsChip(
icon = CommunityMaterial.Icon3.cmd_text_box,
label = stringResource(commonR.string.template_tile),
onClick = onClickTemplateTile
)
}
item {
ListHeader(
id = commonR.string.sensors
)
}
item {
SecondarySettingsChip(
icon = CommunityMaterial.Icon2.cmd_leak,
label = stringResource(id = commonR.string.sensor_title),
onClick = onClickSensors
)
}
item {
ListHeader(
id = commonR.string.assist
)
}
item {
ToggleChip(
modifier = Modifier.fillMaxWidth(),
checked = isAssistantAppAllowed,
onCheckedChange = onAssistantAppAllowed,
label = {
Text(stringResource(commonR.string.available_as_assistant_app))
},
appIcon = {
Image(
asset = CommunityMaterial.Icon.cmd_comment_processing_outline,
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
toggleControl = {
Icon(
imageVector = ToggleChipDefaults.switchIcon(isAssistantAppAllowed),
contentDescription = if (isFavoritesOnly) {
stringResource(commonR.string.enabled)
} else {
stringResource(commonR.string.disabled)
}
)
}
)
}
item {
ListHeader(
id = commonR.string.account
)
}
item {
Chip(
modifier = Modifier.fillMaxWidth(),
icon = {
Image(asset = CommunityMaterial.Icon.cmd_exit_run)
},
label = {
Text(
text = stringResource(id = commonR.string.logout)
)
},
onClick = onClickLogout,
colors = ChipDefaults.primaryChipColors(
backgroundColor = Color.Red,
contentColor = Color.Black
)
}
item {
ListHeader(commonR.string.application_version)
}
item {
Text(
text = BuildConfig.VERSION_NAME
)
}
)
}
item {
ListHeader(commonR.string.application_version)
}
item {
Text(
text = BuildConfig.VERSION_NAME
)
}
}
}

View file

@ -10,11 +10,8 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.Text
import com.mikepenz.iconics.compose.Image
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
@ -31,52 +28,42 @@ fun TemplateTileSettingsView(
refreshInterval: Int,
onClickRefreshInterval: () -> Unit
) {
val scalingLazyListState = rememberScalingLazyListState()
WearAppTheme {
Scaffold(
positionIndicator = {
if (scalingLazyListState.isScrollInProgress) {
PositionIndicator(scalingLazyListState = scalingLazyListState)
}
},
timeText = { TimeText(scalingLazyListState = scalingLazyListState) }
) {
ThemeLazyColumn(state = scalingLazyListState) {
item {
ListHeader(id = R.string.template_tile)
}
item {
Chip(
modifier = Modifier
.fillMaxWidth(),
icon = {
Image(
asset = CommunityMaterial.Icon3.cmd_timer_cog,
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
colors = ChipDefaults.secondaryChipColors(),
label = {
Text(
text = stringResource(id = R.string.refresh_interval)
)
},
secondaryLabel = { Text(intervalToString(LocalContext.current, refreshInterval)) },
onClick = onClickRefreshInterval
)
}
item {
ListHeader(R.string.template_tile_content)
}
item {
Text(stringResource(R.string.template_tile_change_message))
}
item {
Text(
templateContent,
color = Color.DarkGray
)
}
ThemeLazyColumn {
item {
ListHeader(id = R.string.template_tile)
}
item {
Chip(
modifier = Modifier
.fillMaxWidth(),
icon = {
Image(
asset = CommunityMaterial.Icon3.cmd_timer_cog,
colorFilter = ColorFilter.tint(wearColorPalette.onSurface)
)
},
colors = ChipDefaults.secondaryChipColors(),
label = {
Text(
text = stringResource(id = R.string.refresh_interval)
)
},
secondaryLabel = { Text(intervalToString(LocalContext.current, refreshInterval)) },
onClick = onClickRefreshInterval
)
}
item {
ListHeader(R.string.template_tile_content)
}
item {
Text(stringResource(R.string.template_tile_change_message))
}
item {
Text(
templateContent,
color = Color.DarkGray
)
}
}
}

View file

@ -12,15 +12,11 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Button
import androidx.wear.compose.material.ButtonDefaults
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.Text
import io.homeassistant.companion.android.R
import io.homeassistant.companion.android.home.views.TimeText
import io.homeassistant.companion.android.views.ThemeLazyColumn
import io.homeassistant.companion.android.common.R as commonR
@ -30,58 +26,48 @@ fun PhoneInstallView(
onRefresh: () -> Unit,
onAdvanced: () -> Unit
) {
val scrollState = rememberScalingLazyListState()
Scaffold(
positionIndicator = {
if (scrollState.isScrollInProgress) {
PositionIndicator(scalingLazyListState = scrollState)
ThemeLazyColumn {
item {
Image(
painter = painterResource(R.drawable.app_icon),
contentDescription = null,
modifier = Modifier.size(48.dp)
)
}
item {
Text(
text = stringResource(commonR.string.install_phone_to_continue),
style = MaterialTheme.typography.title3,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth().padding(vertical = 16.dp)
)
}
item {
Button(
onClick = onInstall,
modifier = Modifier.fillMaxWidth()
) {
Text(stringResource(commonR.string.install))
}
},
timeText = { TimeText(scalingLazyListState = scrollState) }
) {
ThemeLazyColumn(state = scrollState) {
item {
Image(
painter = painterResource(R.drawable.app_icon),
contentDescription = null,
modifier = Modifier.size(48.dp)
)
}
item {
Button(
onClick = onRefresh,
modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.secondaryButtonColors()
) {
Text(stringResource(commonR.string.refresh))
}
item {
Text(
text = stringResource(commonR.string.install_phone_to_continue),
style = MaterialTheme.typography.title3,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth().padding(vertical = 16.dp)
)
}
item {
Button(
onClick = onInstall,
modifier = Modifier.fillMaxWidth()
) {
Text(stringResource(commonR.string.install))
}
}
item {
Button(
onClick = onRefresh,
modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.secondaryButtonColors()
) {
Text(stringResource(commonR.string.refresh))
}
}
item {
Button(
onClick = onAdvanced,
modifier = Modifier
.fillMaxWidth()
.padding(top = 16.dp),
colors = ButtonDefaults.secondaryButtonColors()
) {
Text(stringResource(commonR.string.advanced))
}
}
item {
Button(
onClick = onAdvanced,
modifier = Modifier
.fillMaxWidth()
.padding(top = 16.dp),
colors = ButtonDefaults.secondaryButtonColors()
) {
Text(stringResource(commonR.string.advanced))
}
}
}

View file

@ -11,8 +11,11 @@ import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
import androidx.wear.compose.foundation.lazy.ScalingLazyListScope
import androidx.wear.compose.foundation.lazy.ScalingLazyListState
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.compose.rotaryinput.rotaryWithScroll
import io.homeassistant.companion.android.home.views.TimeText
@OptIn(ExperimentalHorologistApi::class)
@Composable
@ -20,17 +23,26 @@ fun ThemeLazyColumn(
state: ScalingLazyListState = rememberScalingLazyListState(),
content: ScalingLazyListScope.() -> Unit
) {
ScalingLazyColumn(
modifier = Modifier
.fillMaxSize()
.rotaryWithScroll(state),
contentPadding = PaddingValues(
start = 8.dp,
end = 8.dp
),
verticalArrangement = Arrangement.spacedBy(4.dp),
horizontalAlignment = Alignment.CenterHorizontally,
state = state,
content = content
)
Scaffold(
positionIndicator = {
if (state.isScrollInProgress) {
PositionIndicator(scalingLazyListState = state)
}
},
timeText = { TimeText(scalingLazyListState = state) }
) {
ScalingLazyColumn(
modifier = Modifier
.fillMaxSize()
.rotaryWithScroll(state),
contentPadding = PaddingValues(
start = 8.dp,
end = 8.dp
),
verticalArrangement = Arrangement.spacedBy(4.dp),
horizontalAlignment = Alignment.CenterHorizontally,
state = state,
content = content
)
}
}