Skip to content

Commit 32ab817

Browse files
manucorporatadamdbradley
authored andcommitted
fix(gestures): gesture controller handled by components
* fix(gestures): gesture controller is handled by components fixes #9046 * fix(gestures): adds hybrid disable scroll assistance fixes #9130 fixes #9052 fixes #7444
1 parent 339857a commit 32ab817

26 files changed

+525
-263
lines changed

src/components/action-sheet/action-sheet-component.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import { Form } from '../../util/form';
55
import { Key } from '../../util/key';
66
import { NavParams } from '../../navigation/nav-params';
77
import { ViewController } from '../../navigation/view-controller';
8-
8+
import { BlockerDelegate, GestureController, BLOCK_ALL } from '../../gestures/gesture-controller';
9+
import { assert } from '../../util/util';
910

1011
/**
1112
* @private
@@ -53,15 +54,18 @@ export class ActionSheetCmp {
5354
hdrId: string;
5455
id: number;
5556
mode: string;
57+
gestureBlocker: BlockerDelegate;
5658

5759
constructor(
5860
private _viewCtrl: ViewController,
5961
private _config: Config,
6062
private _elementRef: ElementRef,
6163
private _form: Form,
64+
gestureCtrl: GestureController,
6265
params: NavParams,
6366
renderer: Renderer
6467
) {
68+
this.gestureBlocker = gestureCtrl.createBlocker(BLOCK_ALL);
6569
this.d = params.data;
6670
this.mode = _config.get('mode');
6771
renderer.setElementClass(_elementRef.nativeElement, `action-sheet-${this.mode}`, true);
@@ -110,6 +114,14 @@ export class ActionSheetCmp {
110114
this.d.buttons = buttons;
111115
}
112116

117+
ionViewWillEnter() {
118+
this.gestureBlocker.block();
119+
}
120+
121+
ionViewDidLeave() {
122+
this.gestureBlocker.unblock();
123+
}
124+
113125
ionViewDidEnter() {
114126
this._form.focusOut();
115127

@@ -166,6 +178,11 @@ export class ActionSheetCmp {
166178
dismiss(role: any): Promise<any> {
167179
return this._viewCtrl.dismiss(null, role);
168180
}
181+
182+
ngOnDestroy() {
183+
assert(this.gestureBlocker.blocked === false, 'gesture blocker must be already unblocked');
184+
this.gestureBlocker.destroy();
185+
}
169186
}
170187

171188
let actionSheetIds = -1;

src/components/alert/alert-component.ts

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { Component, ElementRef, HostListener, Renderer, ViewEncapsulation } from '@angular/core';
22

33
import { Config } from '../../config/config';
4-
import { isPresent } from '../../util/util';
4+
import { isPresent, assert } from '../../util/util';
55
import { Key } from '../../util/key';
66
import { NavParams } from '../../navigation/nav-params';
77
import { ViewController } from '../../navigation/view-controller';
8-
8+
import { GestureController, BlockerDelegate, BLOCK_ALL } from '../../gestures/gesture-controller';
99

1010
/**
1111
* @private
@@ -86,14 +86,18 @@ export class AlertCmp {
8686
msgId: string;
8787
subHdrId: string;
8888
mode: string;
89+
gestureBlocker: BlockerDelegate;
8990

9091
constructor(
9192
public _viewCtrl: ViewController,
9293
public _elementRef: ElementRef,
9394
public _config: Config,
95+
gestureCtrl: GestureController,
9496
params: NavParams,
9597
renderer: Renderer
9698
) {
99+
// gesture blocker is used to disable gestures dynamically
100+
this.gestureBlocker = gestureCtrl.createBlocker(BLOCK_ALL);
97101
this.d = params.data;
98102
this.mode = _config.get('mode');
99103
renderer.setElementClass(_elementRef.nativeElement, `alert-${this.mode}`, true);
@@ -172,6 +176,27 @@ export class AlertCmp {
172176
}
173177
}
174178

179+
ionViewWillEnter() {
180+
this.gestureBlocker.block();
181+
}
182+
183+
ionViewDidLeave() {
184+
this.gestureBlocker.unblock();
185+
}
186+
187+
ionViewDidEnter() {
188+
let activeElement: any = document.activeElement;
189+
if (document.activeElement) {
190+
activeElement.blur();
191+
}
192+
193+
let focusableEle = this._elementRef.nativeElement.querySelector('input,button');
194+
if (focusableEle) {
195+
focusableEle.focus();
196+
}
197+
this.enabled = true;
198+
}
199+
175200
@HostListener('body:keyup', ['$event'])
176201
keyUp(ev: KeyboardEvent) {
177202
if (this.enabled && this._viewCtrl.isLast()) {
@@ -193,19 +218,6 @@ export class AlertCmp {
193218
}
194219
}
195220

196-
ionViewDidEnter() {
197-
let activeElement: any = document.activeElement;
198-
if (document.activeElement) {
199-
activeElement.blur();
200-
}
201-
202-
let focusableEle = this._elementRef.nativeElement.querySelector('input,button');
203-
if (focusableEle) {
204-
focusableEle.focus();
205-
}
206-
this.enabled = true;
207-
}
208-
209221
btnClick(button: any, dismissDelay?: number) {
210222
if (!this.enabled) {
211223
return;
@@ -293,6 +305,11 @@ export class AlertCmp {
293305
});
294306
return values;
295307
}
308+
309+
ngOnDestroy() {
310+
assert(this.gestureBlocker.blocked === false, 'gesture blocker must be already unblocked');
311+
this.gestureBlocker.destroy();
312+
}
296313
}
297314

298315
let alertIds = -1;

src/components/app/app-root.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Config } from '../../config/config';
55
import { Ion } from '../ion';
66
import { OverlayPortal } from '../nav/overlay-portal';
77
import { Platform } from '../../platform/platform';
8+
import { nativeTimeout } from '../../util/dom';
89

910
export const AppRootToken = new OpaqueToken('USERROOT');
1011

@@ -23,6 +24,8 @@ export const AppRootToken = new OpaqueToken('USERROOT');
2324
})
2425
export class IonicApp extends Ion implements OnInit {
2526

27+
private _stopScrollPlugin: any;
28+
private _rafId: number;
2629
@ViewChild('viewport', {read: ViewContainerRef}) _viewport: ViewContainerRef;
2730

2831
@ViewChild('modalPortal', { read: OverlayPortal }) _modalPortal: OverlayPortal;
@@ -45,6 +48,7 @@ export class IonicApp extends Ion implements OnInit {
4548
super(config, elementRef, renderer);
4649
// register with App that this is Ionic's appRoot component. tada!
4750
app._appRoot = this;
51+
this._stopScrollPlugin = window['IonicStopScroll'];
4852
}
4953

5054
ngOnInit() {
@@ -109,7 +113,26 @@ export class IonicApp extends Ion implements OnInit {
109113
* @private
110114
*/
111115
_disableScroll(shouldDisableScroll: boolean) {
112-
this.setElementClass('disable-scroll', shouldDisableScroll);
116+
console.log('App Root: Scroll Disable Assist', shouldDisableScroll);
117+
118+
if (shouldDisableScroll) {
119+
this.stopScroll().then(() => {
120+
this._rafId = nativeTimeout(() => this.setElementClass('disable-scroll', true), 16 * 2);
121+
});
122+
} else {
123+
cancelAnimationFrame(this._rafId);
124+
this.setElementClass('disable-scroll', false);
125+
}
126+
}
127+
128+
stopScroll(): Promise<boolean> {
129+
if (this._stopScrollPlugin) {
130+
return new Promise((resolve, reject) => {
131+
this._stopScrollPlugin.stop(() => resolve(true));
132+
});
133+
} else {
134+
return Promise.resolve(false);
135+
}
113136
}
114137

