Fix: AnimateCSS merge hide() and show() animated css class when we do multiple call (#3200)

PR: #3113  

I see this bugs:

AnimateCSS merge hide() and show() animated css class when we do
multiple call
--> result it will stay en hide state

I think event listener (is animateCSS file) is not a proper solution

I correct it with like traditional code with timer

Fix too: AnimateIn on first start
This commit is contained in:
Bugsounet - Cédric 2023-09-19 20:14:35 +02:00 committed by GitHub
parent af0fe37f70
commit 4eccce3f77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 46 deletions

View File

@ -47,6 +47,7 @@ _This release is scheduled to be released on 2023-10-01._
- Fix ipWhiteList test (#3179) - Fix ipWhiteList test (#3179)
- Fix newsfeed: Convert HTML entities, codes and tag in description (#3191) - Fix newsfeed: Convert HTML entities, codes and tag in description (#3191)
- Respect width/height (no fullscreen) if set in electronOptions (together with `fullscreen: false`) in `config.js` (#3174) - Respect width/height (no fullscreen) if set in electronOptions (together with `fullscreen: false`) in `config.js` (#3174)
- Fix: AnimateCSS merge hide() and show() animated css class when we do multiple call
- Fix `Uncaught SyntaxError: Identifier 'getCorsUrl' has already been declared (at utils.js:1:1)` when using `clock` and `weather` module (#3204) - Fix `Uncaught SyntaxError: Identifier 'getCorsUrl' has already been declared (at utils.js:1:1)` when using `clock` and `weather` module (#3204)
## [2.24.0] - 2023-07-01 ## [2.24.0] - 2023-07-01

View File

@ -130,36 +130,35 @@ const AnimateCSSOut = [
/** /**
* Create an animation with Animate CSS * Create an animation with Animate CSS
* resolved as Promise when done
* @param {string} [element] div element to animate. * @param {string} [element] div element to animate.
* @param {string} [animation] animation name. * @param {string} [animation] animation name.
* @param {number} [animationTime] animation duration. * @param {number} [animationTime] animation duration.
*/ */
function AnimateCSS(element, animation, animationTime) { function addAnimateCSS(element, animation, animationTime) {
/* We create a Promise and return it */ const animationName = `animate__${animation}`;
return new Promise((resolve) => { const node = document.getElementById(element);
const animationName = `animate__${animation}`; if (!node) {
const node = document.getElementById(element); // don't execute animate: we don't find div
if (!node) { Log.warn(`addAnimateCSS: node not found for`, element);
// don't execute animate and resolve return;
Log.warn(`AnimateCSS: node not found for`, element); }
resolve(); node.style.setProperty("--animate-duration", `${animationTime}s`);
return; node.classList.add("animate__animated", animationName);
} }
node.style.setProperty("--animate-duration", `${animationTime}s`);
node.classList.add("animate__animated", animationName); /**
* Remove an animation with Animate CSS
/** * @param {string} [element] div element to animate.
* When the animation ends, we clean the classes and resolve the Promise * @param {string} [animation] animation name.
* @param {object} event object */
*/ function removeAnimateCSS(element, animation) {
function handleAnimationEnd(event) { const animationName = `animate__${animation}`;
node.classList.remove("animate__animated", animationName); const node = document.getElementById(element);
node.style.removeProperty("--animate-duration", `${animationTime}s`); if (!node) {
event.stopPropagation(); // don't execute animate: we don't find div
resolve(); Log.warn(`removeAnimateCSS: node not found for`, element);
} return;
}
node.addEventListener("animationend", handleAnimationEnd, { once: true }); node.classList.remove("animate__animated", animationName);
}); node.style.removeProperty("--animate-duration");
} }

View File

@ -1,4 +1,4 @@
/* global Loader, defaults, Translator, AnimateCSS, AnimateCSSIn, AnimateCSSOut */ /* global Loader, defaults, Translator, addAnimateCSS, removeAnimateCSS, AnimateCSSIn, AnimateCSSOut */
/* MagicMirror² /* MagicMirror²
* Main System * Main System
@ -57,7 +57,7 @@ const MM = (function () {
// create the domCreationPromise with AnimateCSS (with animateIn of module definition) // create the domCreationPromise with AnimateCSS (with animateIn of module definition)
// or just display it // or just display it
var domCreationPromise; var domCreationPromise;
if (haveAnimateIn) domCreationPromise = updateDom(module, 1000, null, haveAnimateIn, true); if (haveAnimateIn) domCreationPromise = updateDom(module, { options: { speed: 1000, animate: { in: haveAnimateIn } } }, true);
else domCreationPromise = updateDom(module, 0); else domCreationPromise = updateDom(module, 0);
domCreationPromises.push(domCreationPromise); domCreationPromises.push(domCreationPromise);
@ -269,7 +269,7 @@ const MM = (function () {
* @param {Function} callback Called when the animation is done. * @param {Function} callback Called when the animation is done.
* @param {object} [options] Optional settings for the hide method. * @param {object} [options] Optional settings for the hide method.
*/ */
const hideModule = async function (module, speed, callback, options = {}) { const hideModule = function (module, speed, callback, options = {}) {
// set lockString if set in options. // set lockString if set in options.
if (options.lockString) { if (options.lockString) {
// Log.log("Has lockstring: " + options.lockString); // Log.log("Has lockstring: " + options.lockString);
@ -281,7 +281,17 @@ const MM = (function () {
const moduleWrapper = document.getElementById(module.identifier); const moduleWrapper = document.getElementById(module.identifier);
if (moduleWrapper !== null) { if (moduleWrapper !== null) {
clearTimeout(module.showHideTimer); clearTimeout(module.showHideTimer);
// reset all animations if needed
if (module.hasAnimateOut) {
removeAnimateCSS(module.identifier, module.hasAnimateOut);
Log.debug(`${module.identifier} Force remove animateOut (in hide): ${module.hasAnimateOut}`);
module.hasAnimateOut = false;
}
if (module.hasAnimateIn) {
removeAnimateCSS(module.identifier, module.hasAnimateIn);
Log.debug(`${module.identifier} Force remove animateIn (in hide): ${module.hasAnimateIn}`);
module.hasAnimateIn = false;
}
// haveAnimateName for verify if we are using AninateCSS library // haveAnimateName for verify if we are using AninateCSS library
// we check AnimateCSSOut Array for validate it // we check AnimateCSSOut Array for validate it
// and finaly return the animate name or `null` (for default MM² animation) // and finaly return the animate name or `null` (for default MM² animation)
@ -294,16 +304,22 @@ const MM = (function () {
if (haveAnimateName) { if (haveAnimateName) {
// with AnimateCSS // with AnimateCSS
Log.debug(`${module.identifier} Has animateOut: ${haveAnimateName}`); Log.debug(`${module.identifier} Has animateOut: ${haveAnimateName}`);
await AnimateCSS(module.identifier, haveAnimateName, speed / 1000); module.hasAnimateOut = haveAnimateName;
// AnimateCSS is now done addAnimateCSS(module.identifier, haveAnimateName, speed / 1000);
moduleWrapper.style.opacity = 0; module.showHideTimer = setTimeout(function () {
moduleWrapper.classList.add("hidden"); removeAnimateCSS(module.identifier, haveAnimateName);
moduleWrapper.style.position = "fixed"; Log.debug(`${module.identifier} Remove animateOut: ${module.hasAnimateOut}`);
// AnimateCSS is now done
moduleWrapper.style.opacity = 0;
moduleWrapper.classList.add("hidden");
moduleWrapper.style.position = "fixed";
module.hasAnimateOut = false;
updateWrapperStates(); updateWrapperStates();
if (typeof callback === "function") { if (typeof callback === "function") {
callback(); callback();
} }
}, speed);
} else { } else {
// default MM² Animate // default MM² Animate
moduleWrapper.style.transition = `opacity ${speed / 1000}s`; moduleWrapper.style.transition = `opacity ${speed / 1000}s`;
@ -338,7 +354,7 @@ const MM = (function () {
* @param {Function} callback Called when the animation is done. * @param {Function} callback Called when the animation is done.
* @param {object} [options] Optional settings for the show method. * @param {object} [options] Optional settings for the show method.
*/ */
const showModule = async function (module, speed, callback, options = {}) { const showModule = function (module, speed, callback, options = {}) {
// remove lockString if set in options. // remove lockString if set in options.
if (options.lockString) { if (options.lockString) {
const index = module.lockStrings.indexOf(options.lockString); const index = module.lockStrings.indexOf(options.lockString);
@ -356,6 +372,17 @@ const MM = (function () {
} }
return; return;
} }
// reset all animations if needed
if (module.hasAnimateOut) {
removeAnimateCSS(module.identifier, module.hasAnimateOut);
Log.debug(`${module.identifier} Force remove animateOut (in show): ${module.hasAnimateOut}`);
module.hasAnimateOut = false;
}
if (module.hasAnimateIn) {
removeAnimateCSS(module.identifier, module.hasAnimateIn);
Log.debug(`${module.identifier} Force remove animateIn (in show): ${module.hasAnimateIn}`);
module.hasAnimateIn = false;
}
module.hidden = false; module.hidden = false;
@ -392,10 +419,16 @@ const MM = (function () {
if (haveAnimateName) { if (haveAnimateName) {
// with AnimateCSS // with AnimateCSS
Log.debug(`${module.identifier} Has animateIn: ${haveAnimateName}`); Log.debug(`${module.identifier} Has animateIn: ${haveAnimateName}`);
await AnimateCSS(module.identifier, haveAnimateName, speed / 1000); module.hasAnimateIn = haveAnimateName;
if (typeof callback === "function") { addAnimateCSS(module.identifier, haveAnimateName, speed / 1000);
callback(); module.showHideTimer = setTimeout(function () {
} removeAnimateCSS(module.identifier, haveAnimateName);
Log.debug(`${module.identifier} Remove animateIn: ${haveAnimateName}`);
module.hasAnimateIn = false;
if (typeof callback === "function") {
callback();
}
}, speed);
} else { } else {
// default MM² Animate // default MM² Animate
module.showHideTimer = setTimeout(function () { module.showHideTimer = setTimeout(function () {

View File

@ -205,6 +205,8 @@ const Module = Class.extend({
this.name = data.name; this.name = data.name;
this.identifier = data.identifier; this.identifier = data.identifier;
this.hidden = false; this.hidden = false;
this.hasAnimateIn = false;
this.hasAnimateOut = false;
this.setConfig(data.config, data.configDeepMerge); this.setConfig(data.config, data.configDeepMerge);
}, },