Android TV Remote: Add option to disable IME (#95765)
This commit is contained in:
parent
2cfc11d4b9
commit
d0722e2312
6 changed files with 126 additions and 7 deletions
|
@ -18,7 +18,7 @@ from homeassistant.core import HomeAssistant, callback
|
|||
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||
|
||||
from .const import DOMAIN
|
||||
from .helpers import create_api
|
||||
from .helpers import create_api, get_enable_ime
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -27,7 +27,7 @@ PLATFORMS: list[Platform] = [Platform.MEDIA_PLAYER, Platform.REMOTE]
|
|||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up Android TV Remote from a config entry."""
|
||||
api = create_api(hass, entry.data[CONF_HOST])
|
||||
api = create_api(hass, entry.data[CONF_HOST], get_enable_ime(entry))
|
||||
|
||||
@callback
|
||||
def is_available_updated(is_available: bool) -> None:
|
||||
|
@ -76,6 +76,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
entry.async_on_unload(
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, on_hass_stop)
|
||||
)
|
||||
entry.async_on_unload(entry.add_update_listener(update_listener))
|
||||
|
||||
return True
|
||||
|
||||
|
@ -87,3 +88,8 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
api.disconnect()
|
||||
|
||||
return unload_ok
|
||||
|
||||
|
||||
async def update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
|
||||
"""Handle options update."""
|
||||
await hass.config_entries.async_reload(entry.entry_id)
|
||||
|
|
|
@ -15,11 +15,12 @@ import voluptuous as vol
|
|||
from homeassistant import config_entries
|
||||
from homeassistant.components import zeroconf
|
||||
from homeassistant.const import CONF_HOST, CONF_MAC, CONF_NAME
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.data_entry_flow import FlowResult
|
||||
from homeassistant.helpers.device_registry import format_mac
|
||||
|
||||
from .const import DOMAIN
|
||||
from .helpers import create_api
|
||||
from .const import CONF_ENABLE_IME, DOMAIN
|
||||
from .helpers import create_api, get_enable_ime
|
||||
|
||||
STEP_USER_DATA_SCHEMA = vol.Schema(
|
||||
{
|
||||
|
@ -55,7 +56,7 @@ class AndroidTVRemoteConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
if user_input is not None:
|
||||
self.host = user_input["host"]
|
||||
assert self.host
|
||||
api = create_api(self.hass, self.host)
|
||||
api = create_api(self.hass, self.host, enable_ime=False)
|
||||
try:
|
||||
self.name, self.mac = await api.async_get_name_and_mac()
|
||||
assert self.mac
|
||||
|
@ -75,7 +76,7 @@ class AndroidTVRemoteConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
async def _async_start_pair(self) -> FlowResult:
|
||||
"""Start pairing with the Android TV. Navigate to the pair flow to enter the PIN shown on screen."""
|
||||
assert self.host
|
||||
self.api = create_api(self.hass, self.host)
|
||||
self.api = create_api(self.hass, self.host, enable_ime=False)
|
||||
await self.api.async_generate_cert_if_missing()
|
||||
await self.api.async_start_pairing()
|
||||
return await self.async_step_pair()
|
||||
|
@ -186,3 +187,38 @@ class AndroidTVRemoteConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
description_placeholders={CONF_NAME: self.name},
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@callback
|
||||
def async_get_options_flow(
|
||||
config_entry: config_entries.ConfigEntry,
|
||||
) -> config_entries.OptionsFlow:
|
||||
"""Create the options flow."""
|
||||
return OptionsFlowHandler(config_entry)
|
||||
|
||||
|
||||
class OptionsFlowHandler(config_entries.OptionsFlow):
|
||||
"""Android TV Remote options flow."""
|
||||
|
||||
def __init__(self, config_entry: config_entries.ConfigEntry) -> None:
|
||||
"""Initialize options flow."""
|
||||
self.config_entry = config_entry
|
||||
|
||||
async def async_step_init(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> FlowResult:
|
||||
"""Manage the options."""
|
||||
if user_input is not None:
|
||||
return self.async_create_entry(title="", data=user_input)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="init",
|
||||
data_schema=vol.Schema(
|
||||
{
|
||||
vol.Required(
|
||||
CONF_ENABLE_IME,
|
||||
default=get_enable_ime(self.config_entry),
|
||||
): bool,
|
||||
}
|
||||
),
|
||||
)
|
||||
|
|
|
@ -4,3 +4,6 @@ from __future__ import annotations
|
|||
from typing import Final
|
||||
|
||||
DOMAIN: Final = "androidtv_remote"
|
||||
|
||||
CONF_ENABLE_IME: Final = "enable_ime"
|
||||
CONF_ENABLE_IME_DEFAULT_VALUE: Final = True
|
||||
|
|
|
@ -3,11 +3,14 @@ from __future__ import annotations
|
|||
|
||||
from androidtvremote2 import AndroidTVRemote
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.storage import STORAGE_DIR
|
||||
|
||||
from .const import CONF_ENABLE_IME, CONF_ENABLE_IME_DEFAULT_VALUE
|
||||
|
||||
def create_api(hass: HomeAssistant, host: str) -> AndroidTVRemote:
|
||||
|
||||
def create_api(hass: HomeAssistant, host: str, enable_ime: bool) -> AndroidTVRemote:
|
||||
"""Create an AndroidTVRemote instance."""
|
||||
return AndroidTVRemote(
|
||||
client_name="Home Assistant",
|
||||
|
@ -15,4 +18,10 @@ def create_api(hass: HomeAssistant, host: str) -> AndroidTVRemote:
|
|||
keyfile=hass.config.path(STORAGE_DIR, "androidtv_remote_key.pem"),
|
||||
host=host,
|
||||
loop=hass.loop,
|
||||
enable_ime=enable_ime,
|
||||
)
|
||||
|
||||
|
||||
def get_enable_ime(entry: ConfigEntry) -> bool:
|
||||
"""Get value of enable_ime option or its default value."""
|
||||
return entry.options.get(CONF_ENABLE_IME, CONF_ENABLE_IME_DEFAULT_VALUE)
|
||||
|
|
|
@ -34,5 +34,14 @@
|
|||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"enable_ime": "Enable IME. Needed for getting the current app. Disable for devices that show 'Use keyboard on mobile device screen' instead of the on screen keyboard."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -857,3 +857,59 @@ async def test_reauth_flow_cannot_connect(
|
|||
await hass.async_block_till_done()
|
||||
assert len(mock_unload_entry.mock_calls) == 0
|
||||
assert len(mock_setup_entry.mock_calls) == 0
|
||||
|
||||
|
||||
async def test_options_flow(
|
||||
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_api: MagicMock
|
||||
) -> None:
|
||||
"""Test options flow."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_api.disconnect.call_count == 0
|
||||
assert mock_api.async_connect.call_count == 1
|
||||
|
||||
# Trigger options flow, first time
|
||||
result = await hass.config_entries.options.async_init(mock_config_entry.entry_id)
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "init"
|
||||
data_schema = result["data_schema"].schema
|
||||
assert set(data_schema) == {"enable_ime"}
|
||||
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={"enable_ime": False},
|
||||
)
|
||||
assert result["type"] == "create_entry"
|
||||
assert mock_config_entry.options == {"enable_ime": False}
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_api.disconnect.call_count == 1
|
||||
assert mock_api.async_connect.call_count == 2
|
||||
|
||||
# Trigger options flow, second time, no change, doesn't reload
|
||||
result = await hass.config_entries.options.async_init(mock_config_entry.entry_id)
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={"enable_ime": False},
|
||||
)
|
||||
assert result["type"] == "create_entry"
|
||||
assert mock_config_entry.options == {"enable_ime": False}
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_api.disconnect.call_count == 1
|
||||
assert mock_api.async_connect.call_count == 2
|
||||
|
||||
# Trigger options flow, third time, change, reloads
|
||||
result = await hass.config_entries.options.async_init(mock_config_entry.entry_id)
|
||||
result = await hass.config_entries.options.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={"enable_ime": True},
|
||||
)
|
||||
assert result["type"] == "create_entry"
|
||||
assert mock_config_entry.options == {"enable_ime": True}
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_api.disconnect.call_count == 2
|
||||
assert mock_api.async_connect.call_count == 3
|
||||
|
|
Loading…
Add table
Reference in a new issue