Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid browser freeze when copy paste icon in icon picker #14387

Closed
wants to merge 5 commits into from

Conversation

piitaya
Copy link
Member

@piitaya piitaya commented Nov 15, 2022

Proposed change

Avoid browser freeze when copy paste icon in icon picker. I just did not understand why. It also depends of the pasted content. Setting filteredItems async fixes the problem.

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:

@piitaya piitaya force-pushed the fix_browser_freeze_copy_paste branch from 4af2379 to 0ab938d Compare November 15, 2022 15:27
this.comboBox.filteredItems = filteredItems;
// Setting it sync cause browser freeze when user paste an icon text
setTimeout(() => {
this.comboBox.filteredItems = filteredItems;
Copy link
Member

Choose a reason for hiding this comment

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

I think this is a dirty fix to a bigger problem. The problem I think stems from going behind lit's back to update the items instead of tying them to a reactive property. So whenever a litElement update is triggered, you are starting over with iconItems because that's in render.

Instead, @property the filtered items, update them on input, and let lit handle the update.

Copy link
Member Author

@piitaya piitaya Nov 15, 2022

Choose a reason for hiding this comment

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

Yes you right. I think the filtered items assignment is old code to avoid re-rendering the whole input (created before ha-combobox) but it doesn't make sense anymore. I will look to refactor the component 🙂

Copy link
Member

Choose a reason for hiding this comment

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

👍 I think you could probably keep most as is and just replace this.combobox.filteredItems everywhere with a reactive property update. Might also need to call this.requestUpdate() if the property is only mutated.

Copy link
Member Author

@piitaya piitaya Nov 16, 2022

Choose a reason for hiding this comment

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

I changed it to a reactive state but the setTimeout is always needed... 😕 I have the same behavior. I didn't understand why it's just when pasting a text...

Copy link
Member

Choose a reason for hiding this comment

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

Well, at least it's cleaner now 😜

I was so in disbelief that this actually fixes the problem that I pulled the branch down to try it out. When I test, the initial paste into an empty field goes smoothly, but then I can repeatedly crash the browser by:

  1. Tab to the next field
  2. Shift+tab back to the icon picker
  3. Paste over the 1st paste or just delete it and paste again

I'll try to spend a few more minutes on it to see if I can narrow it down.

Copy link
Member Author

Choose a reason for hiding this comment

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

It also depend of the content paste. If you paste mdi:home, it crash. If you paste mdi:account it doesn't crash. I think the proper solution is to use web worker for the filter to do the search in a background thread.

bramkragten
bramkragten previously approved these changes Nov 16, 2022
@piitaya
Copy link
Member Author

piitaya commented Nov 17, 2022

Doing the computation in background seems to work. I also removed the minimum characters count because it's not needed anymore.

bramkragten
bramkragten previously approved these changes Nov 17, 2022
@steverep
Copy link
Member

My hypothesis last night was that the pastes are probably just firing too many filter-changed events, triggering multiple racing computations. I started to try a fix but didn't get a chance to finish last night. You beat me to it but I finished anyway and it worked great. Here's what I did:

  1. Make the filter-changed listener just set a this._filterString reactive state.
  2. Move the remaining code to perform the filter to render(). This way lit will ensure it only happens once per update (and probably only once per paste)
  3. For the open-changed listener, just call this.requestUpdate() after load instead of setting the filtered items.

This seems to work smoothly no matter what I paste or how many times. I can push it to another branch if you want to take a look, but it was pretty simple.

PS - I also noticed a potential issue when loading custom icon sets but that's unrelated to this.

@bramkragten
Copy link
Member

I think a combination of both solutions might be best, depending on how long filtering actually takes with the fix from Steve. (if it is fast, there is no need to do it in a background worker)

@steverep
Copy link
Member

I'll push it out so you guys can take a look and test

@steverep
Copy link
Member

See #14401

@steverep
Copy link
Member

I can still repeatedly cause a crash by using the same technique as above even with the web worker. I can also crash it by quickly typing gibberish into the field.

@piitaya
Copy link
Member Author

piitaya commented Nov 18, 2022

I removed the web worker and I use afterNextRender. I did not reproduce the problem with this change. I can't wait to see if this fixes the problem for you too 😅

@Misiu
Copy link
Contributor

Misiu commented Nov 18, 2022

My hypothesis last night was that the pastes are probably just firing too many filter-changed events, triggering multiple racing computations. I started to try a fix but didn't get a chance to finish last night. You beat me to it but I finished anyway and it worked great. Here's what I did:

Maybe we can debounce the filter changed event? There is an open issue for vaadin combobox (vaadin/web-components#518), so we must add this for now.

@steverep
Copy link
Member

Nope, still crashes 😞

I had a similar idea though, but first did the changes I made in #14401 make any difference for you?

@piitaya
Copy link
Member Author

piitaya commented Nov 18, 2022

Still crashes too 😕
I will do some tests next week with cross devices and browsers tests : Windows 10, Mac OS, iOS and Android (Chrome/Firefox/Safari).

@steverep
Copy link
Member

Okay, one more trick to try... I'll push in a minute or two

@steverep steverep mentioned this pull request Nov 18, 2022
8 tasks
@piitaya piitaya force-pushed the fix_browser_freeze_copy_paste branch from b3803d8 to 900b9cd Compare November 21, 2022 10:35
@piitaya
Copy link
Member Author

piitaya commented Nov 21, 2022

I rebased the PR to have the last vaadin version.

I tested of several devices and saw no issues.

  • MacOS - Chrome
  • MacOS - Firefox
  • MacOS - Safari
  • iOS - Safari
  • Windows 11 - Chrome
  • WIndows 11 - Edge
  • Windows 11 - Firefox
  • Android - Chrome

Test protocol :

  • Open default dashboard
  • Click on the first entity displayed
  • Click on settings page in more-info dialog
  • Paste mdi:home text in the icon picker

@steverep Can you confirm the issue is fixed for you too? If not, can you describe the steps to reproduce it ? 🙂

@steverep
Copy link
Member

Nope, this branch still has the issue for me on Windows 10 with Chrome. Firefox seems much more resistant because I haven't been able to reproduce it there for a while. Steps are the same as I stated above. Here's more detail:

  1. Load HA with demo content
  2. Open more info then settings tab for CO2 sensor
  3. Paste "mdi:molecule-co2" in icon field (which icon doesn't matter)
  4. Tab to entity field then tab back
  5. Paste "mdi:molecule-co2" again (or another icon)

I think browser is a factor, but if it's a timing issue then any number of factors could affect it.

FYI, I've also tried many other things without success, including completely removing the rendering of icons in the overlay and field. I'm thinking we should treat this as a vaadin bug and solicit their help.

@steverep
Copy link
Member

steverep commented Dec 2, 2022

Closing since #14401 was merged.

@steverep steverep closed this Dec 2, 2022
@steverep steverep deleted the fix_browser_freeze_copy_paste branch January 11, 2023 06:11
@github-actions github-actions bot locked and limited conversation to collaborators Jan 11, 2024
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.

Pasting Icon Text name in Entity Icon Field Causes Freeze of Dashboard.
4 participants