Explorar o código

Split options flow into sync_mode + caldav steps; add configurable refresh interval

CalDAV settings are now only shown when CalDAV mode is selected. Refresh interval
(1–1440 min, default 15) is exposed in the CalDAV step and read by the coordinator
at entry init time.
ZiB hai 4 meses
pai
achega
1811352b58

+ 47 - 24
custom_components/room_cal_ha/config_flow.py

@@ -9,6 +9,9 @@ import voluptuous as vol
 from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult, OptionsFlow
 from homeassistant.core import callback
 from homeassistant.helpers.selector import (
+  NumberSelector,
+  NumberSelectorConfig,
+  NumberSelectorMode,
   SelectSelector,
   SelectSelectorConfig,
   SelectSelectorMode,
@@ -21,8 +24,10 @@ from .const import (
   CONF_CALDAV_URL,
   CONF_CALENDAR_NAME,
   CONF_PASSWORD,
+  CONF_REFRESH_INTERVAL,
   CONF_SYNC_MODE,
   CONF_USERNAME,
+  DEFAULT_REFRESH_INTERVAL,
   DEFAULT_ROOM_STATE_NAME,
   DOMAIN,
   SYNC_MODE_CALDAV,
@@ -89,65 +94,83 @@ class RoomCalConfigFlow(ConfigFlow, domain=DOMAIN):
 class RoomCalOptionsFlow(OptionsFlow):
 
   def __init__(self) -> None:
-    self._username: str = ""
+    self._selected_mode: str = SYNC_MODE_MANUAL
 
   async def async_step_init(
     self, user_input: dict[str, Any] | None = None
   ) -> ConfigFlowResult:
-    self._username = self.config_entry.data.get(CONF_USERNAME, "")
-    return await self.async_step_sync()
+    return await self.async_step_sync_mode()
 
-  async def async_step_sync(
+  async def async_step_sync_mode(
+    self, user_input: dict[str, Any] | None = None
+  ) -> ConfigFlowResult:
+    if user_input is not None:
+      self._selected_mode = user_input[CONF_SYNC_MODE]
+      if self._selected_mode == SYNC_MODE_CALDAV:
+        return await self.async_step_caldav()
+      merged = {**self.config_entry.options, CONF_SYNC_MODE: self._selected_mode}
+      return self.async_create_entry(data=merged)
+
+    opts = self.config_entry.options
+    return self.async_show_form(
+      step_id="sync_mode",
+      data_schema=vol.Schema({
+        vol.Required(CONF_SYNC_MODE, default=opts.get(CONF_SYNC_MODE, SYNC_MODE_MANUAL)): SelectSelector(
+          SelectSelectorConfig(
+            options=[
+              {"value": SYNC_MODE_MANUAL, "label": "Manual"},
+              {"value": SYNC_MODE_CALDAV, "label": "CalDAV"},
+            ],
+            mode=SelectSelectorMode.LIST,
+          )
+        ),
+      }),
+    )
+
+  async def async_step_caldav(
     self, user_input: dict[str, Any] | None = None
   ) -> ConfigFlowResult:
     errors: dict[str, str] = {}
 
     if user_input is not None:
-      self._username = user_input.pop(CONF_USERNAME, "") or self.config_entry.data.get(CONF_USERNAME, "")
+      username = user_input.pop(CONF_USERNAME, "") or self.config_entry.data.get(CONF_USERNAME, "")
       password = user_input.pop(CONF_PASSWORD, "") or self.config_entry.data.get(CONF_PASSWORD, "")
 
-      new_data = {**self.config_entry.data, CONF_USERNAME: self._username}
-
-      if user_input.get(CONF_SYNC_MODE) == SYNC_MODE_CALDAV and user_input.get(CONF_CALDAV_URL):
+      if user_input.get(CONF_CALDAV_URL):
         try:
           await self.hass.async_add_executor_job(
             _test_caldav_auth,
             user_input[CONF_CALDAV_URL],
-            self._username,
+            username,
             password,
           )
         except caldav_error.AuthorizationError:
           errors["base"] = "invalid_auth"
         except Exception:
           errors["base"] = "cannot_connect"
-        else:
-          new_data[CONF_PASSWORD] = password
 
       if not errors:
+        new_data = {**self.config_entry.data, CONF_USERNAME: username, CONF_PASSWORD: password}
         self.hass.config_entries.async_update_entry(self.config_entry, data=new_data)
-        merged = {**self.config_entry.options, **user_input}
+        merged = {**self.config_entry.options, CONF_SYNC_MODE: self._selected_mode, **user_input}
         return self.async_create_entry(data=merged)
 
     opts = self.config_entry.options
     return self.async_show_form(
-      step_id="sync",
+      step_id="caldav",
       data_schema=vol.Schema({
-        vol.Required(CONF_SYNC_MODE, default=opts.get(CONF_SYNC_MODE, SYNC_MODE_MANUAL)): SelectSelector(
-          SelectSelectorConfig(
-            options=[
-              {"value": "caldav", "label": "CalDAV"},
-              {"value": "api", "label": "API"},
-              {"value": "manual", "label": "Manual"},
-            ],
-            mode=SelectSelectorMode.LIST,
-          )
-        ),
         vol.Optional(CONF_CALDAV_URL, default=opts.get(CONF_CALDAV_URL, "")): str,
         vol.Optional(CONF_CALENDAR_NAME, default=opts.get(CONF_CALENDAR_NAME, "")): str,
-        vol.Optional(CONF_USERNAME, default=self._username): str,
+        vol.Optional(CONF_USERNAME, default=self.config_entry.data.get(CONF_USERNAME, "")): str,
         vol.Optional(CONF_PASSWORD, default=""): TextSelector(
           TextSelectorConfig(type=TextSelectorType.PASSWORD)
         ),
+        vol.Optional(
+          CONF_REFRESH_INTERVAL,
+          default=opts.get(CONF_REFRESH_INTERVAL, DEFAULT_REFRESH_INTERVAL),
+        ): NumberSelector(
+          NumberSelectorConfig(min=1, max=1440, unit_of_measurement="min", mode=NumberSelectorMode.BOX)
+        ),
       }),
       errors=errors,
     )

+ 2 - 1
custom_components/room_cal_ha/const.py

@@ -13,6 +13,7 @@ CONF_PASSWORD = "password"
 CONF_SYNC_MODE = "sync_mode"
 CONF_CALDAV_URL = "caldav_url"
 CONF_CALENDAR_NAME = "calendar_name"
+CONF_REFRESH_INTERVAL = "refresh_interval"
 
 # Sync mode values
 SYNC_MODE_CALDAV = "caldav"
@@ -41,7 +42,7 @@ DEFAULT_CURRENT_NAME = "Current"
 DEFAULT_NEXT_NAME = "Next"
 
 # Update interval
-SCAN_INTERVAL_MINUTES = 15
+DEFAULT_REFRESH_INTERVAL = 15
 
 # Store keys
 STORE_CURRENT = "current"

+ 4 - 2
custom_components/room_cal_ha/coordinator.py

@@ -13,9 +13,10 @@ from homeassistant.util import dt as dt_util
 
 from .backends import BackendAuthError, BackendConnectError, CalDavBackend
 from .const import (
+  CONF_REFRESH_INTERVAL,
   CONF_SYNC_MODE,
+  DEFAULT_REFRESH_INTERVAL,
   DOMAIN,
-  SCAN_INTERVAL_MINUTES,
   STORE_CURRENT,
   STORE_NEXT,
   SYNC_MODE_CALDAV,
@@ -37,11 +38,12 @@ class CoordinatorData:
 class RoomCalCoordinator(DataUpdateCoordinator[CoordinatorData]):
 
   def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None:
+    interval = entry.options.get(CONF_REFRESH_INTERVAL, DEFAULT_REFRESH_INTERVAL)
     super().__init__(
       hass,
       _LOGGER,
       name=DOMAIN,
-      update_interval=timedelta(minutes=SCAN_INTERVAL_MINUTES),
+      update_interval=timedelta(minutes=interval),
     )
     self.entry = entry
     self.store = ReservationStore(hass, entry.entry_id)

+ 11 - 5
custom_components/room_cal_ha/strings.json

@@ -20,14 +20,20 @@
   },
   "options": {
     "step": {
-      "sync": {
-        "title": "Sync Settings",
+      "sync_mode": {
+        "title": "Sync Mode",
+        "data": {
+          "sync_mode": "Sync Mode"
+        }
+      },
+      "caldav": {
+        "title": "CalDAV Settings",
         "data": {
-          "sync_mode": "Sync Mode",
           "caldav_url": "CalDAV URL",
-          "calendar_name": "Calendar name",
+          "calendar_name": "Calendar Name",
           "username": "Username",
-          "password": "Password"
+          "password": "Password",
+          "refresh_interval": "Refresh Interval"
         }
       }
     },

+ 11 - 5
custom_components/room_cal_ha/translations/en.json

@@ -20,14 +20,20 @@
   },
   "options": {
     "step": {
-      "sync": {
-        "title": "Sync Settings",
+      "sync_mode": {
+        "title": "Sync Mode",
+        "data": {
+          "sync_mode": "Sync Mode"
+        }
+      },
+      "caldav": {
+        "title": "CalDAV Settings",
         "data": {
-          "sync_mode": "Sync Mode",
           "caldav_url": "CalDAV URL",
-          "calendar_name": "Calendar name",
+          "calendar_name": "Calendar Name",
           "username": "Username",
-          "password": "Password"
+          "password": "Password",
+          "refresh_interval": "Refresh Interval"
         }
       }
     },