showmy.chat icon indicating copy to clipboard operation
showmy.chat copied to clipboard

Remove deletion delay when themes don't animate/transition outgoing messages

Open BenDMyers opened this issue 2 years ago • 11 comments

This feels a bit weird for themes without an animation. I'd expect messages to disappear after the time I set in the urlbuilder on the homepage. For themes with an animation: the animation starts at the time I set. For themes without: do they stay onscreen for the time I set + 1.2s?

Originally posted by @NickyMeuleman in https://github.com/BenDMyers/showmy.chat/pull/91#discussion_r813480092

In #91, showmy.chat added an API to animate messages as they were being deleted (data-twitch-message-display-status="deleting"). However, this meant that we couldn't remove messages immediately — we had to apply the style hook, wait a bit (1.2 seconds), and then delete.

This works great for themes that have outgoing message animations, but it introduces a delay when no animations are used — the overlay user says "remove messages after 5 seconds," and the overlay actually removes them after 6.2 seconds. This isn't noticeable after a long enough message lifespan (the difference between 20 seconds and 21.2 seconds isn't especially profound). However, it would be nice if we could tighten the gap between when the user says to remove messages and when we actually remove them in the case that the theme doesn't animate outgoing messages.

Themes could use either CSS transitions or CSS animations to animate an outgoing message. To detect animations, we've found the getAnimations method, which landed in Chrome 84. With Twitch streamers forced to update their OBS instances soon to continue streaming to Twitch, using >75 Chrome APIs is on the table, but I'd like to give it a few months before we start using >75 APIs just to be safe.

BenDMyers avatar Feb 26 '22 16:02 BenDMyers

do animations fire a transitionend event?

fimion avatar Feb 26 '22 18:02 fimion

@fimion Animations fire an animationend event, but I don't believe they fire transitionend.

We're using both transitionend and animationend as cues to go ahead and remove the element, and they work well from what we've seen.

From src/scripts/utilities.mjs

// Give animation a chance
messageToDelete.addEventListener(
	'transitionend',
	_callbackRemoveMessageFromDom
);
messageToDelete.addEventListener(
	'animationend',
	_callbackRemoveMessageFromDom
);

// If no animation, delete anyways
setTimeout(_callbackRemoveMessageFromDom, 1200);

In case of no animation/transition, or an animation/transition that takes too long, we have that setTimeout call that'll delete the node anyways after 1.2 seconds.

The animationend/transitionend work well — if a theme supplies some sort of "deleting" animation that takes less than 1.2 seconds, it'll be respected, and the element will be deleted immediately after the animation/transition is done.

The trouble here is in cases where themes don't supply a "deleting" animation/transition, meaning that the overlay will wait a full 1.2 seconds to make time for an animation/transition that isn't happening.

BenDMyers avatar Feb 26 '22 18:02 BenDMyers

use getComputedStyles to check for an animation or transition?

fimion avatar Feb 26 '22 19:02 fimion

Also, context on why 1.2 seconds: I figured the absolute longest a "deleting" message should take should be one second. Ideally, deletions would take even less time — since oftentimes, the goal is to clear up space or remove spam and bigotry, and so the goal should be to make sure the message GTFOs. With a 1 second max deletion time, I gave an extra 0.2 sec as a bit of a buffer — hence 1.2 seconds.

BenDMyers avatar Feb 26 '22 19:02 BenDMyers

use getComputedStyles to check for an animation or transition?

@fimion I think this could work! Any chance you'd be interested in (and available for) spinning up a PR?

BenDMyers avatar Feb 26 '22 19:02 BenDMyers

let me take a look at it, because this would also potentially mess with anything that has a transition/animation for insertion or whatever.

fimion avatar Feb 26 '22 19:02 fimion

For sure. For what it's worth, now that we've established data-twitch-message-display-status="deleting" as a precedent, I'd be comfortable setting data-twitch-message-display-status="incoming" (or similar) for new messages, and porting existing themes' entrance animations to that hook.

BenDMyers avatar Feb 26 '22 19:02 BenDMyers

we might also need to set up full FLIP style classes for things so that it is easier to handle transitions/animations

fimion avatar Feb 26 '22 19:02 fimion

Not knowing anything about FLIP, would setting up a FLIP approach like that still afford the stylesheet full control over the entrance/exit animations? (i.e. themes don't have to modify the JavaScript to get custom animations?)

BenDMyers avatar Feb 26 '22 19:02 BenDMyers

correct. the idea behind FLIP is First Last Invert Play. (this is how the vue transition component works.)

Basically, we give 3 classes/attributes for animation/transition.

  1. enter-from/leaving-from state - This is the initial state we need to be in to make the transition work (eg: opacity:0; for our enter-from state, or opacity:1; for our leaving-from state)
  2. enter-active/leaving-active state - this is where you'd define the transition or animation you'd want to use (eg transition: opacity 1s ease;).
  3. enter-to/leaving-to state - this is where you'd apply the end state of your transition (eg opacity:1; for our enter-to state or opacity:0; for our leave-to state)

the implementation works as follows:

apply both the from state and the active state. then remove the from state and apply the to state. listen for transition/animation end and then remove the active and to states.

Let me see if I can get more information about the best way to listen for this.

fimion avatar Feb 26 '22 19:02 fimion

Iiiinteresting. I'd be open to exploring this!

BenDMyers avatar Feb 26 '22 19:02 BenDMyers