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

fix(toast): deduplicate toasts with same key #2657

Merged
merged 10 commits into from
Jan 22, 2020

Conversation

foodforarabbit
Copy link
Contributor

Fixes #2333

Description

  • fixed typing on some of the functions. There was a type ToastPropsShapeT (ToastPropsT minus children) being used for state.toasts and for the return value of getToastProps(), but actually the children prop is in both. children is separate in the toaster.show() function but then it is recombined in the toasterInstance.show() function.
  • added helper function updateToastsMutationWithCount which performs the original toast update mutation but also returns the number of toasts updated
  • added updateToastsMutationWithCount to toasterInstance.show() function - it will attempt to update toasts with matching key prop first, and then only push the new toast if nothing was updated
  • clear existing autohide timeout in Toast.startTimeout if it already exists (i.e. reset the autohide timer)
  • call Toast.startTimeout in componentDidUpdate ONLY if autoHideDuration property is changed - we can avoid a deep comparison to figure out if a toast has changed or not. Might want to make this more explicit somehow - suggestions welcome
  • used Layer instead of creating a portal manually to the body
  • added new scenario and e2e test for normal toast behaviour (no key provided, autogenerate key and pop up additional toasts) and same-key behaviour (if toast with same key found, update it instead of popping up a new one)
  • added some text on the documentation page about toaster utility and the same-key update situation

Scope

  • Patch: Bug Fix
  • Minor: New Feature
  • Major: Breaking Change

@vercel
Copy link

vercel bot commented Jan 19, 2020

This pull request is being automatically deployed with ZEIT Now (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://zeit.co/uber-ui-platform/baseweb/8hbcmffgn
✅ Preview: https://baseweb-git-fork-foodforarabbit-toast-de-duplicate.uber-ui-platform.now.sh

@foodforarabbit
Copy link
Contributor Author

foodforarabbit commented Jan 19, 2020

actually I was thinking we could implement a hidden counter in the toast config (e.g. __updated) that is increased every time a toast is updated. That way, we could know when to reset the autohide timer without any expensive comparisons while also making it automatic (right now I'm simply comparing autoHideDuration so to reset the autohide timer, you need to change this. Seems a bit hacky though). Not sure if this discussion belongs here or in the original issue though.

something like this:

    toasts.forEach((t, index, arr) => {
      if (t.key === key) {
        const toastUpdateCount = parseInt(t.__updated) || 0
        arr[index] = {...t, __updated: toastUpdateCount + 1, ...this.getToastProps(props), key};
      }
    });

@UberOpenSourceBot
Copy link
Contributor

Visual changes were detected on this branch. Please review the following PR containing updated snapshots: foodforarabbit#1

@houmark
Copy link
Contributor

houmark commented Jan 21, 2020

Excited about this PR. I did not have the chance to test it out yet, but it seems like everything annoying about toasts fixed :) Nice work.

@houmark
Copy link
Contributor

houmark commented Jan 21, 2020

About the autoHideDuration — Do I understand it correctly, that to extend an updated toast that had 10000 in its first show, to have another 10 seconds, I will need to submit the update/second show with 10001 for example? Basically a different value than the first time? If I do not submit a value or the same, it will hide 10 seconds after showing the first toast?

A different approach to both of those could be a new prop extendAutoHideDuration so I can decide when updating if I want it to extend the time or not (seems less hacky), but I don't have a strong opinion on either one of the solutions.

Copy link
Collaborator

@chasestarr chasestarr left a comment

Choose a reason for hiding this comment

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

Looks like it's heading in the right direction 👍

I agree that changing the autoHideDuration is not sufficient, and the update count approach seems more appropriate. Another prop called resetAutoHideTimerOnReset or similar can be added to control the behavior. If 'showing' a duplicate toast should it reset the timer by default, or the opposite? I personally am leaning towards reset.

src/toast/toaster.js Outdated Show resolved Hide resolved
documentation-site/components/yard/config/toast.ts Outdated Show resolved Hide resolved
src/toast/toaster.js Show resolved Hide resolved
@houmark
Copy link
Contributor

houmark commented Jan 21, 2020

I agree that changing the autoHideDuration is not sufficient, and the update count approach seems more appropriate. Another prop called resetAutoHideTimerOnReset or similar can be added to control the behavior. If 'showing' a duplicate toast should it reset the timer by default, or the opposite? I personally am leaning towards reset.

Just a naming nitpick. resetAutoHideTimerOnReset should maybe be resetAutoHideTimerOnUpdate?

@foodforarabbit
Copy link
Contributor Author

I agree that changing the autoHideDuration is not sufficient, and the update count approach seems more appropriate. Another prop called resetAutoHideTimerOnReset or similar can be added to control the behavior. If 'showing' a duplicate toast should it reset the timer by default, or the opposite? I personally am leaning towards reset.

Just a naming nitpick. resetAutoHideTimerOnReset should maybe be resetAutoHideTimerOnUpdate?

caught this already :D

@chasestarr
Copy link
Collaborator

I agree that changing the autoHideDuration is not sufficient, and the update count approach seems more appropriate. Another prop called resetAutoHideTimerOnReset or similar can be added to control the behavior. If 'showing' a duplicate toast should it reset the timer by default, or the opposite? I personally am leaning towards reset.

Just a naming nitpick. resetAutoHideTimerOnReset should maybe be resetAutoHideTimerOnUpdate?

caught this already :D

🙄 ah good catch, typo

@chasestarr chasestarr added the ci label Jan 22, 2020
src/toast/toaster.js Outdated Show resolved Hide resolved
@foodforarabbit
Copy link
Contributor Author

foodforarabbit commented Jan 22, 2020 via email

@UberOpenSourceBot
Copy link
Contributor

Visual changes were detected on this branch. Please review the following PR containing updated snapshots: foodforarabbit#1

@chasestarr
Copy link
Collaborator

I think this is good to land once VRT changes are resolved. Thanks for looking into the auto-hide issue and raising the some of the complexities with multiple containers. I'm open to start addressing the placement-by-toast feature. It's not a common pattern, but there's at least one application here that needs it

test(vrt): update visual snapshots for toast-de-duplicate [skip ci]
@foodforarabbit
Copy link
Contributor Author

I think this is good to land once VRT changes are resolved.

Not sure what I need to do with the VRT xD I saw a pull request into my branch and merged it in, saw 3 pngs but not sure what I was looking for.

@chasestarr
Copy link
Collaborator

It's kind of a side-effect of how we combine e2e tests and visual regression tests. In this case, the new screenshots look fine

@chasestarr chasestarr merged commit 4155af2 into uber:master Jan 22, 2020
VladimirMilenko pushed a commit to VladimirMilenko/baseui that referenced this pull request Apr 2, 2020
* fix(toast): deduplicate toasts with same key

* fix(toast): add opt resetAutoHideTimerOnUpdate, update docs, immutable

* fix(toast): fixed documentation and tests

* fix(toast): addressed some code / wording issues

* fix(toast): fixed issues in toast documentation, carry forward autoHideDuration from original toast

* fix(toaster): add warning if another ToasterContainer detected

* fix(toaster): removed warning for multiple ToastContainers

* test(vrt): update visual snapshots for d19e600 [skip ci]

Co-authored-by: UberOpenSourceBot <33560951+UberOpenSourceBot@users.noreply.github.com>
Co-authored-by: Chase Starr <chasestarr@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add ability to de-duplicate toaster notifications
6 participants