mirror of
https://github.com/home-assistant/android
synced 2024-07-09 04:15:51 +00:00
Add 'toggle' tap action to entity state widget (#3798)
* [WIP] Widget tap action: toggle entity * Add feedback on press and failure * Share code for pressing on entities * Align cover press action - Toggle will stop if possible when opening/closing if supported so prefer toggle instead of open/close * Toggle by default if supported - Set the default tap action for supported entities to toggle instead of refresh * Update widget description
This commit is contained in:
parent
e3ce9ed5b0
commit
7f14582909
|
@ -22,7 +22,9 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||
import dagger.hilt.android.EntryPointAccessors
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import io.homeassistant.companion.android.common.data.integration.Entity
|
||||
import io.homeassistant.companion.android.common.data.integration.EntityExt
|
||||
import io.homeassistant.companion.android.common.data.integration.getIcon
|
||||
import io.homeassistant.companion.android.common.data.integration.onEntityPressedWithoutState
|
||||
import io.homeassistant.companion.android.common.data.servers.ServerManager
|
||||
import io.homeassistant.companion.android.database.qs.TileDao
|
||||
import io.homeassistant.companion.android.database.qs.TileEntity
|
||||
|
@ -236,22 +238,9 @@ abstract class TileExtensions : TileService() {
|
|||
}
|
||||
withContext(Dispatchers.IO) {
|
||||
try {
|
||||
serverManager.integrationRepository(tileData.serverId).callService(
|
||||
tileData.entityId.split(".")[0],
|
||||
when (tileData.entityId.split(".")[0]) {
|
||||
"button", "input_button" -> "press"
|
||||
in toggleDomains -> "toggle"
|
||||
"lock" -> {
|
||||
val state = serverManager.integrationRepository(tileData.serverId).getEntity(tileData.entityId)
|
||||
if (state?.state == "locked") {
|
||||
"unlock"
|
||||
} else {
|
||||
"lock"
|
||||
}
|
||||
}
|
||||
else -> "turn_on"
|
||||
},
|
||||
hashMapOf("entity_id" to tileData.entityId)
|
||||
onEntityPressedWithoutState(
|
||||
tileData.entityId,
|
||||
serverManager.integrationRepository(tileData.serverId)
|
||||
)
|
||||
Log.d(TAG, "Service call sent for tile ID: $tileId")
|
||||
} catch (e: Exception) {
|
||||
|
@ -342,11 +331,7 @@ abstract class TileExtensions : TileService() {
|
|||
|
||||
companion object {
|
||||
private const val TAG = "TileExtensions"
|
||||
private val toggleDomains = listOf(
|
||||
"automation", "cover", "fan", "humidifier", "input_boolean", "light",
|
||||
"media_player", "remote", "siren", "switch"
|
||||
)
|
||||
private val toggleDomainsWithLock = toggleDomains.plus("lock")
|
||||
private val toggleDomainsWithLock = EntityExt.DOMAINS_TOGGLE
|
||||
private val validActiveStates = listOf("on", "open", "locked")
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import androidx.fragment.app.viewModels
|
|||
import com.google.accompanist.themeadapter.material.MdcTheme
|
||||
import com.mikepenz.iconics.typeface.IIcon
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.homeassistant.companion.android.common.data.integration.EntityExt
|
||||
import io.homeassistant.companion.android.settings.addHelpMenuProvider
|
||||
import io.homeassistant.companion.android.settings.qs.views.ManageTilesView
|
||||
import io.homeassistant.companion.android.util.icondialog.IconDialog
|
||||
|
@ -25,10 +26,7 @@ class ManageTilesFragment : Fragment() {
|
|||
|
||||
companion object {
|
||||
private const val TAG = "TileFragment"
|
||||
val validDomains = listOf(
|
||||
"automation", "button", "cover", "fan", "humidifier", "input_boolean", "input_button", "light",
|
||||
"lock", "media_player", "remote", "siren", "scene", "script", "switch"
|
||||
)
|
||||
val validDomains = EntityExt.APP_PRESS_ACTION_DOMAINS
|
||||
}
|
||||
|
||||
val viewModel: ManageTilesViewModel by viewModels()
|
||||
|
|
|
@ -12,6 +12,7 @@ import android.util.Log
|
|||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.widget.RemoteViews
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.toColorInt
|
||||
import com.google.android.material.color.DynamicColors
|
||||
|
@ -20,9 +21,11 @@ import io.homeassistant.companion.android.R
|
|||
import io.homeassistant.companion.android.common.data.integration.Entity
|
||||
import io.homeassistant.companion.android.common.data.integration.canSupportPrecision
|
||||
import io.homeassistant.companion.android.common.data.integration.friendlyState
|
||||
import io.homeassistant.companion.android.common.data.integration.onEntityPressedWithoutState
|
||||
import io.homeassistant.companion.android.database.widget.StaticWidgetDao
|
||||
import io.homeassistant.companion.android.database.widget.StaticWidgetEntity
|
||||
import io.homeassistant.companion.android.database.widget.WidgetBackgroundType
|
||||
import io.homeassistant.companion.android.database.widget.WidgetTapAction
|
||||
import io.homeassistant.companion.android.util.getAttribute
|
||||
import io.homeassistant.companion.android.widgets.BaseWidgetProvider
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -34,6 +37,8 @@ class EntityWidget : BaseWidgetProvider() {
|
|||
|
||||
companion object {
|
||||
private const val TAG = "StaticWidget"
|
||||
internal const val TOGGLE_ENTITY =
|
||||
"io.homeassistant.companion.android.widgets.entity.EntityWidget.TOGGLE_ENTITY"
|
||||
|
||||
internal const val EXTRA_SERVER_ID = "EXTRA_SERVER_ID"
|
||||
internal const val EXTRA_ENTITY_ID = "EXTRA_ENTITY_ID"
|
||||
|
@ -42,6 +47,7 @@ class EntityWidget : BaseWidgetProvider() {
|
|||
internal const val EXTRA_TEXT_SIZE = "EXTRA_TEXT_SIZE"
|
||||
internal const val EXTRA_STATE_SEPARATOR = "EXTRA_STATE_SEPARATOR"
|
||||
internal const val EXTRA_ATTRIBUTE_SEPARATOR = "EXTRA_ATTRIBUTE_SEPARATOR"
|
||||
internal const val EXTRA_TAP_ACTION = "EXTRA_TAP_ACTION"
|
||||
internal const val EXTRA_BACKGROUND_TYPE = "EXTRA_BACKGROUND_TYPE"
|
||||
internal const val EXTRA_TEXT_COLOR = "EXTRA_TEXT_COLOR"
|
||||
|
||||
|
@ -55,12 +61,13 @@ class EntityWidget : BaseWidgetProvider() {
|
|||
ComponentName(context, EntityWidget::class.java)
|
||||
|
||||
override suspend fun getWidgetRemoteViews(context: Context, appWidgetId: Int, suggestedEntity: Entity<Map<String, Any>>?): RemoteViews {
|
||||
val widget = staticWidgetDao.get(appWidgetId)
|
||||
|
||||
val intent = Intent(context, EntityWidget::class.java).apply {
|
||||
action = UPDATE_VIEW
|
||||
action = if (widget?.tapAction == WidgetTapAction.TOGGLE) TOGGLE_ENTITY else UPDATE_VIEW
|
||||
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||
}
|
||||
|
||||
val widget = staticWidgetDao.get(appWidgetId)
|
||||
val useDynamicColors = widget?.backgroundType == WidgetBackgroundType.DYNAMICCOLOR && DynamicColors.isDynamicColorAvailable()
|
||||
val views = RemoteViews(context.packageName, if (useDynamicColors) R.layout.widget_static_wrapper_dynamiccolor else R.layout.widget_static_wrapper_default).apply {
|
||||
if (widget != null) {
|
||||
|
@ -83,6 +90,14 @@ class EntityWidget : BaseWidgetProvider() {
|
|||
}
|
||||
|
||||
// Content
|
||||
setViewVisibility(
|
||||
R.id.widgetTextLayout,
|
||||
View.VISIBLE
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widgetProgressBar,
|
||||
View.INVISIBLE
|
||||
)
|
||||
val resolvedText = resolveTextToShow(
|
||||
context,
|
||||
serverId,
|
||||
|
@ -194,6 +209,12 @@ class EntityWidget : BaseWidgetProvider() {
|
|||
val textSizeSelection: String? = extras.getString(EXTRA_TEXT_SIZE)
|
||||
val stateSeparatorSelection: String? = extras.getString(EXTRA_STATE_SEPARATOR)
|
||||
val attributeSeparatorSelection: String? = extras.getString(EXTRA_ATTRIBUTE_SEPARATOR)
|
||||
val tapActionSelection: WidgetTapAction = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
extras.getSerializable(EXTRA_TAP_ACTION, WidgetTapAction::class.java)
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
extras.getSerializable(EXTRA_TAP_ACTION) as? WidgetTapAction
|
||||
} ?: WidgetTapAction.REFRESH
|
||||
val backgroundTypeSelection: WidgetBackgroundType = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
extras.getSerializable(EXTRA_BACKGROUND_TYPE, WidgetBackgroundType::class.java)
|
||||
} else {
|
||||
|
@ -224,6 +245,7 @@ class EntityWidget : BaseWidgetProvider() {
|
|||
textSizeSelection?.toFloatOrNull() ?: 30F,
|
||||
stateSeparatorSelection ?: "",
|
||||
attributeSeparatorSelection ?: "",
|
||||
tapActionSelection,
|
||||
staticWidgetDao.get(appWidgetId)?.lastUpdate ?: "",
|
||||
backgroundTypeSelection,
|
||||
textColorSelection
|
||||
|
@ -241,6 +263,45 @@ class EntityWidget : BaseWidgetProvider() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun toggleEntity(context: Context, appWidgetId: Int) {
|
||||
widgetScope?.launch {
|
||||
// Show progress bar as feedback
|
||||
val appWidgetManager = AppWidgetManager.getInstance(context)
|
||||
val loadingViews = RemoteViews(context.packageName, R.layout.widget_static)
|
||||
loadingViews.setViewVisibility(R.id.widgetProgressBar, View.VISIBLE)
|
||||
loadingViews.setViewVisibility(R.id.widgetTextLayout, View.GONE)
|
||||
appWidgetManager.partiallyUpdateAppWidget(appWidgetId, loadingViews)
|
||||
|
||||
var success = false
|
||||
staticWidgetDao.get(appWidgetId)?.let {
|
||||
try {
|
||||
onEntityPressedWithoutState(
|
||||
it.entityId,
|
||||
serverManager.integrationRepository(it.serverId)
|
||||
)
|
||||
success = true
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to send toggle service call", e)
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
Toast.makeText(context, commonR.string.service_call_failure, Toast.LENGTH_LONG).show()
|
||||
|
||||
val views = getWidgetRemoteViews(context, appWidgetId)
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||
} // else update will be triggered by websocket subscription
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
|
||||
super.onReceive(context, intent)
|
||||
when (lastIntent) {
|
||||
TOGGLE_ENTITY -> toggleEntity(context, appWidgetId)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDeleted(context: Context, appWidgetIds: IntArray) {
|
||||
widgetScope?.launch {
|
||||
staticWidgetDao.deleteAll(appWidgetIds)
|
||||
|
|
|
@ -23,8 +23,11 @@ import androidx.lifecycle.lifecycleScope
|
|||
import com.google.android.material.color.DynamicColors
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.homeassistant.companion.android.common.data.integration.Entity
|
||||
import io.homeassistant.companion.android.common.data.integration.EntityExt
|
||||
import io.homeassistant.companion.android.common.data.integration.domain
|
||||
import io.homeassistant.companion.android.database.widget.StaticWidgetDao
|
||||
import io.homeassistant.companion.android.database.widget.WidgetBackgroundType
|
||||
import io.homeassistant.companion.android.database.widget.WidgetTapAction
|
||||
import io.homeassistant.companion.android.databinding.WidgetStaticConfigureBinding
|
||||
import io.homeassistant.companion.android.settings.widgets.ManageWidgetsViewModel
|
||||
import io.homeassistant.companion.android.util.getHexForColor
|
||||
|
@ -122,6 +125,9 @@ class EntityWidgetConfigureActivity : BaseWidgetConfigureActivity() {
|
|||
|
||||
val staticWidget = staticWidgetDao.get(appWidgetId)
|
||||
|
||||
val tapActionValues = listOf(getString(commonR.string.widget_tap_action_toggle), getString(commonR.string.refresh))
|
||||
binding.tapActionList.adapter = ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, tapActionValues)
|
||||
|
||||
val backgroundTypeValues = mutableListOf(
|
||||
getString(commonR.string.widget_background_type_daynight),
|
||||
getString(commonR.string.widget_background_type_transparent)
|
||||
|
@ -162,6 +168,10 @@ class EntityWidgetConfigureActivity : BaseWidgetConfigureActivity() {
|
|||
setupAttributes()
|
||||
}
|
||||
|
||||
val toggleable = entity?.domain in EntityExt.APP_PRESS_ACTION_DOMAINS
|
||||
binding.tapAction.isVisible = toggleable
|
||||
binding.tapActionList.setSelection(if (toggleable && staticWidget.tapAction == WidgetTapAction.TOGGLE) 0 else 1)
|
||||
|
||||
binding.backgroundType.setSelection(
|
||||
when {
|
||||
staticWidget.backgroundType == WidgetBackgroundType.DYNAMICCOLOR && DynamicColors.isDynamicColorAvailable() ->
|
||||
|
@ -272,6 +282,9 @@ class EntityWidgetConfigureActivity : BaseWidgetConfigureActivity() {
|
|||
attributesAdapter.addAll(*fetchedAttributes?.keys.orEmpty().toTypedArray())
|
||||
binding.widgetTextConfigAttribute.setTokenizer(CommaTokenizer())
|
||||
runOnUiThread {
|
||||
val toggleable = selectedEntity?.domain in EntityExt.APP_PRESS_ACTION_DOMAINS
|
||||
binding.tapAction.isVisible = toggleable
|
||||
binding.tapActionList.setSelection(if (toggleable) 0 else 1)
|
||||
attributesAdapter.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
@ -342,6 +355,14 @@ class EntityWidgetConfigureActivity : BaseWidgetConfigureActivity() {
|
|||
)
|
||||
}
|
||||
|
||||
intent.putExtra(
|
||||
EntityWidget.EXTRA_TAP_ACTION,
|
||||
when (binding.tapActionList.selectedItemPosition) {
|
||||
0 -> WidgetTapAction.TOGGLE
|
||||
else -> WidgetTapAction.REFRESH
|
||||
}
|
||||
)
|
||||
|
||||
intent.putExtra(
|
||||
EntityWidget.EXTRA_BACKGROUND_TYPE,
|
||||
when (binding.backgroundType.selectedItem as String?) {
|
||||
|
|
|
@ -56,4 +56,14 @@
|
|||
android:maxLines="2" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/widgetProgressBar"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:visibility="invisible"
|
||||
android:indeterminate="true"
|
||||
android:indeterminateTint="@color/colorAccent"
|
||||
android:layout_gravity="center"
|
||||
/>
|
||||
</FrameLayout>
|
|
@ -196,6 +196,28 @@
|
|||
android:inputType="text" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/tap_action"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:padding="5dp"
|
||||
android:text="@string/widget_tap_action_label" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/tap_action_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -42,6 +42,17 @@ object EntityExt {
|
|||
const val LIGHT_SUPPORT_BRIGHTNESS_DEPR = 1
|
||||
const val LIGHT_SUPPORT_COLOR_TEMP_DEPR = 2
|
||||
const val ALARM_CONTROL_PANEL_SUPPORT_ARM_AWAY = 2
|
||||
|
||||
val DOMAINS_PRESS = listOf("button", "input_button")
|
||||
val DOMAINS_TOGGLE = listOf(
|
||||
"automation", "cover", "fan", "humidifier", "input_boolean", "light", "lock",
|
||||
"media_player", "remote", "siren", "switch"
|
||||
)
|
||||
|
||||
val APP_PRESS_ACTION_DOMAINS = DOMAINS_PRESS + DOMAINS_TOGGLE + listOf(
|
||||
"scene",
|
||||
"script"
|
||||
)
|
||||
}
|
||||
|
||||
val <T> Entity<T>.domain: String
|
||||
|
@ -601,14 +612,10 @@ suspend fun <T> Entity<T>.onPressed(
|
|||
"lock" -> {
|
||||
if (state == "unlocked") "lock" else "unlock"
|
||||
}
|
||||
"cover" -> {
|
||||
if (state == "open") "close_cover" else "open_cover"
|
||||
}
|
||||
"alarm_control_panel" -> {
|
||||
if (state != "disarmed") "alarm_disarm" else "alarm_arm_away"
|
||||
}
|
||||
"button",
|
||||
"input_button" -> "press"
|
||||
in EntityExt.DOMAINS_PRESS -> "press"
|
||||
"fan",
|
||||
"input_boolean",
|
||||
"script",
|
||||
|
@ -626,6 +633,36 @@ suspend fun <T> Entity<T>.onPressed(
|
|||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an app press action like [Entity.onPressed], but without a current state if possible to
|
||||
* speed up the execution.
|
||||
* @throws IntegrationException on network errors
|
||||
*/
|
||||
suspend fun onEntityPressedWithoutState(
|
||||
entityId: String,
|
||||
integrationRepository: IntegrationRepository
|
||||
) {
|
||||
val domain = entityId.split(".")[0]
|
||||
val service = when (domain) {
|
||||
"lock" -> {
|
||||
val lockEntity = try {
|
||||
integrationRepository.getEntity(entityId)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
if (lockEntity?.state == "locked") "unlock" else "lock"
|
||||
}
|
||||
in EntityExt.DOMAINS_PRESS -> "press"
|
||||
in EntityExt.DOMAINS_TOGGLE -> "toggle"
|
||||
else -> "turn_on"
|
||||
}
|
||||
integrationRepository.callService(
|
||||
domain = domain,
|
||||
service = service,
|
||||
serviceData = hashMapOf("entity_id" to entityId)
|
||||
)
|
||||
}
|
||||
|
||||
val <T> Entity<T>.friendlyName: String
|
||||
get() = (attributes as? Map<*, *>)?.get("friendly_name")?.toString() ?: entityId
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ import io.homeassistant.companion.android.database.widget.StaticWidgetEntity
|
|||
import io.homeassistant.companion.android.database.widget.TemplateWidgetDao
|
||||
import io.homeassistant.companion.android.database.widget.TemplateWidgetEntity
|
||||
import io.homeassistant.companion.android.database.widget.WidgetBackgroundTypeConverter
|
||||
import io.homeassistant.companion.android.database.widget.WidgetTapActionConverter
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.util.UUID
|
||||
import io.homeassistant.companion.android.common.R as commonR
|
||||
|
@ -90,7 +91,7 @@ import io.homeassistant.companion.android.common.R as commonR
|
|||
Server::class,
|
||||
Setting::class
|
||||
],
|
||||
version = 42,
|
||||
version = 43,
|
||||
autoMigrations = [
|
||||
AutoMigration(from = 24, to = 25),
|
||||
AutoMigration(from = 25, to = 26),
|
||||
|
@ -108,7 +109,8 @@ import io.homeassistant.companion.android.common.R as commonR
|
|||
AutoMigration(from = 37, to = 38, spec = AppDatabase.Companion.Migration37to38::class),
|
||||
AutoMigration(from = 38, to = 39),
|
||||
AutoMigration(from = 39, to = 40),
|
||||
AutoMigration(from = 41, to = 42)
|
||||
AutoMigration(from = 41, to = 42),
|
||||
AutoMigration(from = 42, to = 43)
|
||||
]
|
||||
)
|
||||
@TypeConverters(
|
||||
|
@ -116,7 +118,8 @@ import io.homeassistant.companion.android.common.R as commonR
|
|||
LocalSensorSettingConverter::class,
|
||||
EntriesTypeConverter::class,
|
||||
SensorSettingTypeConverter::class,
|
||||
WidgetBackgroundTypeConverter::class
|
||||
WidgetBackgroundTypeConverter::class,
|
||||
WidgetTapActionConverter::class
|
||||
)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun authenticationDao(): AuthenticationDao
|
||||
|
|
|
@ -22,6 +22,8 @@ data class StaticWidgetEntity(
|
|||
val stateSeparator: String = "",
|
||||
@ColumnInfo(name = "attribute_separator")
|
||||
val attributeSeparator: String = "",
|
||||
@ColumnInfo(name = "tap_action", defaultValue = "REFRESH")
|
||||
val tapAction: WidgetTapAction,
|
||||
@ColumnInfo(name = "last_update")
|
||||
val lastUpdate: String,
|
||||
@ColumnInfo(name = "background_type", defaultValue = "DAYNIGHT")
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package io.homeassistant.companion.android.database.widget
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
|
||||
enum class WidgetTapAction {
|
||||
REFRESH, TOGGLE
|
||||
}
|
||||
|
||||
class WidgetTapActionConverter {
|
||||
|
||||
@TypeConverter
|
||||
fun toWidgetTapAction(setting: String): WidgetTapAction = WidgetTapAction.valueOf(setting)
|
||||
|
||||
@TypeConverter
|
||||
fun fromWidgetBackgroundType(setting: WidgetTapAction): String = setting.name
|
||||
}
|
|
@ -224,7 +224,7 @@
|
|||
<string name="entity_attribute_checkbox">Append attribute value</string>
|
||||
<string name="entity_id">Entity ID</string>
|
||||
<string name="entity_id_name">Entity ID: %1$s</string>
|
||||
<string name="entity_widget_desc">Current state and attribute of any entity</string>
|
||||
<string name="entity_widget_desc">View any entity\'s current state and toggle it</string>
|
||||
<string name="error_auth_revoked">It appears that your authorization was revoked, please reconnect to Home Assistant.</string>
|
||||
<string name="error_connection_failed">Unable to connect to Home Assistant.</string>
|
||||
<string name="error_loading_entities">Error loading entities</string>
|
||||
|
@ -956,6 +956,8 @@
|
|||
<string name="widget_spinner_server">Server:</string>
|
||||
<string name="widget_state_separator_label">State and attribute separator:</string>
|
||||
<string name="widget_static_image_description">Entity state</string>
|
||||
<string name="widget_tap_action_label">Tap action:</string>
|
||||
<string name="widget_tap_action_toggle">Toggle</string>
|
||||
<string name="widget_template_error">Unable to render the template</string>
|
||||
<string name="widget_text_hint_label">Label</string>
|
||||
<string name="widget_text_hint_service_data">Entity ID</string>
|
||||
|
|
|
@ -5,6 +5,7 @@ import io.homeassistant.companion.android.BuildConfig
|
|||
import io.homeassistant.companion.android.common.data.authentication.SessionState
|
||||
import io.homeassistant.companion.android.common.data.integration.DeviceRegistration
|
||||
import io.homeassistant.companion.android.common.data.integration.Entity
|
||||
import io.homeassistant.companion.android.common.data.integration.EntityExt
|
||||
import io.homeassistant.companion.android.common.data.prefs.WearPrefsRepository
|
||||
import io.homeassistant.companion.android.common.data.servers.ServerManager
|
||||
import io.homeassistant.companion.android.common.data.websocket.WebSocketState
|
||||
|
@ -31,10 +32,6 @@ class HomePresenterImpl @Inject constructor(
|
|||
) : HomePresenter {
|
||||
|
||||
companion object {
|
||||
val toggleDomains = listOf(
|
||||
"cover", "fan", "humidifier", "input_boolean", "light", "lock",
|
||||
"media_player", "remote", "siren", "switch"
|
||||
)
|
||||
val domainsWithNames = mapOf(
|
||||
"button" to commonR.string.buttons,
|
||||
"cover" to commonR.string.covers,
|
||||
|
@ -97,7 +94,7 @@ class HomePresenterImpl @Inject constructor(
|
|||
"lock"
|
||||
}
|
||||
}
|
||||
in toggleDomains -> "toggle"
|
||||
in EntityExt.DOMAINS_TOGGLE -> "toggle"
|
||||
else -> "turn_on"
|
||||
}
|
||||
try {
|
||||
|
|
|
@ -41,7 +41,6 @@ import io.homeassistant.companion.android.common.data.integration.getLightBright
|
|||
import io.homeassistant.companion.android.common.data.integration.supportsFanSetSpeed
|
||||
import io.homeassistant.companion.android.common.data.integration.supportsLightBrightness
|
||||
import io.homeassistant.companion.android.common.data.integration.supportsLightColorTemperature
|
||||
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
|
||||
|
@ -84,7 +83,7 @@ fun DetailsPanelView(
|
|||
val friendlyName = attributes["friendly_name"].toString()
|
||||
Text(friendlyName)
|
||||
|
||||
if (entity.domain in HomePresenterImpl.toggleDomains) {
|
||||
if (entity.domain in EntityExt.DOMAINS_TOGGLE) {
|
||||
val isChecked = entity.state in listOf("on", "locked", "open", "opening")
|
||||
ToggleButton(
|
||||
checked = isChecked,
|
||||
|
|
|
@ -23,9 +23,9 @@ import com.mikepenz.iconics.compose.Image
|
|||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||
import io.homeassistant.companion.android.common.R
|
||||
import io.homeassistant.companion.android.common.data.integration.Entity
|
||||
import io.homeassistant.companion.android.common.data.integration.EntityExt
|
||||
import io.homeassistant.companion.android.common.data.integration.domain
|
||||
import io.homeassistant.companion.android.common.data.integration.getIcon
|
||||
import io.homeassistant.companion.android.home.HomePresenterImpl
|
||||
import io.homeassistant.companion.android.theme.wearColorPalette
|
||||
import io.homeassistant.companion.android.util.WearToggleChip
|
||||
import io.homeassistant.companion.android.util.onEntityClickedFeedback
|
||||
|
@ -46,7 +46,7 @@ fun EntityUi(
|
|||
val iconBitmap = entity.getIcon(LocalContext.current)
|
||||
val friendlyName = attributes["friendly_name"].toString()
|
||||
|
||||
if (entity.domain in HomePresenterImpl.toggleDomains) {
|
||||
if (entity.domain in EntityExt.DOMAINS_TOGGLE) {
|
||||
val isChecked = entity.state in listOf("on", "locked", "open", "opening")
|
||||
ToggleChip(
|
||||
checked = isChecked,
|
||||
|
|
|
@ -10,9 +10,9 @@ import android.os.VibratorManager
|
|||
import android.util.Log
|
||||
import androidx.core.content.getSystemService
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.homeassistant.companion.android.common.data.integration.onEntityPressedWithoutState
|
||||
import io.homeassistant.companion.android.common.data.prefs.WearPrefsRepository
|
||||
import io.homeassistant.companion.android.common.data.servers.ServerManager
|
||||
import io.homeassistant.companion.android.home.HomePresenterImpl
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -46,30 +46,10 @@ class TileActionReceiver : BroadcastReceiver() {
|
|||
}
|
||||
}
|
||||
|
||||
val domain = entityId.split(".")[0]
|
||||
val serviceName = when (domain) {
|
||||
"button", "input_button" -> "press"
|
||||
"lock" -> {
|
||||
val lockEntity = try {
|
||||
serverManager.integrationRepository().getEntity(entityId)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
if (lockEntity?.state == "locked") {
|
||||
"unlock"
|
||||
} else {
|
||||
"lock"
|
||||
}
|
||||
}
|
||||
in HomePresenterImpl.toggleDomains -> "toggle"
|
||||
else -> "turn_on"
|
||||
}
|
||||
|
||||
try {
|
||||
serverManager.integrationRepository().callService(
|
||||
domain,
|
||||
serviceName,
|
||||
hashMapOf("entity_id" to entityId)
|
||||
onEntityPressedWithoutState(
|
||||
entityId = entityId,
|
||||
integrationRepository = serverManager.integrationRepository()
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Cannot call tile service", e)
|
||||
|
|
Loading…
Reference in New Issue
Block a user