115138
}

src/components/app/app.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export class App {
2222
private _title: string = '';
2323
private _titleSrv: Title = new Title();
2424
private _rootNav: NavController = null;
25-
private _canDisableScroll: boolean;
25+
private _disableScrollAssist: boolean;
2626

2727
/**
2828
* @private
@@ -71,7 +71,7 @@ export class App {
7171
// listen for hardware back button events
7272
// register this back button action with a default priority
7373
_platform.registerBackButtonAction(this.navPop.bind(this));
74-
this._canDisableScroll = _config.get('canDisableScroll', false);
74+
this._disableScrollAssist = _config.getBoolean('disableScrollAssist', false);
7575
}
7676

7777
/**
@@ -124,7 +124,7 @@ export class App {
124124
* scrolling is enabled. When set to `true`, scrolling is disabled.
125125
*/
126126
setScrollDisabled(disableScroll: boolean) {
127-
if (this._canDisableScroll) {
127+
if (this._disableScrollAssist) {
128128
this._appRoot._disableScroll(disableScroll);
129129
}
130130
}

src/components/backdrop/backdrop.scss

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,3 @@ ion-backdrop {
1919
opacity: .01;
2020
transform: translateZ(0);
2121
}
22-
23-
ion-backdrop.hide-backdrop {
24-
display: none;
25-
}

src/components/backdrop/backdrop.ts

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import { Directive, ElementRef, Input, Renderer } from '@angular/core';
2-
3-
import { GestureController } from '../../gestures/gesture-controller';
4-
import { isTrueProperty } from '../../util/util';
5-
1+
import { Directive, ElementRef, Renderer } from '@angular/core';
62

73
/**
84
* @private
@@ -16,26 +12,11 @@ import { isTrueProperty } from '../../util/util';
1612
},
1713
})
1814
export class Backdrop {
19-
private _gestureID: number = null;
20-
@Input() disableScroll = true;
2115

2216
constructor(
23-
private _gestureCtrl: GestureController,
2417
private _elementRef: ElementRef,
25-
private _renderer: Renderer) { }
26-
27-
ngOnInit() {
28-
if (isTrueProperty(this.disableScroll)) {
29-
this._gestureID = this._gestureCtrl.newID();
30-
this._gestureCtrl.disableScroll(this._gestureID);
31-
}
32-
}
33-
34-
ngOnDestroy() {
35-
if (this._gestureID) {
36-
this._gestureCtrl.enableScroll(this._gestureID);
37-
}
38-
}
18+
private _renderer: Renderer
19+
) { }
3920

4021
getNativeElement(): HTMLElement {
4122
return this._elementRef.nativeElement;

src/components/content/content.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ ion-content.js-scroll > .scroll-content {
5151
will-change: initial;
5252
}
5353

54-
.disable-scroll .ion-page .scroll-content {
54+
.disable-scroll .ion-page {
5555
pointer-events: none;
5656
}
5757

src/components/item/item-sliding-gesture.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { ItemSliding } from './item-sliding';
22
import { List } from '../list/list';
33

4-
import { GesturePriority } from '../../gestures/gesture-controller';
4+
import { GestureController, GesturePriority, GESTURE_ITEM_SWIPE } from '../../gestures/gesture-controller';
55
import { PanGesture } from '../../gestures/drag-gesture';
66
import { pointerCoord } from '../../util/dom';
77
import { NativeRafDebouncer } from '../../util/debouncer';
88

9-
const DRAG_THRESHOLD = 10;
10-
const MAX_ATTACK_ANGLE = 20;
11-
9+
/**
10+
* @private
11+
*/
1212
export class ItemSlidingGesture extends PanGesture {
1313

1414
private preSelectedContainer: ItemSliding = null;
@@ -17,14 +17,16 @@ export class ItemSlidingGesture extends PanGesture {
1717
private firstCoordX: number;
1818
private firstTimestamp: number;
1919

20-
constructor(public list: List) {
20+
constructor(public list: List, gestureCtrl: GestureController) {
2121
super(list.getNativeElement(), {
22-
maxAngle: MAX_ATTACK_ANGLE,
23-
threshold: DRAG_THRESHOLD,
22+
maxAngle: 20,
23+
threshold: 10,
2424
zone: false,
2525
debouncer: new NativeRafDebouncer(),
26-
gesture: list._gestureCtrl.create('item-sliding', {
26+
gesture: gestureCtrl.createGesture({
27+
name: GESTURE_ITEM_SWIPE,
2728
priority: GesturePriority.SlidingItem,
29+
disableScroll: false // TODO: set true
2830
})
2931
});
3032
}

src/components/list/list.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export class List extends Ion {
9595

9696
} else if (!this._slidingGesture) {
9797
console.debug('enableSlidingItems');
98-
this._slidingGesture = new ItemSlidingGesture(this);
98+
this._slidingGesture = new ItemSlidingGesture(this, this._gestureCtrl);
9999
this._slidingGesture.listen();
100100
}
101101
}

0 commit comments

Comments
 (0)