diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index a8abd4fbd92..8cbb83da645 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -605,6 +605,11 @@ Sharing logs with the Home Assistant team will help to solve issues. Please share the logs only if you have been asked to do so by a Home Assistant developer Show and Share Logs Sign in on phone + %1$s decreased + %1$s increased + Fan speed + Brightness + Color temperature Skip Speed: %1$d%% Auto diff --git a/wear/src/main/java/io/homeassistant/companion/android/home/views/DetailsPanelView.kt b/wear/src/main/java/io/homeassistant/companion/android/home/views/DetailsPanelView.kt index f24b029a506..60dd601cdb9 100644 --- a/wear/src/main/java/io/homeassistant/companion/android/home/views/DetailsPanelView.kt +++ b/wear/src/main/java/io/homeassistant/companion/android/home/views/DetailsPanelView.kt @@ -1,5 +1,6 @@ package io.homeassistant.companion.android.home.views +import android.content.Context import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth @@ -10,6 +11,9 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.hapticfeedback.HapticFeedback +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.wear.compose.material.InlineSlider @@ -30,6 +34,8 @@ import io.homeassistant.companion.android.common.data.integration.supportsLightC import io.homeassistant.companion.android.home.HomePresenterImpl import io.homeassistant.companion.android.theme.WearAppTheme import io.homeassistant.companion.android.util.getColorTemperature +import io.homeassistant.companion.android.util.onEntityClickedFeedback +import io.homeassistant.companion.android.util.onEntityFeedback import java.text.DateFormat @Composable @@ -38,8 +44,13 @@ fun DetailsPanelView( onEntityToggled: (String, String) -> Unit, onFanSpeedChanged: (Float) -> Unit, onBrightnessChanged: (Float) -> Unit, - onColorTempChanged: (Float) -> Unit + onColorTempChanged: (Float) -> Unit, + isToastEnabled: Boolean, + isHapticEnabled: Boolean ) { + val haptic = LocalHapticFeedback.current + val context = LocalContext.current + WearAppTheme { ThemeLazyColumn { val attributes = entity.attributes as Map<*, *> @@ -55,7 +66,16 @@ fun DetailsPanelView( val isChecked = entity.state in listOf("on", "locked", "open", "opening") ToggleButton( checked = isChecked, - onCheckedChange = { onEntityToggled(entity.entityId, entity.state) }, + onCheckedChange = { + onEntityToggled(entity.entityId, entity.state) + onEntityClickedFeedback( + isToastEnabled, + isHapticEnabled, + context, + friendlyName, + haptic + ) + }, modifier = Modifier .padding(start = 16.dp) .size(ToggleButtonDefaults.SmallToggleButtonSize) @@ -69,20 +89,20 @@ fun DetailsPanelView( if (entity.domain == "fan") { if (entity.supportsFanSetSpeed()) { item { - FanSpeedSlider(attributes, onFanSpeedChanged) + FanSpeedSlider(attributes, onFanSpeedChanged, isToastEnabled, isHapticEnabled) } } } if (entity.domain == "light") { if (entity.supportsLightBrightness()) { item { - BrightnessSlider(attributes, onBrightnessChanged) + BrightnessSlider(attributes, onBrightnessChanged, isToastEnabled, isHapticEnabled) } } if (entity.supportsLightColorTemperature() && attributes["color_mode"] == EntityExt.LIGHT_MODE_COLOR_TEMP) { item { - ColorTempSlider(attributes, onColorTempChanged) + ColorTempSlider(attributes, onColorTempChanged, isToastEnabled, isHapticEnabled) } } } @@ -129,7 +149,15 @@ fun DetailsPanelView( } @Composable -fun FanSpeedSlider(attributes: Map<*, *>, onFanSpeedChanged: (Float) -> Unit) { +fun FanSpeedSlider( + attributes: Map<*, *>, + onFanSpeedChanged: (Float) -> Unit, + isToastEnabled: Boolean, + isHapticEnabled: Boolean +) { + val haptic = LocalHapticFeedback.current + val context = LocalContext.current + val minValue = 0f val maxValue = 100f var currentValue = (attributes["percentage"] as? Number)?.toFloat() ?: 0f @@ -147,7 +175,17 @@ fun FanSpeedSlider(attributes: Map<*, *>, onFanSpeedChanged: (Float) -> Unit) { ) InlineSlider( value = currentValue, - onValueChange = onFanSpeedChanged, + onValueChange = { + onFanSpeedChanged(it) + onSliderChangedFeedback( + isToastEnabled, + isHapticEnabled, + it > currentValue, + context.getString(R.string.slider_fan_speed), + context, + haptic + ) + }, steps = 9, valueRange = minValue..maxValue, decreaseIcon = { @@ -168,7 +206,15 @@ fun FanSpeedSlider(attributes: Map<*, *>, onFanSpeedChanged: (Float) -> Unit) { } @Composable -fun BrightnessSlider(attributes: Map<*, *>, onBrightnessChanged: (Float) -> Unit) { +fun BrightnessSlider( + attributes: Map<*, *>, + onBrightnessChanged: (Float) -> Unit, + isToastEnabled: Boolean, + isHapticEnabled: Boolean +) { + val haptic = LocalHapticFeedback.current + val context = LocalContext.current + val minValue = 0f val maxValue = 100f var currentValue = @@ -190,6 +236,14 @@ fun BrightnessSlider(attributes: Map<*, *>, onBrightnessChanged: (Float) -> Unit value = currentValue, onValueChange = { brightness -> onBrightnessChanged(brightness.div(100).times(255)) + onSliderChangedFeedback( + isToastEnabled, + isHapticEnabled, + brightness > currentValue, + context.getString(R.string.slider_light_brightness), + context, + haptic + ) }, steps = 20, valueRange = minValue..maxValue, @@ -211,7 +265,15 @@ fun BrightnessSlider(attributes: Map<*, *>, onBrightnessChanged: (Float) -> Unit } @Composable -fun ColorTempSlider(attributes: Map<*, *>, onColorTempChanged: (Float) -> Unit) { +fun ColorTempSlider( + attributes: Map<*, *>, + onColorTempChanged: (Float) -> Unit, + isToastEnabled: Boolean, + isHapticEnabled: Boolean +) { + val haptic = LocalHapticFeedback.current + val context = LocalContext.current + val minValue = (attributes["min_mireds"] as? Number)?.toFloat() ?: 0f val maxValue = (attributes["max_mireds"] as? Number)?.toFloat() ?: 0f var currentValue = (attributes["color_temp"] as? Number)?.toFloat() ?: 0f @@ -229,7 +291,17 @@ fun ColorTempSlider(attributes: Map<*, *>, onColorTempChanged: (Float) -> Unit) ) InlineSlider( value = currentValue, - onValueChange = onColorTempChanged, + onValueChange = { + onColorTempChanged(it) + onSliderChangedFeedback( + isToastEnabled, + isHapticEnabled, + it > currentValue, + context.getString(R.string.slider_light_colortemp), + context, + haptic + ) + }, steps = 20, valueRange = minValue..maxValue, decreaseIcon = { @@ -253,3 +325,23 @@ fun ColorTempSlider(attributes: Map<*, *>, onColorTempChanged: (Float) -> Unit) ) } } + +private fun onSliderChangedFeedback( + isToastEnabled: Boolean, + isHapticEnabled: Boolean, + increase: Boolean, + sliderName: String, + context: Context, + haptic: HapticFeedback +) { + val fullMessage = + if (increase) context.getString(R.string.slider_increased, sliderName) + else context.getString(R.string.slider_decreased, sliderName) + onEntityFeedback( + isToastEnabled, + isHapticEnabled, + fullMessage, + context, + haptic + ) +} diff --git a/wear/src/main/java/io/homeassistant/companion/android/home/views/HomeView.kt b/wear/src/main/java/io/homeassistant/companion/android/home/views/HomeView.kt index 401775a5a47..5f150ba1e3c 100644 --- a/wear/src/main/java/io/homeassistant/companion/android/home/views/HomeView.kt +++ b/wear/src/main/java/io/homeassistant/companion/android/home/views/HomeView.kt @@ -124,7 +124,9 @@ fun LoadHomePage( entity.entityId, colorTemp ) - } + }, + isToastEnabled = mainViewModel.isToastEnabled.value, + isHapticEnabled = mainViewModel.isHapticEnabled.value ) } } diff --git a/wear/src/main/java/io/homeassistant/companion/android/util/CommonFunctions.kt b/wear/src/main/java/io/homeassistant/companion/android/util/CommonFunctions.kt index 8fc179772ac..910c257b5f2 100755 --- a/wear/src/main/java/io/homeassistant/companion/android/util/CommonFunctions.kt +++ b/wear/src/main/java/io/homeassistant/companion/android/util/CommonFunctions.kt @@ -124,8 +124,13 @@ private fun coverIcon(state: String?, entity: Entity>?): IIcon? } fun onEntityClickedFeedback(isToastEnabled: Boolean, isHapticEnabled: Boolean, context: Context, friendlyName: String, haptic: HapticFeedback) { + val message = context.getString(commonR.string.toast_message, friendlyName) + onEntityFeedback(isToastEnabled, isHapticEnabled, message, context, haptic) +} + +fun onEntityFeedback(isToastEnabled: Boolean, isHapticEnabled: Boolean, message: String, context: Context, haptic: HapticFeedback) { if (isToastEnabled) - Toast.makeText(context, context.getString(commonR.string.toast_message, friendlyName), Toast.LENGTH_SHORT).show() + Toast.makeText(context, message, Toast.LENGTH_SHORT).show() if (isHapticEnabled) haptic.performHapticFeedback(HapticFeedbackType.LongPress) }