Преглед изворни кода

Add ForceRefresh and PromoteFromNext buttons

Fix ForceRefreshButton to use async_refresh() so presses always trigger
an immediate poll regardless of debounce cooldown.

Add PromoteFromNextButton on the Room State device: copies the Next
reservation slot into Current via the store, updating last_refresh, so
users can stage data in Next and apply it on demand without a CalDAV fetch.
ZiB пре 4 месеци
родитељ
комит
707337a14c
2 измењених фајлова са 38 додато и 2 уклоњено
  1. 26 2
      custom_components/room_cal_ha/button.py
  2. 12 0
      custom_components/room_cal_ha/coordinator.py

+ 26 - 2
custom_components/room_cal_ha/button.py

@@ -17,7 +17,10 @@ async def async_setup_entry(
 ) -> None:
   coordinator: RoomCalCoordinator = hass.data[DOMAIN][entry.entry_id]["coordinator"]
   device_name = entry.data.get(CONF_ROOM_STATE_NAME, DEFAULT_ROOM_STATE_NAME)
-  async_add_entities([ForceRefreshButton(coordinator, entry, device_name)])
+  async_add_entities([
+    ForceRefreshButton(coordinator, entry, device_name),
+    PromoteFromNextButton(coordinator, entry, device_name),
+  ])
 
 
 class ForceRefreshButton(ButtonEntity):
@@ -38,4 +41,25 @@ class ForceRefreshButton(ButtonEntity):
     )
 
   async def async_press(self) -> None:
-    await self._coordinator.async_request_refresh()
+    await self._coordinator.async_refresh()
+
+
+class PromoteFromNextButton(ButtonEntity):
+  _attr_has_entity_name = True
+  _attr_name = "Promote from Next"
+
+  def __init__(
+    self,
+    coordinator: RoomCalCoordinator,
+    entry: ConfigEntry,
+    device_name: str,
+  ) -> None:
+    self._coordinator = coordinator
+    self._attr_unique_id = f"{entry.entry_id}_promote_from_next"
+    self._attr_device_info = DeviceInfo(
+      identifiers={(DOMAIN, f"{entry.entry_id}_room_state")},
+      name=device_name,
+    )
+
+  async def async_press(self) -> None:
+    await self._coordinator.async_promote_next_to_current()

+ 12 - 0
custom_components/room_cal_ha/coordinator.py

@@ -207,6 +207,18 @@ class RoomCalCoordinator(DataUpdateCoordinator[CoordinatorData]):
     if self._guest_mode_switch is not None:
       self.hass.async_create_task(self._guest_mode_switch.async_turn_off())
 
+  async def async_promote_next_to_current(self) -> None:
+    """Copy the Next slot into Current and notify listeners."""
+    next_data = self.store.get(STORE_NEXT) or ReservationData()
+    await self.store.async_set(STORE_CURRENT, next_data)
+    self._current_last_refresh = dt_util.utcnow()
+    self.async_set_updated_data(CoordinatorData(
+      current=next_data,
+      next=self.store.get(STORE_NEXT) or ReservationData(),
+      current_last_refresh=self._current_last_refresh,
+      next_last_refresh=self._next_last_refresh,
+    ))
+
   async def async_apply_update(self, target: str, partial: dict[str, Any]) -> None:
     """Apply a thin update (service call) to current or next."""
     stored = self.store.get(target) or ReservationData()