Skip to content

Close notification drawer after dismissing last notification#7229

Merged
bramkragten merged 2 commits intohome-assistant:devfrom
mattmattmatt:close-notifications-after-last-dismiss
Oct 12, 2020
Merged

Close notification drawer after dismissing last notification#7229
bramkragten merged 2 commits intohome-assistant:devfrom
mattmattmatt:close-notifications-after-last-dismiss

Conversation

@mattmattmatt
Copy link
Contributor

@mattmattmatt mattmattmatt commented Oct 5, 2020

Proposed change

This change adds a listener to any changes of the notifications property once the notification drawer opens. After the last notification is dismissed, the notification drawer closes automatically, and the listener is removed.

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

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:

This change adds a listener to any changes of the notifications property once the drawer opens. After the last notification is dismissed, the notification drawer closes automatically, and the listener is removed.
Comment on lines +126 to +129
this.addEventListener(
"notifications-changed",
this._onNotificationsChanged
);
Copy link
Member

Choose a reason for hiding this comment

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

We can call this in _computeNotifications instead of with an event? And otherwise we should add an observer on notifications instead of the notify

Copy link
Contributor Author

@mattmattmatt mattmattmatt Oct 5, 2020

Choose a reason for hiding this comment

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

The issue with all approaches that don't include an event observer is that the notifications are loaded async. That means when the user tries to open the drawer, for a split second notifications.length === 0 is true, and the drawer immediately closes again (actually stays closed).
This is an issue both if we use an observer pattern (like _openChanged does), and if we move this into _computeNotifications.

While encapsulating everything in _computeNotifications is a lot more compact, it runs into the issue mentioned above:

  _computeNotifications(open, hass, notificationsBackend) {
    if (!open) {
      return [];
    }

    const configuratorEntities = Object.keys(hass.states)
      .filter((entityId) => computeDomain(entityId) === "configurator")
      .map((entityId) => hass.states[entityId]);

    const notifications = notificationsBackend.concat(configuratorEntities);

    // this evaluates to true when the user tries to open the drawer before we have
    // received any notifications from the backend-subscription, thus preventing the drawer from opening
    if (notifications.length === 0) {
        this.open = false;
    }

    return notifications;
  }

The only way I have found to avoid this is by attaching the observer once we have loaded all notifications.

Another option would be to rewrite the whole component to set up the server subscription in PolymerElement.ready, but that would be a larger refactor that I did not feel comfortable proposing for this small feature.

Copy link
Member

Choose a reason for hiding this comment

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

We should rewrite it to a LitElement, that will solve your problem and should be done anyway

Copy link
Member

Choose a reason for hiding this comment

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

If you want that challenge that is :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have not worked with Polymer or LitElement before, so I'll have to see how deep I want to go into that rabbit hole for adding this mini-feature. 😄
Until then, is this PR not acceptable?

Copy link
Member

Choose a reason for hiding this comment

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

I would not like to merge it as is, if you want to keep the Polymer you can use:

  static get properties() {
    return {
	  ...,
      notifications: {
        type: Array,
        computed: "_computeNotifications(open, hass, _notificationsBackend)",
        observer: "_notificationsChanged",
      },
      ...,
    };
  }

  _notificationsChanged(newNotifications, oldNotifications) {
    if (this.open && oldNotifications.length && !newNotifications.length) {
      this.open = false;
    }
  }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wasn't aware of the newNotifications, oldNotifications arguments to the observer function. This is a much easier approach. Thanks for the suggestion!

I adjusted the PR and propose merging like this. If I feel up for it, I'll create a separate PR for a LitElement rewrite, but don't want to commit to it at this time.

Using the observer pattern instead subscribing to change events for notification changes simplifies the implementation noticeably.
@bramkragten bramkragten merged commit d9a954c into home-assistant:dev Oct 12, 2020
@mattmattmatt mattmattmatt deleted the close-notifications-after-last-dismiss branch October 15, 2020 21:26
@bramkragten bramkragten mentioned this pull request Oct 21, 2020
@github-actions github-actions bot locked and limited conversation to collaborators Jul 5, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants