From 543b136f7c7428fa3dc06dcaf17b887d60f8ea7b Mon Sep 17 00:00:00 2001 From: Alexander Skvortsov <38059171+askvortsov1@users.noreply.github.com> Date: Thu, 15 Oct 2020 17:34:35 -0400 Subject: [PATCH] Refactor PostStream animations (#2364) - If the fadeIn animation is specified on the PostStream class itself, any time we add/remove another animation, it will redo fadeIn. To avoid this, we move fadeIn into it's own css class, which is applied, and then immediately removed after the animation is completed to ensure it only runs once. - The "fix" for flashItem was actually broken, as it resulted in 'flash' never being removed, so we never went back to .PostStream's fadeIn. We adjust flashItem to ensure that '.flash' is removed. We also remove 'fadeIn' in case it hasn't yet been removed in oncreate. --- js/src/forum/components/PostStream.js | 17 +++++++++++++---- less/forum/PostStream.less | 24 +++++++++++++----------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/js/src/forum/components/PostStream.js b/js/src/forum/components/PostStream.js index 667d27694..fcff6e723 100644 --- a/js/src/forum/components/PostStream.js +++ b/js/src/forum/components/PostStream.js @@ -32,6 +32,13 @@ export default class PostStream extends Component { const posts = this.stream.posts(); const postIds = this.discussion.postIds(); + const postFadeIn = (vnode) => { + $(vnode.dom).addClass('fadeIn'); + // 500 is the duration of the fadeIn CSS animation + 100ms, + // so the animation has time to complete + setTimeout(() => $(vnode.dom).removeClass('fadeIn'), 500); + }; + const items = posts.map((post, i) => { let content; const attrs = { 'data-index': this.stream.visibleStart + i }; @@ -42,6 +49,7 @@ export default class PostStream extends Component { content = PostComponent ? PostComponent.component({ post }) : ''; attrs.key = 'post' + post.id(); + attrs.oncreate = postFadeIn; attrs['data-time'] = time.toISOString(); attrs['data-number'] = post.number(); attrs['data-id'] = post.id(); @@ -89,7 +97,7 @@ export default class PostStream extends Component { // is not already doing so, then show a 'write a reply' placeholder. if (viewingEnd && (!app.session.user || this.discussion.canReply())) { items.push( -
+
{ReplyPlaceholder.component({ discussion: this.discussion })}
); @@ -389,10 +397,11 @@ export default class PostStream extends Component { * @param {jQuery} $item */ flashItem($item) { + // This might execute before the fadeIn class has been removed in PostStreamItem's + // oncreate, so we remove it just to be safe and avoid a double animation. + $item.removeClass('fadeIn'); $item.addClass('flash').on('animationend webkitAnimationEnd', (e) => { - if (e.animationName === 'fadeIn') { - $item.removeClass('flash'); - } + $item.removeClass('flash'); }); } } diff --git a/less/forum/PostStream.less b/less/forum/PostStream.less index b4ea701f8..9e649cb3b 100644 --- a/less/forum/PostStream.less +++ b/less/forum/PostStream.less @@ -6,18 +6,7 @@ margin-top: 10px; } } - -@-webkit-keyframes fadeIn { - 0% {opacity: 0} - 100% {opacity: 1} -} -@keyframes fadeIn { - 0% {opacity: 0} - 100% {opacity: 1} -} .PostStream-item { - .animation(fadeIn 0.4s ease-in-out); - &:not(:last-child) { border-bottom: 1px solid @control-bg; @@ -104,3 +93,16 @@ .animation(pulsate 0.2s ease-in-out); .animation-iteration-count(1); } + +@-webkit-keyframes fadeIn { + 0% {opacity: 0} + 100% {opacity: 1} +} +@keyframes fadeIn { + 0% {opacity: 0} + 100% {opacity: 1} +} +.fadeIn { + .animation(fadeIn 0.4s ease-in-out); + .animation-iteration-count(1); +}