Added catch blocks for bad custom component service data responses (#407)

This commit is contained in:
Kevin T. Berstene 2020-02-13 01:22:11 -05:00 committed by GitHub
parent 3da17bb95b
commit e82a6cc9e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 16 deletions

View file

@ -9,7 +9,10 @@ import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.AutoCompleteTextView
import android.widget.EditText
import androidx.appcompat.app.AlertDialog
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.gson.Gson
import io.homeassistant.companion.android.R
@ -93,6 +96,31 @@ class ButtonWidgetConfigureActivity : Activity() {
finish()
}
private val onAddFieldListener = View.OnClickListener {
val context = this@ButtonWidgetConfigureActivity
val fieldKeyInput = EditText(context)
fieldKeyInput.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
AlertDialog.Builder(context)
.setTitle("Field")
.setView(fieldKeyInput)
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.setPositiveButton(android.R.string.ok) { _, _ ->
dynamicFields.add(
ServiceFieldBinder(
context.widget_text_config_service.text.toString(),
fieldKeyInput.text.toString()
)
)
dynamicFieldAdapter.notifyDataSetChanged()
}
.show()
}
private val dropDownOnFocus = View.OnFocusChangeListener { view, hasFocus ->
if (hasFocus && view is AutoCompleteTextView) {
view.showDropDown()
@ -183,26 +211,38 @@ class ButtonWidgetConfigureActivity : Activity() {
widget_text_config_service.onFocusChangeListener = dropDownOnFocus
mainScope.launch {
// Fetch services
integrationUseCase.getServices().forEach {
services[getServiceString(it)] = it
}
serviceAdapter.addAll(services.values)
serviceAdapter.sort()
try {
// Fetch services
integrationUseCase.getServices().forEach {
services[getServiceString(it)] = it
}
serviceAdapter.addAll(services.values)
serviceAdapter.sort()
// Fetch entities
integrationUseCase.getEntities().forEach {
entities[it.entityId] = it
// Update service adapter
runOnUiThread {
serviceAdapter.notifyDataSetChanged()
}
} catch (e: Exception) {
// Custom components can cause services to not load
// Display error text
widget_config_service_error.visibility = View.VISIBLE
}
// Update service adapter
runOnUiThread {
serviceAdapter.notifyDataSetChanged()
try {
// Fetch entities
integrationUseCase.getEntities().forEach {
entities[it.entityId] = it
}
} catch (e: Exception) {
// If entities fail to load, it's okay to pass
// an empty map to the dynamicFieldAdapter
}
}
widget_text_config_service.addTextChangedListener(serviceTextWatcher)
add_field_button.setOnClickListener(onAddFieldListener)
add_button.setOnClickListener(onClickListener)
dynamicFieldAdapter = WidgetDynamicFieldAdapter(services, entities, dynamicFields)

View file

@ -64,14 +64,14 @@ class WidgetDynamicFieldAdapter(
// Only populate with entities for the domain
// or for homeassistant domain, which should be able
// to manipulate entities in any domain
val domain = services[serviceText]!!.domain
val domain = services[serviceText]?.domain
// Add all as an available entity
// all is a special keyword, so it won't be listed in any
// domains even though it is available for all of them
domainEntities.add("all")
if (domain == ("homeassistant")) {
if (domain == ("homeassistant") || domain == null) {
domainEntities.addAll(entities.keys)
} else {
entities.keys.forEach {
@ -85,12 +85,12 @@ class WidgetDynamicFieldAdapter(
adapter.addAll(domainEntities.sorted().toMutableList())
autoCompleteTextView.setAdapter(adapter)
autoCompleteTextView.onFocusChangeListener = dropDownOnFocus
} else if (services[serviceText]!!.serviceData.fields[fieldKey]!!.values != null) {
} else if (services[serviceText]?.serviceData?.fields?.get(fieldKey)?.values != null) {
// If a non-"entity_id" field has specific values,
// populate the autocomplete with valid values
val fieldAdapter = SingleItemArrayAdapter<String>(context) { it!! }
fieldAdapter.addAll(
services[serviceText]!!.serviceData.fields[fieldKey]!!.values!!.sorted().toMutableList()
services[serviceText]!!.serviceData.fields.getValue(fieldKey).values!!.sorted().toMutableList()
)
autoCompleteTextView.setAdapter(fieldAdapter)
autoCompleteTextView.onFocusChangeListener = dropDownOnFocus

View file

@ -40,11 +40,29 @@
android:inputType="text" />
</LinearLayout>
<TextView
android:id="@+id/widget_config_service_error"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textSize="14sp"
android:text="@string/widget_config_service_error"
android:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/widget_config_fields_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/add_field_button"
style="@style/Widget.HomeAssistant.Button.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="8dp"
android:text="@string/add_service_data_field" />
<LinearLayout
android:id="@+id/widget_config_icon_layout"
android:layout_width="match_parent"

View file

@ -41,6 +41,8 @@
<string name="configure_service_call">Configure Service Call</string>
<string name="configure_widget_label">Widget Label</string>
<string name="add_widget">Add widget</string>
<string name="add_service_data_field">Add Field</string>
<string name="widget_config_service_error">A custom component is preventing service data from loading.</string>
<string name="widget_text_hint_service_domain">Domain</string>
<string name="widget_text_hint_service_service">Service</string>
<string name="widget_text_hint_service_data">Entity ID</string>