From 8ca9797c0fe13ce7a18a5916a80c631898f5bb11 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Mon, 9 Jan 2017 16:44:37 -0600 Subject: [PATCH] fix(clickblock): add NavOptions.minClickBlockDuration * feat(clickblock): ability to set a minimum duration for click block * fix(clickblock): add NavOptions.minClickBlockDuration --- .../action-sheet/action-sheet-component.ts | 6 +++++- src/components/action-sheet/action-sheet.ts | 1 + src/components/alert/alert-component.ts | 6 +++++- src/components/alert/alert.ts | 1 + src/components/app/app.ts | 6 +++--- src/components/modal/modal-component.ts | 6 +++++- src/components/modal/modal.ts | 1 + src/navigation/nav-controller-base.ts | 2 +- src/navigation/nav-util.ts | 1 + src/navigation/view-controller.ts | 6 ++++++ src/themes/util.scss | 4 ++-- src/util/click-block.ts | 20 ++++++++++++++++++- 12 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/components/action-sheet/action-sheet-component.ts b/src/components/action-sheet/action-sheet-component.ts index e0af981f875..24b623964f3 100644 --- a/src/components/action-sheet/action-sheet-component.ts +++ b/src/components/action-sheet/action-sheet-component.ts @@ -6,6 +6,7 @@ import { Config } from '../../config/config'; import { Key } from '../../platform/key'; import { Platform } from '../../platform/platform'; import { NavParams } from '../../navigation/nav-params'; +import { NavOptions } from '../../navigation/nav-util'; import { ViewController } from '../../navigation/view-controller'; /** @@ -174,7 +175,10 @@ export class ActionSheetCmp { } dismiss(role: any): Promise { - return this._viewCtrl.dismiss(null, role); + const opts: NavOptions = { + minClickBlockDuration: 400 + }; + return this._viewCtrl.dismiss(null, role, opts); } ngOnDestroy() { diff --git a/src/components/action-sheet/action-sheet.ts b/src/components/action-sheet/action-sheet.ts index 4fd9a043a0e..c1539077eb8 100644 --- a/src/components/action-sheet/action-sheet.ts +++ b/src/components/action-sheet/action-sheet.ts @@ -58,6 +58,7 @@ export class ActionSheet extends ViewController { * @returns {Promise} Returns a promise which is resolved when the transition has completed. */ present(navOptions: NavOptions = {}) { + navOptions.minClickBlockDuration = navOptions.minClickBlockDuration || 400; return this._app.present(this, navOptions); } diff --git a/src/components/alert/alert-component.ts b/src/components/alert/alert-component.ts index 50a15d60c20..7f3e84871f0 100644 --- a/src/components/alert/alert-component.ts +++ b/src/components/alert/alert-component.ts @@ -6,6 +6,7 @@ import { GestureController, BlockerDelegate, BLOCK_ALL } from '../../gestures/ge import { isPresent, assert } from '../../util/util'; import { Key } from '../../platform/key'; import { NavParams } from '../../navigation/nav-params'; +import { NavOptions } from '../../navigation/nav-util'; import { Platform } from '../../platform/platform'; import { ViewController } from '../../navigation/view-controller'; @@ -298,7 +299,10 @@ export class AlertCmp { } dismiss(role: any): Promise { - return this._viewCtrl.dismiss(this.getValues(), role); + const opts: NavOptions = { + minClickBlockDuration: 400 + }; + return this._viewCtrl.dismiss(this.getValues(), role, opts); } getValues(): any { diff --git a/src/components/alert/alert.ts b/src/components/alert/alert.ts index d57b2eef070..98b1ca5320e 100644 --- a/src/components/alert/alert.ts +++ b/src/components/alert/alert.ts @@ -81,6 +81,7 @@ export class Alert extends ViewController { * @returns {Promise} Returns a promise which is resolved when the transition has completed. */ present(navOptions: NavOptions = {}) { + navOptions.minClickBlockDuration = navOptions.minClickBlockDuration || 400; return this._app.present(this, navOptions); } diff --git a/src/components/app/app.ts b/src/components/app/app.ts index 40ea124f815..67ba961bd06 100644 --- a/src/components/app/app.ts +++ b/src/components/app/app.ts @@ -119,17 +119,17 @@ export class App { * it will automatically enable the app again. It's basically a fallback incase * something goes wrong during a transition and the app wasn't re-enabled correctly. */ - setEnabled(isEnabled: boolean, duration: number = 700) { + setEnabled(isEnabled: boolean, duration: number = 700, minDuration: number = 0) { this._disTime = (isEnabled ? 0 : Date.now() + duration); if (this._clickBlock) { if (isEnabled) { // disable the click block if it's enabled, or the duration is tiny - this._clickBlock.activate(false, CLICK_BLOCK_BUFFER_IN_MILLIS); + this._clickBlock.activate(false, CLICK_BLOCK_BUFFER_IN_MILLIS, minDuration); } else { // show the click block for duration + some number - this._clickBlock.activate(true, duration + CLICK_BLOCK_BUFFER_IN_MILLIS); + this._clickBlock.activate(true, duration + CLICK_BLOCK_BUFFER_IN_MILLIS, minDuration); } } } diff --git a/src/components/modal/modal-component.ts b/src/components/modal/modal-component.ts index fa2ace7190e..e0e086ae78c 100644 --- a/src/components/modal/modal-component.ts +++ b/src/components/modal/modal-component.ts @@ -2,6 +2,7 @@ import { Component, ComponentFactoryResolver, HostListener, Renderer, ViewChild, import { Key } from '../../platform/key'; import { NavParams } from '../../navigation/nav-params'; +import { NavOptions } from '../../navigation/nav-util'; import { ViewController } from '../../navigation/view-controller'; import { GestureController, BlockerDelegate, GESTURE_MENU_SWIPE, GESTURE_GO_BACK_SWIPE } from '../../gestures/gesture-controller'; import { assert } from '../../util/util'; @@ -78,7 +79,10 @@ export class ModalCmp { _bdClick() { if (this._enabled && this._bdDismiss) { - return this._viewCtrl.dismiss(null, 'backdrop').catch(() => { + const opts: NavOptions = { + minClickBlockDuration: 400 + }; + return this._viewCtrl.dismiss(null, 'backdrop', opts).catch(() => { console.debug('Dismiss modal by clicking backdrop was cancelled'); }); } diff --git a/src/components/modal/modal.ts b/src/components/modal/modal.ts index 0290da474f0..aa6077a35db 100644 --- a/src/components/modal/modal.ts +++ b/src/components/modal/modal.ts @@ -58,6 +58,7 @@ export class Modal extends ViewController { * @returns {Promise} Returns a promise which is resolved when the transition has completed. */ present(navOptions: NavOptions = {}) { + navOptions.minClickBlockDuration = navOptions.minClickBlockDuration || 400; return this._app.present(this, navOptions, AppPortal.MODAL); } diff --git a/src/navigation/nav-controller-base.ts b/src/navigation/nav-controller-base.ts index ac2061f6637..c89e5daeefc 100644 --- a/src/navigation/nav-controller-base.ts +++ b/src/navigation/nav-controller-base.ts @@ -663,7 +663,7 @@ export class NavControllerBase extends Ion implements NavController { if (duration > DISABLE_APP_MINIMUM_DURATION && opts.disableApp !== false) { // if this transition has a duration and this is the root transition // then set that the app is actively disabled - this._app.setEnabled(false, duration + ACTIVE_TRANSITION_OFFSET); + this._app.setEnabled(false, duration + ACTIVE_TRANSITION_OFFSET, opts.minClickBlockDuration); } else { console.debug('transition is running but app has not been disabled'); } diff --git a/src/navigation/nav-util.ts b/src/navigation/nav-util.ts index 989f8b41e0e..aade5a88e77 100644 --- a/src/navigation/nav-util.ts +++ b/src/navigation/nav-util.ts @@ -162,6 +162,7 @@ export interface NavOptions { keyboardClose?: boolean; progressAnimation?: boolean; disableApp?: boolean; + minClickBlockDuration?: number; ev?: any; updateUrl?: boolean; isNavRoot?: boolean; diff --git a/src/navigation/view-controller.ts b/src/navigation/view-controller.ts index 3059778c6df..4c852033cac 100644 --- a/src/navigation/view-controller.ts +++ b/src/navigation/view-controller.ts @@ -167,6 +167,12 @@ export class ViewController { if (!this._nav) { return Promise.resolve(false); } + if (this.isOverlay && !navOptions.minClickBlockDuration) { + // This is a Modal being dismissed so we need + // to add the minClickBlockDuration option + // for UIWebView + navOptions.minClickBlockDuration = 400; + } this._dismissData = data; this._dismissRole = role; diff --git a/src/themes/util.scss b/src/themes/util.scss index 79ef88ed278..8939f7872fc 100755 --- a/src/themes/util.scss +++ b/src/themes/util.scss @@ -63,8 +63,8 @@ ion-input :focus { opacity: 0; transform: translate3d(0, -100%, 0) translateY(1px); - // background: red; - // opacity: .3; + background: red; + opacity: .3; contain: strict; } diff --git a/src/util/click-block.ts b/src/util/click-block.ts index 410d45689ee..e16693a1f8d 100644 --- a/src/util/click-block.ts +++ b/src/util/click-block.ts @@ -14,6 +14,8 @@ import { Platform } from '../platform/platform'; export class ClickBlock { private _tmr: number; private _showing: boolean = false; + private _start: number; + private _minEnd: number; isEnabled: boolean; constructor( @@ -31,10 +33,15 @@ export class ClickBlock { } } - activate(shouldShow: boolean, expire: number = 100) { + activate(shouldShow: boolean, expire: number = 100, minDuration: number = 0) { if (this.isEnabled) { this.plt.cancelTimeout(this._tmr); if (shouldShow) { + // remember when we started the click block + this._start = Date.now(); + // figure out the minimum time it should be showing until + // this is useful for transitions that are less than 300ms + this._minEnd = this._start + (minDuration || 0); this._activate(true); } this._tmr = this.plt.timeout(this._activate.bind(this, false), expire); @@ -44,6 +51,17 @@ export class ClickBlock { /** @internal */ _activate(shouldShow: boolean) { if (this._showing !== shouldShow) { + + if (!shouldShow) { + // check if it was enabled before the minimum duration + // this is useful for transitions that are less than 300ms + var now = Date.now(); + if (now < this._minEnd) { + this._tmr = this.plt.timeout(this._activate.bind(this, false), this._minEnd - now); + return; + } + } + this._setElementClass('click-block-active', shouldShow); this._showing = shouldShow; }