artemsky / vue-snotify

Vuejs 2 Notification Center
https://artemsky.github.io/vue-snotify/
MIT License
795 stars 98 forks source link

[Bug] Backdrop not removed when 2 notifications with same timeout #57

Open Meshz opened 6 years ago

Meshz commented 6 years ago

Hello,

First of all, thank you for this package. I noticed that when you programatically call 2 notifications with the same timeout, the backdrop is not removed. Do you have any solution for this problem?

Thank you!

alekstar79 commented 6 years ago

I have the same problem when I call a notification with the backdrop enabled, the following notification calls also work with the backdrop enabled, ignoring the configuration settings. Does not help even a forced call to vm.$snotify.setDefaults(config: SnotifyDefaults)

Meshz commented 6 years ago

Hello,

As I had many problems with this bug, I tweaked your package by adding an initTime to each toast (timestamp divided by 100 and rounded for precision purposes): this.toast.initTime = Math.round(+new Date()/100) in initToast method. Then in stateChanged method, I loop through each toast and group them by initTime. So when 2 toasts are launched at the same time, they are seen as one.

For some reason I had to change the template to (_vm.backdrop > 0) instead of (_vm.backdrop >= 0) because the line setTimeout(function () { return _this.$snotify.remove(_this.toast.id, true); }, _this.toast.config.animation.time / 2) in onRemove method seems to recreate a backdrop with 0 opacity.

HTH you finding a way to fix this. Thank you again!

Mornney commented 6 years ago

I am having a similar issue with the backdrop not being removed.

I found this in the JS file: // TODO: fix backdrop if more than one toast called in a row

Any news on when this will be fixed? Does anyone know a work around, at the moment the backdrop dosesnt get removed which then prevents users being able to access the form behind the backdrop

Meshz commented 6 years ago

Basically, my fix is explained in my previous post. But here is what I did for now in vue-snotify.esm.js (kinda ugly but it works). HTH!

// --- Line 323
initToast: function () {
    this.toast.initTime = Math.round(+new Date()/100); // Added initTime
    if (this.toast.config.timeout > 0) {
        this.startTimeout(0);
    }
}
// --- Line 634
stateChanged: function (event) {
    let toastShown = []
    if (!this.withBackdrop.length) {
        return;
    } else {
        // --- Group toasts by initTime
        for (let i=0; i<this.withBackdrop.length; i++) {
            if(toastShown.indexOf(this.withBackdrop[i].initTime) == -1){
                toastShown.push(this.withBackdrop[i].initTime);
            }
        }
    }
    switch (event) {
        case 'mounted':
            if (this.backdrop < 0) {
                this.backdrop = 0;
            }
            break;
        case 'beforeShow':
            this.backdrop = this.withBackdrop[this.withBackdrop.length - 1].config.backdrop;
            break;
        case 'beforeHide':
            // --- Use groups to determine if one or more toasts shown
            if (toastShown.length === 1) {
                this.backdrop = 0;
            }
            break;
        case 'hidden':
            // --- Same as beforeHide
            if (toastShown.length === 1) {
                this.backdrop = -1;
            }
            break;
        }
    }
}
// --- Line 695
// --- Changed condition _vm.backdrop >= 0 to _vm.backdrop > 0 because backdrop is recreated with 0 opacity by second timeout in onRemove (line 400)
var __vue_render__$3 = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[(_vm.backdrop > 0)?_c('div',{staticClass:"snotify-backdrop",style:({opacity: _vm.backdrop})}):_vm._e(),_vm._v(" "),_vm._l((_vm.notifications),function(position,index){return _c('div',{staticClass:"snotify",class:'snotify-' + index},_vm._l((_vm.notifications[index].slice(_vm.blockSize_a, _vm.blockSize_b)),function(toast){return _c('toast',{key:toast.id,attrs:{"toastData":toast},on:{"stateChanged":_vm.stateChanged}})}))})],2)};
Mornney commented 6 years ago

Thank you, will have a look at trying this.

Its better than my work around :)

jeffbarretocopam commented 5 years ago

Basically, my fix is explained in my previous post. But here is what I did for now in vue-snotify.esm.js (kinda ugly but it works). HTH!

// --- Line 323
initToast: function () {
  this.toast.initTime = Math.round(+new Date()/100); // Added initTime
  if (this.toast.config.timeout > 0) {
      this.startTimeout(0);
  }
}
// --- Line 634
stateChanged: function (event) {
  let toastShown = []
  if (!this.withBackdrop.length) {
      return;
  } else {
      // --- Group toasts by initTime
      for (let i=0; i<this.withBackdrop.length; i++) {
          if(toastShown.indexOf(this.withBackdrop[i].initTime) == -1){
              toastShown.push(this.withBackdrop[i].initTime);
          }
      }
  }
  switch (event) {
      case 'mounted':
          if (this.backdrop < 0) {
              this.backdrop = 0;
          }
          break;
      case 'beforeShow':
          this.backdrop = this.withBackdrop[this.withBackdrop.length - 1].config.backdrop;
          break;
      case 'beforeHide':
          // --- Use groups to determine if one or more toasts shown
          if (toastShown.length === 1) {
              this.backdrop = 0;
          }
          break;
      case 'hidden':
          // --- Same as beforeHide
          if (toastShown.length === 1) {
              this.backdrop = -1;
          }
          break;
      }
  }
}
// --- Line 695
// --- Changed condition _vm.backdrop >= 0 to _vm.backdrop > 0 because backdrop is recreated with 0 opacity by second timeout in onRemove (line 400)
var __vue_render__$3 = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[(_vm.backdrop > 0)?_c('div',{staticClass:"snotify-backdrop",style:({opacity: _vm.backdrop})}):_vm._e(),_vm._v(" "),_vm._l((_vm.notifications),function(position,index){return _c('div',{staticClass:"snotify",class:'snotify-' + index},_vm._l((_vm.notifications[index].slice(_vm.blockSize_a, _vm.blockSize_b)),function(toast){return _c('toast',{key:toast.id,attrs:{"toastData":toast},on:{"stateChanged":_vm.stateChanged}})}))})],2)};

Why you don't create that PR ? This is one of the solution