do not deactivate buttons during transition

Closes #94
This commit is contained in:
Adam Bradley
2015-09-09 10:03:48 -05:00
parent 72b419030a
commit e46863640e
5 changed files with 62 additions and 37 deletions

View File

@ -39,6 +39,7 @@ export class IonicApp {
*/ */
constructor() { constructor() {
this.overlays = []; this.overlays = [];
this._isTransitioning = false;
// Our component registry map // Our component registry map
this.components = {}; this.components = {};
@ -74,6 +75,24 @@ export class IonicApp {
document.title = val; document.title = val;
} }
/**
* Sets if the app is currently transitioning or not. For example
* this is set to `true` while views transition, a modal slides up, an action-menu
* slides up, etc. After the transition completes it is set back to `false`.
* @param {bool} isTransitioning
*/
setTransitioning(isTransitioning) {
this._isTransitioning = !!isTransitioning;
}
/**
* Boolean if the app is actively transitioning or not.
* @return {bool}
*/
isTransitioning() {
return this._isTransitioning;
}
/** /**
* TODO * TODO
* @param {TODO=} val TODO * @param {TODO=} val TODO

View File

@ -128,6 +128,7 @@ export class OverlayRef {
animation.before.addClass('show-overlay'); animation.before.addClass('show-overlay');
ClickBlock(true, animation.duration() + 200); ClickBlock(true, animation.duration() + 200);
this.app.setTransitioning(true);
this.app.zoneRunOutside(() => { this.app.zoneRunOutside(() => {
@ -135,6 +136,7 @@ export class OverlayRef {
this.app.zoneRun(() => { this.app.zoneRun(() => {
ClickBlock(false); ClickBlock(false);
this.app.setTransitioning(false);
animation.dispose(); animation.dispose();
instance.viewDidEnter && instance.viewDidEnter(); instance.viewDidEnter && instance.viewDidEnter();
resolve(); resolve();
@ -160,6 +162,7 @@ export class OverlayRef {
animation.after.removeClass('show-overlay'); animation.after.removeClass('show-overlay');
ClickBlock(true, animation.duration() + 200); ClickBlock(true, animation.duration() + 200);
this.app.setTransitioning(true);
animation.play().then(() => { animation.play().then(() => {
instance.viewDidLeave && instance.viewDidLeave(); instance.viewDidLeave && instance.viewDidLeave();
@ -168,6 +171,7 @@ export class OverlayRef {
this._dispose(); this._dispose();
ClickBlock(false); ClickBlock(false);
this.app.setTransitioning(false);
animation.dispose(); animation.dispose();
resolve(); resolve();

View File

@ -228,6 +228,7 @@ export class TextInput extends Ion {
// manually scroll the text input to the top // manually scroll the text input to the top
// do not allow any clicks while it's scrolling // do not allow any clicks while it's scrolling
ClickBlock(true, SCROLL_INTO_VIEW_DURATION + 100); ClickBlock(true, SCROLL_INTO_VIEW_DURATION + 100);
this.app.setTransitioning(true);
// temporarily move the focus to the focus holder so the browser // temporarily move the focus to the focus holder so the browser
// doesn't freak out while it's trying to get the input in place // doesn't freak out while it's trying to get the input in place
@ -242,6 +243,7 @@ export class TextInput extends Ion {
// all good, allow clicks again // all good, allow clicks again
ClickBlock(false); ClickBlock(false);
this.app.setTransitioning(false);
}); });
} else { } else {

View File

@ -279,6 +279,7 @@ export class ViewController extends Ion {
// block any clicks during the transition and provide a // block any clicks during the transition and provide a
// fallback to remove the clickblock if something goes wrong // fallback to remove the clickblock if something goes wrong
ClickBlock(true, duration + 200); ClickBlock(true, duration + 200);
this.app.setTransitioning(true);
} }
// start the transition // start the transition
@ -396,6 +397,7 @@ export class ViewController extends Ion {
swipeBackProgress(progress) { swipeBackProgress(progress) {
if (this.sbTransition) { if (this.sbTransition) {
ClickBlock(true, 4000); ClickBlock(true, 4000);
this.app.setTransitioning(true);
this.sbTransition.progress( Math.min(1, Math.max(0, progress)) ); this.sbTransition.progress( Math.min(1, Math.max(0, progress)) );
} }
} }
@ -481,6 +483,7 @@ export class ViewController extends Ion {
// allow clicks again // allow clicks again
ClickBlock(false); ClickBlock(false);
this.app.setTransitioning(false);
} }
/** /**

View File

@ -15,6 +15,7 @@ export class Activator {
self.active = {}; self.active = {};
self.activatedClass = 'activated'; self.activatedClass = 'activated';
self.deactivateTimeout = 180; self.deactivateTimeout = 180;
this.deactivateAttempt = 0;
self.pointerTolerance = 4; self.pointerTolerance = 4;
self.isTouch = false; self.isTouch = false;
self.disableClick = 0; self.disableClick = 0;
@ -109,7 +110,8 @@ export class Activator {
mouseDown(ev) { mouseDown(ev) {
if (this.isDisabledClick()) { if (this.isDisabledClick()) {
console.debug('mouseDown prevent'); console.debug('mouseDown prevent');
preventEvent(ev); ev.preventDefault();
ev.stopPropagation();
} else if (!self.isTouch) { } else if (!self.isTouch) {
this.pointerStart(ev); this.pointerStart(ev);
@ -123,7 +125,8 @@ export class Activator {
mouseUp(ev) { mouseUp(ev) {
if (this.isDisabledClick()) { if (this.isDisabledClick()) {
console.debug('mouseUp prevent'); console.debug('mouseUp prevent');
preventEvent(ev); ev.preventDefault();
ev.stopPropagation();
} }
if (!self.isTouch) { if (!self.isTouch) {
@ -153,7 +156,7 @@ export class Activator {
* TODO * TODO
*/ */
pointerEnd(ev) { pointerEnd(ev) {
this.endActive(); this.queueDeactivate();
this.moveListeners(false); this.moveListeners(false);
} }
@ -162,7 +165,7 @@ export class Activator {
*/ */
pointerCancel() { pointerCancel() {
console.debug('pointerCancel') console.debug('pointerCancel')
this.clearActive(); this.deactivate();
this.moveListeners(false); this.moveListeners(false);
this.disableClick = Date.now(); this.disableClick = Date.now();
} }
@ -192,7 +195,8 @@ export class Activator {
click(ev) { click(ev) {
if (!this.allowClick(ev)) { if (!this.allowClick(ev)) {
console.debug('click prevent'); console.debug('click prevent');
preventEvent(ev); ev.preventDefault();
ev.stopPropagation();
} }
this.isTouch = false; this.isTouch = false;
} }
@ -240,50 +244,43 @@ export class Activator {
}); });
} }
endActive() { queueDeactivate() {
const self = this; const self = this;
setTimeout(function() { setTimeout(function() {
self.clearActive(); self.deactivate();
}, this.deactivateTimeout); }, this.deactivateTimeout);
} }
clearActive() { deactivate() {
const self = this; const self = this;
// clear out any elements that are queued to be set to active if (this.app.isTransitioning() && this.deactivateAttempt < 10) {
self.queue = {}; // the app is actively transitioning, don't bother deactivating
// anything this makes it easier on the GPU so it doesn't
// have to redraw any buttons during a transition
// retry
++this.deactivateAttempt;
this.queueDeactivate();
// in the next frame, remove the active class from all active elements } else {
raf(function() { // not actively transitioning, good to deactivate any elements
for (var key in self.active) { // clear out any elements that are queued to be set to active
if (self.active[key]) { self.queue = {};
self.active[key].classList.remove(self.activatedClass);
// in the next frame, remove the active class from all active elements
raf(function() {
for (var key in self.active) {
if (self.active[key]) {
self.active[key].classList.remove(self.activatedClass);
}
delete self.active[key];
} }
delete self.active[key]; });
}
});
}
clickBlock(enable) { this.deactivateAttempt = 0;
console.log('clickBlock', enable);
this.doc.removeEventListener('click', preventEvent, true);
this.doc.removeEventListener('touchmove', preventEvent, true);
this.doc.removeEventListener('touchstart', preventEvent, true);
this.doc.removeEventListener('touchend', preventEvent, true);
if (enable) {
this.doc.addEventListener('click', preventEvent, true);
this.doc.addEventListener('touchmove', preventEvent, true);
this.doc.addEventListener('touchstart', preventEvent, true);
this.doc.addEventListener('touchend', preventEvent, true);
} }
} }
} }
function preventEvent(ev) {
ev.preventDefault();
ev.stopPropagation();
}