Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@MindFreeze
Copy link
Member

@MindFreeze MindFreeze commented Nov 11, 2025

Proposed change

Prompted from #27565

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (thank you!)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Example configuration

Additional information

  • This PR fixes or closes issue: fixes #
  • This PR is related to issue or discussion:
  • Link to documentation pull request:

Checklist

  • The code change is tested and works locally.
  • There is no commented out code in this PR.
  • Tests have been added to verify that the new code works.

If user exposed functionality or configuration variables are added/changed:

Replace polling-based calendar event fetching with real-time websocket subscriptions. This leverages the new subscription API added in core to provide automatic updates when calendar events change, eliminating the need for periodic polling.

The subscription pattern follows the same approach used for todo items, with proper lifecycle management and cleanup.

Related: home-assistant/core#156340
Related: #27565

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
MindFreeze and others added 2 commits November 11, 2025 12:05
Remove premature subscription attempt in setConfig() that was failing because the date range wasn't available yet. The subscription now properly happens when the view-changed event fires from ha-full-calendar after initial render, which includes the necessary start/end dates.

This ensures calendar events load immediately when the component is first displayed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
The websocket subscription returns event data with fields named start and end, but the frontend was expecting dtstart and dtend. This caused events to not display because the data wasn't being properly mapped.

Now properly transform the subscription response format:
- Subscription format: start/end/summary/description
- Internal format: dtstart/dtend/summary/description

This ensures both initial event loading and real-time updates work correctly.
@MindFreeze MindFreeze marked this pull request as ready for review November 11, 2025 10:15
@MindFreeze MindFreeze requested a review from Copilot November 11, 2025 10:38
Copilot finished reviewing on behalf of MindFreeze November 11, 2025 10:41
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR converts calendar event fetching from REST API calls to WebSocket subscriptions, enabling real-time updates for calendar events. The change affects both the calendar card (Lovelace) and the calendar panel, implementing a subscription-based pattern that allows the UI to receive live updates when calendar events change.

Key changes:

  • Replaced fetchCalendarEvents with subscribeCalendarEvents using WebSocket subscriptions
  • Added subscription management with proper cleanup in disconnectedCallback
  • Implemented per-calendar subscription tracking to handle individual calendar selection/deselection

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 11 comments.

File Description
src/data/calendar.ts Adds new CalendarEventSubscription interface and subscribeCalendarEvents function for WebSocket-based event subscriptions
src/panels/lovelace/cards/hui-calendar-card.ts Converts calendar card from REST API fetching to WebSocket subscriptions with subscription lifecycle management
src/panels/calendar/ha-panel-calendar.ts Converts calendar panel from REST API fetching to WebSocket subscriptions with per-calendar subscription management

MindFreeze and others added 2 commits November 11, 2025 12:58
Fixes based on Copilot review feedback:

1. **Fixed race conditions**: Made _unsubscribeAll() async and await it
   before creating new subscriptions to prevent old subscription events
   from updating UI after new subscriptions are created.

2. **Added error handling**: All unsubscribe operations now catch errors
   to handle cases where subscriptions may have already been closed.

3. **Fixed type safety**: Replaced 'any' type with proper
   CalendarEventSubscriptionData type and added interface definition
   for subscription response data structure.

4. **Improved error tracking**: Calendar card now accumulates errors from
   multiple calendars instead of only showing the last error.

5. **Prevented duplicate subscriptions**: Added checks to unsubscribe
   existing subscriptions before creating new ones in both
   _subscribeCalendarEvents and _requestSelected.

6. **Fixed null handling**: Properly convert null values to undefined
   for CalendarEventData fields to match expected types.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Reduced code duplication by extracting the calendar event normalization
logic from both hui-calendar-card.ts and ha-panel-calendar.ts into a
shared utility function in calendar.ts.

The normalizeSubscriptionEventData() function handles the conversion
from subscription format (start/end) to internal format (dtstart/dtend)
in a single, reusable location.

This improves maintainability by ensuring consistent event normalization
across all calendar components and reduces the risk of divergence.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@MindFreeze MindFreeze requested a review from Copilot November 11, 2025 11:05
Copilot finished reviewing on behalf of MindFreeze November 11, 2025 11:07
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

src/data/calendar.ts:1

  • The location field from CalendarEventSubscriptionData is normalized but not included in the returned CalendarEvent object. This appears to be a data loss issue - either location should be added to CalendarEventData interface and included in normalizedEventData, or it should be removed from CalendarEventSubscriptionData if not supported.
import { getColorByIndex } from "../common/color/colors";

Fixed remaining issues from code review:

1. **Added @State decorator to _errorCalendars**: Ensures proper reactivity
   in calendar card when errors occur or are cleared, triggering UI updates.

2. **Fixed error accumulation in panel calendar**: Panel now properly
   accumulates errors from multiple calendars similar to the card
   implementation, preventing previously failed calendars from being
   hidden when new errors occur.

3. **Removed duplicate subscription check**: Deleted redundant duplicate
   subscription prevention in _requestSelected() since
   _subscribeCalendarEvents() already handles this at lines 221-227.

Note: The [nitpick] comment about loading states during await is a
performance enhancement suggestion, not a required fix.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@MindFreeze MindFreeze requested a review from Copilot November 11, 2025 11:16
Copilot finished reviewing on behalf of MindFreeze November 11, 2025 11:17
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

src/data/calendar.ts:1

  • The location field in CalendarEventSubscriptionData is not used in the normalizeSubscriptionEventData function. This should be documented in the interface or handled in the normalization function, as calendar events typically support location information.
import { getColorByIndex } from "../common/color/colors";

MindFreeze and others added 7 commits November 11, 2025 13:23
Eliminated code duplication by reusing normalizeSubscriptionEventData() in
fetchCalendarEvents(). After extracting date strings from the REST API
response format, we now convert to a subscription-like format and pass
it to the shared utility.

This ensures consistent event normalization across both REST API and
WebSocket subscription code paths, reducing maintenance burden and
potential for divergence.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
The getCalendarDate helper is part of the normalization process and should be inside the normalization function. This makes normalizeSubscriptionEventData handle both REST API format (with dateTime/date objects) and subscription format (plain strings).

Changes:
- Moved getCalendarDate into normalizeSubscriptionEventData
- Updated CalendarEventSubscriptionData to accept string | any for start/end
- Made normalizeSubscriptionEventData return CalendarEvent | null for invalid dates
- Simplified fetchCalendarEvents to use the shared normalization
- Added null filtering in calendar card and panel event handlers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Added proper types for calendar event data:
- CalendarDateValue: Union type for date values (string | {dateTime} | {date})
- CalendarEventRestData: Interface for REST API event responses
- Updated fetchCalendarEvents to use CalendarEventRestData[]
- Updated CalendarEventSubscriptionData to use CalendarDateValue
- Updated getCalendarDate to use proper type guards with 'in' operator

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Both interfaces had identical structures, so unified them into a single
CalendarEventSubscriptionData interface that is used for both REST API
responses and WebSocket subscription data.

Changes:
- Removed CalendarEventRestData interface
- Updated fetchCalendarEvents to use CalendarEventSubscriptionData
- Added documentation clarifying the interface is used for both APIs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
* Calendar event data from both REST API and WebSocket subscription.
* Both APIs use the same data format.
*/
export interface CalendarEventSubscriptionData {
Copy link
Member

@bramkragten bramkragten Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why call it SubscriptionData if it is used in the REST API too? Just rename it to CalendarEventData?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, thats used for the normalized version...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed it to CalendarEventApiData 🤷

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants