appium-android-driver 5.13.0 → 5.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/build/index.js +43 -40
- package/build/lib/android-helpers.d.ts +136 -0
- package/build/lib/android-helpers.d.ts.map +1 -0
- package/build/lib/android-helpers.js +760 -679
- package/build/lib/android-helpers.js.map +1 -1
- package/build/lib/bootstrap.d.ts +29 -0
- package/build/lib/bootstrap.d.ts.map +1 -0
- package/build/lib/bootstrap.js +192 -179
- package/build/lib/bootstrap.js.map +1 -1
- package/build/lib/commands/actions.d.ts +209 -0
- package/build/lib/commands/actions.d.ts.map +1 -0
- package/build/lib/commands/actions.js +327 -265
- package/build/lib/commands/actions.js.map +1 -1
- package/build/lib/commands/alert.d.ts +10 -0
- package/build/lib/commands/alert.d.ts.map +1 -0
- package/build/lib/commands/alert.js +12 -18
- package/build/lib/commands/alert.js.map +1 -1
- package/build/lib/commands/app-management.d.ts +314 -0
- package/build/lib/commands/app-management.d.ts.map +1 -0
- package/build/lib/commands/app-management.js +278 -110
- package/build/lib/commands/app-management.js.map +1 -1
- package/build/lib/commands/context.d.ts +94 -0
- package/build/lib/commands/context.d.ts.map +1 -0
- package/build/lib/commands/context.js +412 -260
- package/build/lib/commands/context.js.map +1 -1
- package/build/lib/commands/coverage.d.ts +5 -0
- package/build/lib/commands/coverage.d.ts.map +1 -0
- package/build/lib/commands/coverage.js +14 -17
- package/build/lib/commands/coverage.js.map +1 -1
- package/build/lib/commands/element.d.ts +36 -0
- package/build/lib/commands/element.d.ts.map +1 -0
- package/build/lib/commands/element.js +97 -127
- package/build/lib/commands/element.js.map +1 -1
- package/build/lib/commands/emu-console.d.ts +49 -0
- package/build/lib/commands/emu-console.d.ts.map +1 -0
- package/build/lib/commands/emu-console.js +36 -25
- package/build/lib/commands/emu-console.js.map +1 -1
- package/build/lib/commands/execute.d.ts +6 -0
- package/build/lib/commands/execute.d.ts.map +1 -0
- package/build/lib/commands/execute.js +68 -69
- package/build/lib/commands/execute.js.map +1 -1
- package/build/lib/commands/file-actions.d.ts +129 -0
- package/build/lib/commands/file-actions.d.ts.map +1 -0
- package/build/lib/commands/file-actions.js +321 -178
- package/build/lib/commands/file-actions.js.map +1 -1
- package/build/lib/commands/find.d.ts +13 -0
- package/build/lib/commands/find.d.ts.map +1 -0
- package/build/lib/commands/find.js +69 -51
- package/build/lib/commands/find.js.map +1 -1
- package/build/lib/commands/general.d.ts +133 -0
- package/build/lib/commands/general.d.ts.map +1 -0
- package/build/lib/commands/general.js +275 -216
- package/build/lib/commands/general.js.map +1 -1
- package/build/lib/commands/ime.d.ts +11 -0
- package/build/lib/commands/ime.d.ts.map +1 -0
- package/build/lib/commands/ime.js +27 -33
- package/build/lib/commands/ime.js.map +1 -1
- package/build/lib/commands/index.d.ts +3 -0
- package/build/lib/commands/index.d.ts.map +1 -0
- package/build/lib/commands/index.js +32 -35
- package/build/lib/commands/index.js.map +1 -1
- package/build/lib/commands/intent.d.ts +418 -0
- package/build/lib/commands/intent.d.ts.map +1 -0
- package/build/lib/commands/intent.js +281 -151
- package/build/lib/commands/intent.js.map +1 -1
- package/build/lib/commands/keyboard.d.ts +6 -0
- package/build/lib/commands/keyboard.d.ts.map +1 -0
- package/build/lib/commands/keyboard.js +6 -14
- package/build/lib/commands/keyboard.js.map +1 -1
- package/build/lib/commands/log.d.ts +45 -0
- package/build/lib/commands/log.d.ts.map +1 -0
- package/build/lib/commands/log.js +117 -103
- package/build/lib/commands/log.js.map +1 -1
- package/build/lib/commands/media-projection.d.ts +144 -0
- package/build/lib/commands/media-projection.d.ts.map +1 -0
- package/build/lib/commands/media-projection.js +228 -171
- package/build/lib/commands/media-projection.js.map +1 -1
- package/build/lib/commands/network.d.ts +139 -0
- package/build/lib/commands/network.d.ts.map +1 -0
- package/build/lib/commands/network.js +249 -181
- package/build/lib/commands/network.js.map +1 -1
- package/build/lib/commands/performance.d.ts +101 -0
- package/build/lib/commands/performance.d.ts.map +1 -0
- package/build/lib/commands/performance.js +390 -236
- package/build/lib/commands/performance.js.map +1 -1
- package/build/lib/commands/permissions.d.ts +93 -0
- package/build/lib/commands/permissions.d.ts.map +1 -0
- package/build/lib/commands/permissions.js +133 -93
- package/build/lib/commands/permissions.js.map +1 -1
- package/build/lib/commands/recordscreen.d.ts +194 -0
- package/build/lib/commands/recordscreen.d.ts.map +1 -0
- package/build/lib/commands/recordscreen.js +293 -224
- package/build/lib/commands/recordscreen.js.map +1 -1
- package/build/lib/commands/shell.d.ts +8 -0
- package/build/lib/commands/shell.d.ts.map +1 -0
- package/build/lib/commands/shell.js +38 -43
- package/build/lib/commands/shell.js.map +1 -1
- package/build/lib/commands/streamscreen.d.ts +104 -0
- package/build/lib/commands/streamscreen.d.ts.map +1 -0
- package/build/lib/commands/streamscreen.js +364 -305
- package/build/lib/commands/streamscreen.js.map +1 -1
- package/build/lib/commands/system-bars.d.ts +100 -0
- package/build/lib/commands/system-bars.d.ts.map +1 -0
- package/build/lib/commands/system-bars.js +148 -90
- package/build/lib/commands/system-bars.js.map +1 -1
- package/build/lib/commands/touch.d.ts +30 -0
- package/build/lib/commands/touch.d.ts.map +1 -0
- package/build/lib/commands/touch.js +311 -287
- package/build/lib/commands/touch.js.map +1 -1
- package/build/lib/desired-caps.d.ts +353 -0
- package/build/lib/desired-caps.d.ts.map +1 -0
- package/build/lib/desired-caps.js +291 -292
- package/build/lib/desired-caps.js.map +1 -1
- package/build/lib/driver.d.ts +430 -0
- package/build/lib/driver.d.ts.map +1 -0
- package/build/lib/driver.js +449 -384
- package/build/lib/driver.js.map +1 -1
- package/build/lib/logger.d.ts +3 -0
- package/build/lib/logger.d.ts.map +1 -0
- package/build/lib/logger.js +5 -11
- package/build/lib/logger.js.map +1 -1
- package/build/lib/method-map.d.ts +389 -0
- package/build/lib/method-map.d.ts.map +1 -0
- package/build/lib/method-map.js +220 -394
- package/build/lib/method-map.js.map +1 -1
- package/build/lib/stubs.d.ts +8 -0
- package/build/lib/stubs.d.ts.map +1 -0
- package/build/lib/stubs.js +5 -0
- package/build/lib/stubs.js.map +1 -0
- package/build/lib/uiautomator.d.ts +24 -0
- package/build/lib/uiautomator.d.ts.map +1 -0
- package/build/lib/uiautomator.js +86 -82
- package/build/lib/uiautomator.js.map +1 -1
- package/build/lib/unlock-helpers.d.ts +38 -0
- package/build/lib/unlock-helpers.d.ts.map +1 -0
- package/build/lib/unlock-helpers.js +228 -204
- package/build/lib/unlock-helpers.js.map +1 -1
- package/build/lib/utils.d.ts +11 -0
- package/build/lib/utils.d.ts.map +1 -0
- package/build/lib/utils.js +23 -18
- package/build/lib/utils.js.map +1 -1
- package/build/lib/webview-helpers.d.ts +223 -0
- package/build/lib/webview-helpers.d.ts.map +1 -0
- package/build/lib/webview-helpers.js +476 -298
- package/build/lib/webview-helpers.js.map +1 -1
- package/index.js +3 -1
- package/lib/android-helpers.js +2 -1
- package/lib/stubs.ts +8 -0
- package/lib/unlock-helpers.js +2 -2
- package/package.json +23 -14
|
@@ -1,322 +1,346 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
require("
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
var _support = require("@appium/support");
|
|
15
|
-
let commands = {},
|
|
16
|
-
helpers = {},
|
|
17
|
-
extensions = {};
|
|
18
|
-
exports.helpers = helpers;
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.helpers = exports.commands = void 0;
|
|
7
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
8
|
+
const android_helpers_1 = __importDefault(require("../android-helpers"));
|
|
9
|
+
const bluebird_1 = __importDefault(require("bluebird"));
|
|
10
|
+
const driver_1 = require("appium/driver");
|
|
11
|
+
const asyncbox_1 = require("asyncbox");
|
|
12
|
+
const support_1 = require("@appium/support");
|
|
13
|
+
let commands = {}, helpers = {}, extensions = {};
|
|
19
14
|
exports.commands = commands;
|
|
15
|
+
exports.helpers = helpers;
|
|
20
16
|
function getCoordDefault(val) {
|
|
21
|
-
|
|
17
|
+
// going the long way and checking for undefined and null since
|
|
18
|
+
// we can't be assured `elId` is a string and not an int. Same
|
|
19
|
+
// thing with destElement below.
|
|
20
|
+
return support_1.util.hasValue(val) ? val : 0.5;
|
|
22
21
|
}
|
|
23
22
|
function getSwipeTouchDuration(waitGesture) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
duration =
|
|
27
|
-
if (
|
|
28
|
-
|
|
23
|
+
// the touch action api uses ms, we want seconds
|
|
24
|
+
// 0.8 is the default time for the operation
|
|
25
|
+
let duration = 0.8;
|
|
26
|
+
if (typeof waitGesture.options.ms !== 'undefined' && waitGesture.options.ms) {
|
|
27
|
+
duration = waitGesture.options.ms / 1000;
|
|
28
|
+
if (duration === 0) {
|
|
29
|
+
// set to a very low number, since they wanted it fast
|
|
30
|
+
// but below 0.1 becomes 0 steps, which causes errors
|
|
31
|
+
duration = 0.1;
|
|
32
|
+
}
|
|
29
33
|
}
|
|
30
|
-
|
|
31
|
-
return duration;
|
|
34
|
+
return duration;
|
|
32
35
|
}
|
|
33
36
|
commands.doTouchAction = async function doTouchAction(action, opts = {}) {
|
|
34
|
-
|
|
35
|
-
element
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
break;
|
|
58
|
-
default:
|
|
59
|
-
this.log.errorAndThrow(`unknown action ${action}`);
|
|
60
|
-
}
|
|
37
|
+
const { element, x, y, count, ms, duration } = opts;
|
|
38
|
+
// parseTouch precalculates absolute element positions
|
|
39
|
+
// so there is no need to pass `element` to the affected gestures
|
|
40
|
+
switch (action) {
|
|
41
|
+
case 'tap':
|
|
42
|
+
return await this.tap(null, x, y, count);
|
|
43
|
+
case 'press':
|
|
44
|
+
return await this.touchDown(null, x, y);
|
|
45
|
+
case 'release':
|
|
46
|
+
return await this.touchUp(element, x, y);
|
|
47
|
+
case 'moveTo':
|
|
48
|
+
return await this.touchMove(null, x, y);
|
|
49
|
+
case 'wait':
|
|
50
|
+
return await bluebird_1.default.delay(ms);
|
|
51
|
+
case 'longPress':
|
|
52
|
+
return await this.touchLongClick(null, x, y, duration || 1000);
|
|
53
|
+
case 'cancel':
|
|
54
|
+
// TODO: clarify behavior of 'cancel' action and fix this
|
|
55
|
+
this.log.warn('Cancel action currently has no effect');
|
|
56
|
+
break;
|
|
57
|
+
default:
|
|
58
|
+
this.log.errorAndThrow(`unknown action ${action}`);
|
|
59
|
+
}
|
|
61
60
|
};
|
|
61
|
+
// drag is *not* press-move-release, so we need to translate
|
|
62
|
+
// drag works fine for scroll, as well
|
|
62
63
|
helpers.doTouchDrag = async function doTouchDrag(gestures) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
let
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
let apiLevel = await this.adb.getApiLevel();
|
|
86
|
-
let duration = apiLevel >= 5 ? 2 : 1;
|
|
87
|
-
if (longPress.options && longPress.options.duration) {
|
|
88
|
-
duration = Math.max(longPress.options.duration / 1000, duration);
|
|
89
|
-
}
|
|
90
|
-
return await this.drag(startX, startY, endX, endY, duration, 1, longPress.options.element, moveTo.options.element);
|
|
64
|
+
let longPress = gestures[0];
|
|
65
|
+
let moveTo = gestures[1];
|
|
66
|
+
let startX = longPress.options.x || 0, startY = longPress.options.y || 0, endX = moveTo.options.x || 0, endY = moveTo.options.y || 0;
|
|
67
|
+
if (longPress.options.element) {
|
|
68
|
+
let { x, y } = await this.getLocationInView(longPress.options.element);
|
|
69
|
+
startX += x || 0;
|
|
70
|
+
startY += y || 0;
|
|
71
|
+
}
|
|
72
|
+
if (moveTo.options.element) {
|
|
73
|
+
let { x, y } = await this.getLocationInView(moveTo.options.element);
|
|
74
|
+
endX += x || 0;
|
|
75
|
+
endY += y || 0;
|
|
76
|
+
}
|
|
77
|
+
let apiLevel = await this.adb.getApiLevel();
|
|
78
|
+
// lollipop takes a little longer to get things rolling
|
|
79
|
+
let duration = apiLevel >= 5 ? 2 : 1;
|
|
80
|
+
// make sure that if the long press has a duration, we use it.
|
|
81
|
+
if (longPress.options && longPress.options.duration) {
|
|
82
|
+
duration = Math.max(longPress.options.duration / 1000, duration);
|
|
83
|
+
}
|
|
84
|
+
// `drag` will take care of whether there is an element or not at that level
|
|
85
|
+
return await this.drag(startX, startY, endX, endY, duration, 1, longPress.options.element, moveTo.options.element);
|
|
91
86
|
};
|
|
87
|
+
// Release gesture needs element or co-ordinates to release it from that position
|
|
88
|
+
// or else release gesture is performed from center of the screen, so to fix it
|
|
89
|
+
// This method sets co-ordinates/element to release gesture if it has no options set already.
|
|
92
90
|
helpers.fixRelease = async function fixRelease(gestures) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
let ref = null;
|
|
100
|
-
for (let gesture of gestures.reverse()) {
|
|
101
|
-
let opts = gesture.options;
|
|
102
|
-
if (opts.element || opts.x && opts.y) {
|
|
103
|
-
ref = gesture;
|
|
104
|
-
break;
|
|
91
|
+
let release = lodash_1.default.last(gestures);
|
|
92
|
+
// sometimes there are no options
|
|
93
|
+
release.options = release.options || {};
|
|
94
|
+
// nothing to do if release options are already set
|
|
95
|
+
if (release.options.element || (release.options.x && release.options.y)) {
|
|
96
|
+
return;
|
|
105
97
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
release.options = {
|
|
119
|
-
x: loc.x + size.width / 2,
|
|
120
|
-
y: loc.y + size.height / 2
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
} else {
|
|
124
|
-
release.options = _lodash.default.pick(opts, 'x', 'y');
|
|
98
|
+
// without coordinates, `release` uses the center of the screen, which,
|
|
99
|
+
// generally speaking, is not what we want
|
|
100
|
+
// therefore: loop backwards and use the last command with an element and/or
|
|
101
|
+
// offset coordinates
|
|
102
|
+
gestures = lodash_1.default.clone(gestures);
|
|
103
|
+
let ref = null;
|
|
104
|
+
for (let gesture of gestures.reverse()) {
|
|
105
|
+
let opts = gesture.options;
|
|
106
|
+
if (opts.element || (opts.x && opts.y)) {
|
|
107
|
+
ref = gesture;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
125
110
|
}
|
|
126
|
-
|
|
127
|
-
|
|
111
|
+
if (ref) {
|
|
112
|
+
let opts = ref.options;
|
|
113
|
+
if (opts.element) {
|
|
114
|
+
let loc = await this.getLocationInView(opts.element);
|
|
115
|
+
if (opts.x && opts.y) {
|
|
116
|
+
// this is an offset from the element
|
|
117
|
+
release.options = {
|
|
118
|
+
x: loc.x + opts.x,
|
|
119
|
+
y: loc.y + opts.y
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
// this is the center of the element
|
|
124
|
+
let size = await this.getSize(opts.element);
|
|
125
|
+
release.options = {
|
|
126
|
+
x: loc.x + size.width / 2,
|
|
127
|
+
y: loc.y + size.height / 2
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
release.options = lodash_1.default.pick(opts, 'x', 'y');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return release;
|
|
128
136
|
};
|
|
137
|
+
// Perform one gesture
|
|
129
138
|
helpers.performGesture = async function performGesture(gesture) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
139
|
+
try {
|
|
140
|
+
return await this.doTouchAction(gesture.action, gesture.options || {});
|
|
141
|
+
}
|
|
142
|
+
catch (e) {
|
|
143
|
+
// sometime the element is not available when releasing, retry without it
|
|
144
|
+
if ((0, driver_1.isErrorType)(e, driver_1.errors.NoSuchElementError) && gesture.action === 'release' &&
|
|
145
|
+
gesture.options.element) {
|
|
146
|
+
delete gesture.options.element;
|
|
147
|
+
this.log.debug(`retrying release without element opts: ${gesture.options}.`);
|
|
148
|
+
return await this.doTouchAction(gesture.action, gesture.options || {});
|
|
149
|
+
}
|
|
150
|
+
throw e;
|
|
137
151
|
}
|
|
138
|
-
throw e;
|
|
139
|
-
}
|
|
140
152
|
};
|
|
141
153
|
commands.getSwipeOptions = async function getSwipeOptions(gestures, touchCount = 1) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
let firstElLocation = await this.getLocationInView(element);
|
|
158
|
-
endX -= firstElLocation.x;
|
|
159
|
-
endY -= firstElLocation.y;
|
|
154
|
+
let startX = getCoordDefault(gestures[0].options.x), startY = getCoordDefault(gestures[0].options.y), endX = getCoordDefault(gestures[2].options.x), endY = getCoordDefault(gestures[2].options.y), duration = getSwipeTouchDuration(gestures[1]), element = gestures[0].options.element, destElement = gestures[2].options.element || gestures[0].options.element;
|
|
155
|
+
// there's no destination element handling in bootstrap and since it applies to all platforms, we handle it here
|
|
156
|
+
if (support_1.util.hasValue(destElement)) {
|
|
157
|
+
let locResult = await this.getLocationInView(destElement);
|
|
158
|
+
let sizeResult = await this.getSize(destElement);
|
|
159
|
+
let offsetX = (Math.abs(endX) < 1 && Math.abs(endX) > 0) ? sizeResult.width * endX : endX;
|
|
160
|
+
let offsetY = (Math.abs(endY) < 1 && Math.abs(endY) > 0) ? sizeResult.height * endY : endY;
|
|
161
|
+
endX = locResult.x + offsetX;
|
|
162
|
+
endY = locResult.y + offsetY;
|
|
163
|
+
// if the target element was provided, the coordinates for the destination need to be relative to it.
|
|
164
|
+
if (support_1.util.hasValue(element)) {
|
|
165
|
+
let firstElLocation = await this.getLocationInView(element);
|
|
166
|
+
endX -= firstElLocation.x;
|
|
167
|
+
endY -= firstElLocation.y;
|
|
168
|
+
}
|
|
160
169
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
startX,
|
|
164
|
-
startY,
|
|
165
|
-
endX,
|
|
166
|
-
endY,
|
|
167
|
-
duration,
|
|
168
|
-
touchCount,
|
|
169
|
-
element
|
|
170
|
-
};
|
|
170
|
+
// clients are responsible to use these options correctly
|
|
171
|
+
return { startX, startY, endX, endY, duration, touchCount, element };
|
|
171
172
|
};
|
|
172
173
|
commands.performTouch = async function performTouch(gestures) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if (actions.length === 2) {
|
|
182
|
-
if (_lodash.default.head(actions) === 'press' && _lodash.default.last(actions) === 'release') {
|
|
183
|
-
actions[0] = 'tap';
|
|
184
|
-
gestures[0].action = 'tap';
|
|
185
|
-
}
|
|
186
|
-
if ((_lodash.default.head(actions) === 'tap' || _lodash.default.head(actions) === 'longPress') && _lodash.default.last(actions) === 'release') {
|
|
187
|
-
gestures.pop();
|
|
188
|
-
actions.pop();
|
|
189
|
-
}
|
|
190
|
-
} else {
|
|
191
|
-
if (actions[0] === 'longPress') {
|
|
192
|
-
actions = ['press', 'wait', ...actions.slice(1)];
|
|
193
|
-
let press = gestures.shift();
|
|
194
|
-
press.action = 'press';
|
|
195
|
-
let wait = {
|
|
196
|
-
action: 'wait',
|
|
197
|
-
options: {
|
|
198
|
-
ms: press.options.duration || 1000
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
delete press.options.duration;
|
|
202
|
-
gestures = [press, wait, ...gestures];
|
|
203
|
-
}
|
|
174
|
+
// press-wait-moveTo-release is `swipe`, so use native method
|
|
175
|
+
if (gestures.length === 4 &&
|
|
176
|
+
gestures[0].action === 'press' &&
|
|
177
|
+
gestures[1].action === 'wait' &&
|
|
178
|
+
gestures[2].action === 'moveTo' &&
|
|
179
|
+
gestures[3].action === 'release') {
|
|
180
|
+
let swipeOpts = await this.getSwipeOptions(gestures);
|
|
181
|
+
return await this.swipe(swipeOpts.startX, swipeOpts.startY, swipeOpts.endX, swipeOpts.endY, swipeOpts.duration, swipeOpts.touchCount, swipeOpts.element);
|
|
204
182
|
}
|
|
205
|
-
let
|
|
206
|
-
if (actions[
|
|
207
|
-
|
|
183
|
+
let actions = lodash_1.default.map(gestures, 'action');
|
|
184
|
+
if (actions[0] === 'longPress' && actions[1] === 'moveTo' && actions[2] === 'release') {
|
|
185
|
+
// some things are special
|
|
186
|
+
return await this.doTouchDrag(gestures);
|
|
208
187
|
}
|
|
209
|
-
|
|
210
|
-
|
|
188
|
+
else {
|
|
189
|
+
if (actions.length === 2) {
|
|
190
|
+
// `press` without a wait is too slow and gets interpretted as a `longPress`
|
|
191
|
+
if (lodash_1.default.head(actions) === 'press' && lodash_1.default.last(actions) === 'release') {
|
|
192
|
+
actions[0] = 'tap';
|
|
193
|
+
gestures[0].action = 'tap';
|
|
194
|
+
}
|
|
195
|
+
// the `longPress` and `tap` methods release on their own
|
|
196
|
+
if ((lodash_1.default.head(actions) === 'tap' || lodash_1.default.head(actions) === 'longPress') && lodash_1.default.last(actions) === 'release') {
|
|
197
|
+
gestures.pop();
|
|
198
|
+
actions.pop();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
// longpress followed by anything other than release should become a press and wait
|
|
203
|
+
if (actions[0] === 'longPress') {
|
|
204
|
+
actions = ['press', 'wait', ...actions.slice(1)];
|
|
205
|
+
let press = gestures.shift();
|
|
206
|
+
press.action = 'press';
|
|
207
|
+
let wait = {
|
|
208
|
+
action: 'wait',
|
|
209
|
+
options: { ms: press.options.duration || 1000 }
|
|
210
|
+
};
|
|
211
|
+
delete press.options.duration;
|
|
212
|
+
gestures = [press, wait, ...gestures];
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
let fixedGestures = await this.parseTouch(gestures, false);
|
|
216
|
+
// fix release action then perform all actions
|
|
217
|
+
if (actions[actions.length - 1] === 'release') {
|
|
218
|
+
actions[actions.length - 1] = await this.fixRelease(gestures);
|
|
219
|
+
}
|
|
220
|
+
for (let g of fixedGestures) {
|
|
221
|
+
await this.performGesture(g);
|
|
222
|
+
}
|
|
211
223
|
}
|
|
212
|
-
}
|
|
213
224
|
};
|
|
214
225
|
helpers.parseTouch = async function parseTouch(gestures, multi) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
let touchStateObjects = await (0, _asyncbox.asyncmap)(gestures, async gesture => {
|
|
219
|
-
let options = gesture.options || {};
|
|
220
|
-
if (_lodash.default.includes(['press', 'moveTo', 'tap', 'longPress'], gesture.action)) {
|
|
221
|
-
options.offset = false;
|
|
222
|
-
let elementId = gesture.options.element;
|
|
223
|
-
if (elementId) {
|
|
224
|
-
let pos = await this.getLocationInView(elementId);
|
|
225
|
-
if (gesture.options.x || gesture.options.y) {
|
|
226
|
-
options.x = pos.x + (gesture.options.x || 0);
|
|
227
|
-
options.y = pos.y + (gesture.options.y || 0);
|
|
228
|
-
} else {
|
|
229
|
-
const {
|
|
230
|
-
width,
|
|
231
|
-
height
|
|
232
|
-
} = await this.getSize(elementId);
|
|
233
|
-
options.x = pos.x + width / 2;
|
|
234
|
-
options.y = pos.y + height / 2;
|
|
235
|
-
}
|
|
236
|
-
let touchStateObject = {
|
|
237
|
-
action: gesture.action,
|
|
238
|
-
options,
|
|
239
|
-
timeOffset: 0.005
|
|
240
|
-
};
|
|
241
|
-
return touchStateObject;
|
|
242
|
-
} else {
|
|
243
|
-
options.x = gesture.options.x || 0;
|
|
244
|
-
options.y = gesture.options.y || 0;
|
|
245
|
-
let touchStateObject = {
|
|
246
|
-
action: gesture.action,
|
|
247
|
-
options,
|
|
248
|
-
timeOffset: 0.005
|
|
249
|
-
};
|
|
250
|
-
return touchStateObject;
|
|
251
|
-
}
|
|
252
|
-
} else {
|
|
253
|
-
let offset = 0.005;
|
|
254
|
-
if (gesture.action === 'wait') {
|
|
255
|
-
options = gesture.options;
|
|
256
|
-
offset = parseInt(gesture.options.ms, 10) / 1000;
|
|
257
|
-
}
|
|
258
|
-
let touchStateObject = {
|
|
259
|
-
action: gesture.action,
|
|
260
|
-
options,
|
|
261
|
-
timeOffset: offset
|
|
262
|
-
};
|
|
263
|
-
return touchStateObject;
|
|
264
|
-
}
|
|
265
|
-
}, false);
|
|
266
|
-
let prevPos = null,
|
|
267
|
-
time = 0;
|
|
268
|
-
for (let state of touchStateObjects) {
|
|
269
|
-
if (_lodash.default.isUndefined(state.options.x) && _lodash.default.isUndefined(state.options.y) && prevPos !== null) {
|
|
270
|
-
state.options.x = prevPos.x;
|
|
271
|
-
state.options.y = prevPos.y;
|
|
272
|
-
}
|
|
273
|
-
if (state.options.offset && prevPos) {
|
|
274
|
-
state.options.x += prevPos.x;
|
|
275
|
-
state.options.y += prevPos.y;
|
|
276
|
-
}
|
|
277
|
-
delete state.options.offset;
|
|
278
|
-
if (!_lodash.default.isUndefined(state.options.x) && !_lodash.default.isUndefined(state.options.y)) {
|
|
279
|
-
prevPos = state.options;
|
|
226
|
+
// because multi-touch releases at the end by default
|
|
227
|
+
if (multi && lodash_1.default.last(gestures).action === 'release') {
|
|
228
|
+
gestures.pop();
|
|
280
229
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
230
|
+
let touchStateObjects = await (0, asyncbox_1.asyncmap)(gestures, async (gesture) => {
|
|
231
|
+
let options = gesture.options || {};
|
|
232
|
+
if (lodash_1.default.includes(['press', 'moveTo', 'tap', 'longPress'], gesture.action)) {
|
|
233
|
+
options.offset = false;
|
|
234
|
+
let elementId = gesture.options.element;
|
|
235
|
+
if (elementId) {
|
|
236
|
+
let pos = await this.getLocationInView(elementId);
|
|
237
|
+
if (gesture.options.x || gesture.options.y) {
|
|
238
|
+
options.x = pos.x + (gesture.options.x || 0);
|
|
239
|
+
options.y = pos.y + (gesture.options.y || 0);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
const { width, height } = await this.getSize(elementId);
|
|
243
|
+
options.x = pos.x + (width / 2);
|
|
244
|
+
options.y = pos.y + (height / 2);
|
|
245
|
+
}
|
|
246
|
+
let touchStateObject = {
|
|
247
|
+
action: gesture.action,
|
|
248
|
+
options,
|
|
249
|
+
timeOffset: 0.005,
|
|
250
|
+
};
|
|
251
|
+
return touchStateObject;
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
options.x = (gesture.options.x || 0);
|
|
255
|
+
options.y = (gesture.options.y || 0);
|
|
256
|
+
let touchStateObject = {
|
|
257
|
+
action: gesture.action,
|
|
258
|
+
options,
|
|
259
|
+
timeOffset: 0.005,
|
|
260
|
+
};
|
|
261
|
+
return touchStateObject;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
let offset = 0.005;
|
|
266
|
+
if (gesture.action === 'wait') {
|
|
267
|
+
options = gesture.options;
|
|
268
|
+
offset = (parseInt(gesture.options.ms, 10) / 1000);
|
|
269
|
+
}
|
|
270
|
+
let touchStateObject = {
|
|
271
|
+
action: gesture.action,
|
|
272
|
+
options,
|
|
273
|
+
timeOffset: offset,
|
|
274
|
+
};
|
|
275
|
+
return touchStateObject;
|
|
276
|
+
}
|
|
277
|
+
}, false);
|
|
278
|
+
// we need to change the time (which is now an offset)
|
|
279
|
+
// and the position (which may be an offset)
|
|
280
|
+
let prevPos = null, time = 0;
|
|
281
|
+
for (let state of touchStateObjects) {
|
|
282
|
+
if (lodash_1.default.isUndefined(state.options.x) && lodash_1.default.isUndefined(state.options.y) && prevPos !== null) {
|
|
283
|
+
// this happens with wait
|
|
284
|
+
state.options.x = prevPos.x;
|
|
285
|
+
state.options.y = prevPos.y;
|
|
286
|
+
}
|
|
287
|
+
if (state.options.offset && prevPos) {
|
|
288
|
+
// the current position is an offset
|
|
289
|
+
state.options.x += prevPos.x;
|
|
290
|
+
state.options.y += prevPos.y;
|
|
291
|
+
}
|
|
292
|
+
delete state.options.offset;
|
|
293
|
+
if (!lodash_1.default.isUndefined(state.options.x) && !lodash_1.default.isUndefined(state.options.y)) {
|
|
294
|
+
prevPos = state.options;
|
|
295
|
+
}
|
|
296
|
+
if (multi) {
|
|
297
|
+
let timeOffset = state.timeOffset;
|
|
298
|
+
time += timeOffset;
|
|
299
|
+
state.time = android_helpers_1.default.truncateDecimals(time, 3);
|
|
300
|
+
// multi gestures require 'touch' rather than 'options'
|
|
301
|
+
if (!lodash_1.default.isUndefined(state.options.x) && !lodash_1.default.isUndefined(state.options.y)) {
|
|
302
|
+
state.touch = {
|
|
303
|
+
x: state.options.x,
|
|
304
|
+
y: state.options.y
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
delete state.options;
|
|
308
|
+
}
|
|
309
|
+
delete state.timeOffset;
|
|
292
310
|
}
|
|
293
|
-
|
|
294
|
-
}
|
|
295
|
-
return touchStateObjects;
|
|
311
|
+
return touchStateObjects;
|
|
296
312
|
};
|
|
297
313
|
commands.performMultiAction = async function performMultiAction(actions, elementId) {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
314
|
+
// Android needs at least two actions to be able to perform a multi pointer gesture
|
|
315
|
+
if (actions.length === 1) {
|
|
316
|
+
throw new Error('Multi Pointer Gestures need at least two actions. ' +
|
|
317
|
+
'Use Touch Actions for a single action.');
|
|
318
|
+
}
|
|
319
|
+
const states = await (0, asyncbox_1.asyncmap)(actions, async (action) => await this.parseTouch(action, true), false);
|
|
320
|
+
return await this.doPerformMultiAction(elementId, states);
|
|
303
321
|
};
|
|
322
|
+
/**
|
|
323
|
+
* Reason for isolating doPerformMultiAction from performMultiAction is for reusing performMultiAction
|
|
324
|
+
* across android-drivers (like appium-uiautomator2-driver) and to avoid code duplication.
|
|
325
|
+
* Other android-drivers (like appium-uiautomator2-driver) need to override doPerformMultiAction
|
|
326
|
+
* to facilitate performMultiAction.
|
|
327
|
+
*/
|
|
304
328
|
commands.doPerformMultiAction = async function doPerformMultiAction(elementId, states) {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
329
|
+
let opts;
|
|
330
|
+
if (elementId) {
|
|
331
|
+
opts = {
|
|
332
|
+
elementId,
|
|
333
|
+
actions: states
|
|
334
|
+
};
|
|
335
|
+
return await this.bootstrap.sendAction('element:performMultiPointerGesture', opts);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
opts = {
|
|
339
|
+
actions: states
|
|
340
|
+
};
|
|
341
|
+
return await this.bootstrap.sendAction('performMultiPointerGesture', opts);
|
|
342
|
+
}
|
|
318
343
|
};
|
|
319
344
|
Object.assign(extensions, commands, helpers);
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbG9kYXNoIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfYW5kcm9pZEhlbHBlcnMiLCJfYmx1ZWJpcmQiLCJfZHJpdmVyIiwiX2FzeW5jYm94IiwiX3N1cHBvcnQiLCJjb21tYW5kcyIsImhlbHBlcnMiLCJleHRlbnNpb25zIiwiZXhwb3J0cyIsImdldENvb3JkRGVmYXVsdCIsInZhbCIsInV0aWwiLCJoYXNWYWx1ZSIsImdldFN3aXBlVG91Y2hEdXJhdGlvbiIsIndhaXRHZXN0dXJlIiwiZHVyYXRpb24iLCJvcHRpb25zIiwibXMiLCJkb1RvdWNoQWN0aW9uIiwiYWN0aW9uIiwib3B0cyIsImVsZW1lbnQiLCJ4IiwieSIsImNvdW50IiwidGFwIiwidG91Y2hEb3duIiwidG91Y2hVcCIsInRvdWNoTW92ZSIsIkIiLCJkZWxheSIsInRvdWNoTG9uZ0NsaWNrIiwibG9nIiwid2FybiIsImVycm9yQW5kVGhyb3ciLCJkb1RvdWNoRHJhZyIsImdlc3R1cmVzIiwibG9uZ1ByZXNzIiwibW92ZVRvIiwic3RhcnRYIiwic3RhcnRZIiwiZW5kWCIsImVuZFkiLCJnZXRMb2NhdGlvbkluVmlldyIsImFwaUxldmVsIiwiYWRiIiwiZ2V0QXBpTGV2ZWwiLCJNYXRoIiwibWF4IiwiZHJhZyIsImZpeFJlbGVhc2UiLCJyZWxlYXNlIiwiXyIsImxhc3QiLCJjbG9uZSIsInJlZiIsImdlc3R1cmUiLCJyZXZlcnNlIiwibG9jIiwic2l6ZSIsImdldFNpemUiLCJ3aWR0aCIsImhlaWdodCIsInBpY2siLCJwZXJmb3JtR2VzdHVyZSIsImUiLCJpc0Vycm9yVHlwZSIsImVycm9ycyIsIk5vU3VjaEVsZW1lbnRFcnJvciIsImRlYnVnIiwiZ2V0U3dpcGVPcHRpb25zIiwidG91Y2hDb3VudCIsImRlc3RFbGVtZW50IiwibG9jUmVzdWx0Iiwic2l6ZVJlc3VsdCIsIm9mZnNldFgiLCJhYnMiLCJvZmZzZXRZIiwiZmlyc3RFbExvY2F0aW9uIiwicGVyZm9ybVRvdWNoIiwibGVuZ3RoIiwic3dpcGVPcHRzIiwic3dpcGUiLCJhY3Rpb25zIiwibWFwIiwiaGVhZCIsInBvcCIsInNsaWNlIiwicHJlc3MiLCJzaGlmdCIsIndhaXQiLCJmaXhlZEdlc3R1cmVzIiwicGFyc2VUb3VjaCIsImciLCJtdWx0aSIsInRvdWNoU3RhdGVPYmplY3RzIiwiYXN5bmNtYXAiLCJpbmNsdWRlcyIsIm9mZnNldCIsImVsZW1lbnRJZCIsInBvcyIsInRvdWNoU3RhdGVPYmplY3QiLCJ0aW1lT2Zmc2V0IiwicGFyc2VJbnQiLCJwcmV2UG9zIiwidGltZSIsInN0YXRlIiwiaXNVbmRlZmluZWQiLCJhbmRyb2lkSGVscGVycyIsInRydW5jYXRlRGVjaW1hbHMiLCJ0b3VjaCIsInBlcmZvcm1NdWx0aUFjdGlvbiIsIkVycm9yIiwic3RhdGVzIiwiZG9QZXJmb3JtTXVsdGlBY3Rpb24iLCJib290c3RyYXAiLCJzZW5kQWN0aW9uIiwiT2JqZWN0IiwiYXNzaWduIiwiX2RlZmF1bHQiLCJkZWZhdWx0Il0sInNvdXJjZXMiOlsiLi4vLi4vLi4vbGliL2NvbW1hbmRzL3RvdWNoLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgYW5kcm9pZEhlbHBlcnMgZnJvbSAnLi4vYW5kcm9pZC1oZWxwZXJzJztcbmltcG9ydCBCIGZyb20gJ2JsdWViaXJkJztcbmltcG9ydCB7IGVycm9ycywgaXNFcnJvclR5cGUgfSBmcm9tICdhcHBpdW0vZHJpdmVyJztcbmltcG9ydCB7IGFzeW5jbWFwIH0gZnJvbSAnYXN5bmNib3gnO1xuaW1wb3J0IHsgdXRpbCB9IGZyb20gJ0BhcHBpdW0vc3VwcG9ydCc7XG5cbmxldCBjb21tYW5kcyA9IHt9LCBoZWxwZXJzID0ge30sIGV4dGVuc2lvbnMgPSB7fTtcblxuZnVuY3Rpb24gZ2V0Q29vcmREZWZhdWx0ICh2YWwpIHtcbiAgLy8gZ29pbmcgdGhlIGxvbmcgd2F5IGFuZCBjaGVja2luZyBmb3IgdW5kZWZpbmVkIGFuZCBudWxsIHNpbmNlXG4gIC8vIHdlIGNhbid0IGJlIGFzc3VyZWQgYGVsSWRgIGlzIGEgc3RyaW5nIGFuZCBub3QgYW4gaW50LiBTYW1lXG4gIC8vIHRoaW5nIHdpdGggZGVzdEVsZW1lbnQgYmVsb3cuXG4gIHJldHVybiB1dGlsLmhhc1ZhbHVlKHZhbCkgPyB2YWwgOiAwLjU7XG59XG5cbmZ1bmN0aW9uIGdldFN3aXBlVG91Y2hEdXJhdGlvbiAod2FpdEdlc3R1cmUpIHtcbiAgLy8gdGhlIHRvdWNoIGFjdGlvbiBhcGkgdXNlcyBtcywgd2Ugd2FudCBzZWNvbmRzXG4gIC8vIDAuOCBpcyB0aGUgZGVmYXVsdCB0aW1lIGZvciB0aGUgb3BlcmF0aW9uXG4gIGxldCBkdXJhdGlvbiA9IDAuODtcbiAgaWYgKHR5cGVvZiB3YWl0R2VzdHVyZS5vcHRpb25zLm1zICE9PSAndW5kZWZpbmVkJyAmJiB3YWl0R2VzdHVyZS5vcHRpb25zLm1zKSB7XG4gICAgZHVyYXRpb24gPSB3YWl0R2VzdHVyZS5vcHRpb25zLm1zIC8gMTAwMDtcbiAgICBpZiAoZHVyYXRpb24gPT09IDApIHtcbiAgICAgIC8vIHNldCB0byBhIHZlcnkgbG93IG51bWJlciwgc2luY2UgdGhleSB3YW50ZWQgaXQgZmFzdFxuICAgICAgLy8gYnV0IGJlbG93IDAuMSBiZWNvbWVzIDAgc3RlcHMsIHdoaWNoIGNhdXNlcyBlcnJvcnNcbiAgICAgIGR1cmF0aW9uID0gMC4xO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZHVyYXRpb247XG59XG5cbmNvbW1hbmRzLmRvVG91Y2hBY3Rpb24gPSBhc3luYyBmdW5jdGlvbiBkb1RvdWNoQWN0aW9uIChhY3Rpb24sIG9wdHMgPSB7fSkge1xuICBjb25zdCB7IGVsZW1lbnQsIHgsIHksIGNvdW50LCBtcywgZHVyYXRpb24gfSA9IG9wdHM7XG4gIC8vIHBhcnNlVG91Y2ggcHJlY2FsY3VsYXRlcyBhYnNvbHV0ZSBlbGVtZW50IHBvc2l0aW9uc1xuICAvLyBzbyB0aGVyZSBpcyBubyBuZWVkIHRvIHBhc3MgYGVsZW1lbnRgIHRvIHRoZSBhZmZlY3RlZCBnZXN0dXJlc1xuICBzd2l0Y2ggKGFjdGlvbikge1xuICAgIGNhc2UgJ3RhcCc6XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy50YXAobnVsbCwgeCwgeSwgY291bnQpO1xuICAgIGNhc2UgJ3ByZXNzJzpcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLnRvdWNoRG93bihudWxsLCB4LCB5KTtcbiAgICBjYXNlICdyZWxlYXNlJzpcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLnRvdWNoVXAoZWxlbWVudCwgeCwgeSk7XG4gICAgY2FzZSAnbW92ZVRvJzpcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLnRvdWNoTW92ZShudWxsLCB4LCB5KTtcbiAgICBjYXNlICd3YWl0JzpcbiAgICAgIHJldHVybiBhd2FpdCBCLmRlbGF5KG1zKTtcbiAgICBjYXNlICdsb25nUHJlc3MnOlxuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMudG91Y2hMb25nQ2xpY2sobnVsbCwgeCwgeSwgZHVyYXRpb24gfHwgMTAwMCk7XG4gICAgY2FzZSAnY2FuY2VsJzpcbiAgICAgIC8vIFRPRE86IGNsYXJpZnkgYmVoYXZpb3Igb2YgJ2NhbmNlbCcgYWN0aW9uIGFuZCBmaXggdGhpc1xuICAgICAgdGhpcy5sb2cud2FybignQ2FuY2VsIGFjdGlvbiBjdXJyZW50bHkgaGFzIG5vIGVmZmVjdCcpO1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRoaXMubG9nLmVycm9yQW5kVGhyb3coYHVua25vd24gYWN0aW9uICR7YWN0aW9ufWApO1xuICB9XG59O1xuXG4vLyBkcmFnIGlzICpub3QqIHByZXNzLW1vdmUtcmVsZWFzZSwgc28gd2UgbmVlZCB0byB0cmFuc2xhdGVcbi8vIGRyYWcgd29ya3MgZmluZSBmb3Igc2Nyb2xsLCBhcyB3ZWxsXG5oZWxwZXJzLmRvVG91Y2hEcmFnID0gYXN5bmMgZnVuY3Rpb24gZG9Ub3VjaERyYWcgKGdlc3R1cmVzKSB7XG4gIGxldCBsb25nUHJlc3MgPSBnZXN0dXJlc1swXTtcbiAgbGV0IG1vdmVUbyA9IGdlc3R1cmVzWzFdO1xuICBsZXQgc3RhcnRYID0gbG9uZ1ByZXNzLm9wdGlvbnMueCB8fCAwLFxuICAgICAgc3RhcnRZID0gbG9uZ1ByZXNzLm9wdGlvbnMueSB8fCAwLFxuICAgICAgZW5kWCA9IG1vdmVUby5vcHRpb25zLnggfHwgMCxcbiAgICAgIGVuZFkgPSBtb3ZlVG8ub3B0aW9ucy55IHx8IDA7XG4gIGlmIChsb25nUHJlc3Mub3B0aW9ucy5lbGVtZW50KSB7XG4gICAgbGV0IHt4LCB5fSA9IGF3YWl0IHRoaXMuZ2V0TG9jYXRpb25JblZpZXcobG9uZ1ByZXNzLm9wdGlvbnMuZWxlbWVudCk7XG4gICAgc3RhcnRYICs9IHggfHwgMDtcbiAgICBzdGFydFkgKz0geSB8fCAwO1xuICB9XG4gIGlmIChtb3ZlVG8ub3B0aW9ucy5lbGVtZW50KSB7XG4gICAgbGV0IHt4LCB5fSA9IGF3YWl0IHRoaXMuZ2V0TG9jYXRpb25JblZpZXcobW92ZVRvLm9wdGlvbnMuZWxlbWVudCk7XG4gICAgZW5kWCArPSB4IHx8IDA7XG4gICAgZW5kWSArPSB5IHx8IDA7XG4gIH1cblxuICBsZXQgYXBpTGV2ZWwgPSBhd2FpdCB0aGlzLmFkYi5nZXRBcGlMZXZlbCgpO1xuICAvLyBsb2xsaXBvcCB0YWtlcyBhIGxpdHRsZSBsb25nZXIgdG8gZ2V0IHRoaW5ncyByb2xsaW5nXG4gIGxldCBkdXJhdGlvbiA9IGFwaUxldmVsID49IDUgPyAyIDogMTtcbiAgLy8gbWFrZSBzdXJlIHRoYXQgaWYgdGhlIGxvbmcgcHJlc3MgaGFzIGEgZHVyYXRpb24sIHdlIHVzZSBpdC5cbiAgaWYgKGxvbmdQcmVzcy5vcHRpb25zICYmIGxvbmdQcmVzcy5vcHRpb25zLmR1cmF0aW9uKSB7XG4gICAgZHVyYXRpb24gPSBNYXRoLm1heChsb25nUHJlc3Mub3B0aW9ucy5kdXJhdGlvbiAvIDEwMDAsIGR1cmF0aW9uKTtcbiAgfVxuXG4gIC8vIGBkcmFnYCB3aWxsIHRha2UgY2FyZSBvZiB3aGV0aGVyIHRoZXJlIGlzIGFuIGVsZW1lbnQgb3Igbm90IGF0IHRoYXQgbGV2ZWxcbiAgcmV0dXJuIGF3YWl0IHRoaXMuZHJhZyhzdGFydFgsIHN0YXJ0WSwgZW5kWCwgZW5kWSwgZHVyYXRpb24sIDEsIGxvbmdQcmVzcy5vcHRpb25zLmVsZW1lbnQsIG1vdmVUby5vcHRpb25zLmVsZW1lbnQpO1xufTtcblxuLy8gUmVsZWFzZSBnZXN0dXJlIG5lZWRzIGVsZW1lbnQgb3IgY28tb3JkaW5hdGVzIHRvIHJlbGVhc2UgaXQgZnJvbSB0aGF0IHBvc2l0aW9uXG4vLyBvciBlbHNlIHJlbGVhc2UgZ2VzdHVyZSBpcyBwZXJmb3JtZWQgZnJvbSBjZW50ZXIgb2YgdGhlIHNjcmVlbiwgc28gdG8gZml4IGl0XG4vLyBUaGlzIG1ldGhvZCBzZXRzIGNvLW9yZGluYXRlcy9lbGVtZW50IHRvIHJlbGVhc2UgZ2VzdHVyZSBpZiBpdCBoYXMgbm8gb3B0aW9ucyBzZXQgYWxyZWFkeS5cbmhlbHBlcnMuZml4UmVsZWFzZSA9IGFzeW5jIGZ1bmN0aW9uIGZpeFJlbGVhc2UgKGdlc3R1cmVzKSB7XG4gIGxldCByZWxlYXNlID0gXy5sYXN0KGdlc3R1cmVzKTtcbiAgLy8gc29tZXRpbWVzIHRoZXJlIGFyZSBubyBvcHRpb25zXG4gIHJlbGVhc2Uub3B0aW9ucyA9IHJlbGVhc2Uub3B0aW9ucyB8fCB7fTtcbiAgLy8gbm90aGluZyB0byBkbyBpZiByZWxlYXNlIG9wdGlvbnMgYXJlIGFscmVhZHkgc2V0XG4gIGlmIChyZWxlYXNlLm9wdGlvbnMuZWxlbWVudCB8fCAocmVsZWFzZS5vcHRpb25zLnggJiYgcmVsZWFzZS5vcHRpb25zLnkpKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIC8vIHdpdGhvdXQgY29vcmRpbmF0ZXMsIGByZWxlYXNlYCB1c2VzIHRoZSBjZW50ZXIgb2YgdGhlIHNjcmVlbiwgd2hpY2gsXG4gIC8vIGdlbmVyYWxseSBzcGVha2luZywgaXMgbm90IHdoYXQgd2Ugd2FudFxuICAvLyB0aGVyZWZvcmU6IGxvb3AgYmFja3dhcmRzIGFuZCB1c2UgdGhlIGxhc3QgY29tbWFuZCB3aXRoIGFuIGVsZW1lbnQgYW5kL29yXG4gIC8vIG9mZnNldCBjb29yZGluYXRlc1xuICBnZXN0dXJlcyA9IF8uY2xvbmUoZ2VzdHVyZXMpO1xuICBsZXQgcmVmID0gbnVsbDtcbiAgZm9yIChsZXQgZ2VzdHVyZSBvZiBnZXN0dXJlcy5yZXZlcnNlKCkpIHtcbiAgICBsZXQgb3B0cyA9IGdlc3R1cmUub3B0aW9ucztcbiAgICBpZiAob3B0cy5lbGVtZW50IHx8IChvcHRzLnggJiYgb3B0cy55KSkge1xuICAgICAgcmVmID0gZ2VzdHVyZTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuICBpZiAocmVmKSB7XG4gICAgbGV0IG9wdHMgPSByZWYub3B0aW9ucztcbiAgICBpZiAob3B0cy5lbGVtZW50KSB7XG4gICAgICBsZXQgbG9jID0gYXdhaXQgdGhpcy5nZXRMb2NhdGlvbkluVmlldyhvcHRzLmVsZW1lbnQpO1xuICAgICAgaWYgKG9wdHMueCAmJiBvcHRzLnkpIHtcbiAgICAgICAgLy8gdGhpcyBpcyBhbiBvZmZzZXQgZnJvbSB0aGUgZWxlbWVudFxuICAgICAgICByZWxlYXNlLm9wdGlvbnMgPSB7XG4gICAgICAgICAgeDogbG9jLnggKyBvcHRzLngsXG4gICAgICAgICAgeTogbG9jLnkgKyBvcHRzLnlcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHRoaXMgaXMgdGhlIGNlbnRlciBvZiB0aGUgZWxlbWVudFxuICAgICAgICBsZXQgc2l6ZSA9IGF3YWl0IHRoaXMuZ2V0U2l6ZShvcHRzLmVsZW1lbnQpO1xuICAgICAgICByZWxlYXNlLm9wdGlvbnMgPSB7XG4gICAgICAgICAgeDogbG9jLnggKyBzaXplLndpZHRoIC8gMixcbiAgICAgICAgICB5OiBsb2MueSArIHNpemUuaGVpZ2h0IC8gMlxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZWxlYXNlLm9wdGlvbnMgPSBfLnBpY2sob3B0cywgJ3gnLCAneScpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVsZWFzZTtcbn07XG5cbi8vIFBlcmZvcm0gb25lIGdlc3R1cmVcbmhlbHBlcnMucGVyZm9ybUdlc3R1cmUgPSBhc3luYyBmdW5jdGlvbiBwZXJmb3JtR2VzdHVyZSAoZ2VzdHVyZSkge1xuICB0cnkge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLmRvVG91Y2hBY3Rpb24oZ2VzdHVyZS5hY3Rpb24sIGdlc3R1cmUub3B0aW9ucyB8fCB7fSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAvLyBzb21ldGltZSB0aGUgZWxlbWVudCBpcyBub3QgYXZhaWxhYmxlIHdoZW4gcmVsZWFzaW5nLCByZXRyeSB3aXRob3V0IGl0XG4gICAgaWYgKGlzRXJyb3JUeXBlKGUsIGVycm9ycy5Ob1N1Y2hFbGVtZW50RXJyb3IpICYmIGdlc3R1cmUuYWN0aW9uID09PSAncmVsZWFzZScgJiZcbiAgICAgICAgZ2VzdHVyZS5vcHRpb25zLmVsZW1lbnQpIHtcbiAgICAgIGRlbGV0ZSBnZXN0dXJlLm9wdGlvbnMuZWxlbWVudDtcbiAgICAgIHRoaXMubG9nLmRlYnVnKGByZXRyeWluZyByZWxlYXNlIHdpdGhvdXQgZWxlbWVudCBvcHRzOiAke2dlc3R1cmUub3B0aW9uc30uYCk7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5kb1RvdWNoQWN0aW9uKGdlc3R1cmUuYWN0aW9uLCBnZXN0dXJlLm9wdGlvbnMgfHwge30pO1xuICAgIH1cbiAgICB0aHJvdyBlO1xuICB9XG59O1xuXG5jb21tYW5kcy5nZXRTd2lwZU9wdGlvbnMgPSBhc3luYyBmdW5jdGlvbiBnZXRTd2lwZU9wdGlvbnMgKGdlc3R1cmVzLCB0b3VjaENvdW50ID0gMSkge1xuICBsZXQgc3RhcnRYID0gZ2V0Q29vcmREZWZhdWx0KGdlc3R1cmVzWzBdLm9wdGlvbnMueCksXG4gICAgICBzdGFydFkgPSBnZXRDb29yZERlZmF1bHQoZ2VzdHVyZXNbMF0ub3B0aW9ucy55KSxcbiAgICAgIGVuZFggPSBnZXRDb29yZERlZmF1bHQoZ2VzdHVyZXNbMl0ub3B0aW9ucy54KSxcbiAgICAgIGVuZFkgPSBnZXRDb29yZERlZmF1bHQoZ2VzdHVyZXNbMl0ub3B0aW9ucy55KSxcbiAgICAgIGR1cmF0aW9uID0gZ2V0U3dpcGVUb3VjaER1cmF0aW9uKGdlc3R1cmVzWzFdKSxcbiAgICAgIGVsZW1lbnQgPSBnZXN0dXJlc1swXS5vcHRpb25zLmVsZW1lbnQsXG4gICAgICBkZXN0RWxlbWVudCA9IGdlc3R1cmVzWzJdLm9wdGlvbnMuZWxlbWVudCB8fCBnZXN0dXJlc1swXS5vcHRpb25zLmVsZW1lbnQ7XG5cbiAgLy8gdGhlcmUncyBubyBkZXN0aW5hdGlvbiBlbGVtZW50IGhhbmRsaW5nIGluIGJvb3RzdHJhcCBhbmQgc2luY2UgaXQgYXBwbGllcyB0byBhbGwgcGxhdGZvcm1zLCB3ZSBoYW5kbGUgaXQgaGVyZVxuICBpZiAodXRpbC5oYXNWYWx1ZShkZXN0RWxlbWVudCkpIHtcbiAgICBsZXQgbG9jUmVzdWx0ID0gYXdhaXQgdGhpcy5nZXRMb2NhdGlvbkluVmlldyhkZXN0RWxlbWVudCk7XG4gICAgbGV0IHNpemVSZXN1bHQgPSBhd2FpdCB0aGlzLmdldFNpemUoZGVzdEVsZW1lbnQpO1xuICAgIGxldCBvZmZzZXRYID0gKE1hdGguYWJzKGVuZFgpIDwgMSAmJiBNYXRoLmFicyhlbmRYKSA+IDApID8gc2l6ZVJlc3VsdC53aWR0aCAqIGVuZFggOiBlbmRYO1xuICAgIGxldCBvZmZzZXRZID0gKE1hdGguYWJzKGVuZFkpIDwgMSAmJiBNYXRoLmFicyhlbmRZKSA+IDApID8gc2l6ZVJlc3VsdC5oZWlnaHQgKiBlbmRZIDogZW5kWTtcbiAgICBlbmRYID0gbG9jUmVzdWx0LnggKyBvZmZzZXRYO1xuICAgIGVuZFkgPSBsb2NSZXN1bHQueSArIG9mZnNldFk7XG4gICAgLy8gaWYgdGhlIHRhcmdldCBlbGVtZW50IHdhcyBwcm92aWRlZCwgdGhlIGNvb3JkaW5hdGVzIGZvciB0aGUgZGVzdGluYXRpb24gbmVlZCB0byBiZSByZWxhdGl2ZSB0byBpdC5cbiAgICBpZiAodXRpbC5oYXNWYWx1ZShlbGVtZW50KSkge1xuICAgICAgbGV0IGZpcnN0RWxMb2NhdGlvbiA9IGF3YWl0IHRoaXMuZ2V0TG9jYXRpb25JblZpZXcoZWxlbWVudCk7XG4gICAgICBlbmRYIC09IGZpcnN0RWxMb2NhdGlvbi54O1xuICAgICAgZW5kWSAtPSBmaXJzdEVsTG9jYXRpb24ueTtcbiAgICB9XG4gIH1cbiAgLy8gY2xpZW50cyBhcmUgcmVzcG9uc2libGUgdG8gdXNlIHRoZXNlIG9wdGlvbnMgY29ycmVjdGx5XG4gIHJldHVybiB7c3RhcnRYLCBzdGFydFksIGVuZFgsIGVuZFksIGR1cmF0aW9uLCB0b3VjaENvdW50LCBlbGVtZW50fTtcbn07XG5cbmNvbW1hbmRzLnBlcmZvcm1Ub3VjaCA9IGFzeW5jIGZ1bmN0aW9uIHBlcmZvcm1Ub3VjaCAoZ2VzdHVyZXMpIHtcbiAgLy8gcHJlc3Mtd2FpdC1tb3ZlVG8tcmVsZWFzZSBpcyBgc3dpcGVgLCBzbyB1c2UgbmF0aXZlIG1ldGhvZFxuICBpZiAoZ2VzdHVyZXMubGVuZ3RoID09PSA0ICYmXG4gICAgICBnZXN0dXJlc1swXS5hY3Rpb24gPT09ICdwcmVzcycgJiZcbiAgICAgIGdlc3R1cmVzWzFdLmFjdGlvbiA9PT0gJ3dhaXQnICYmXG4gICAgICBnZXN0dXJlc1syXS5hY3Rpb24gPT09ICdtb3ZlVG8nICYmXG4gICAgICBnZXN0dXJlc1szXS5hY3Rpb24gPT09ICdyZWxlYXNlJykge1xuXG4gICAgbGV0IHN3aXBlT3B0cyA9IGF3YWl0IHRoaXMuZ2V0U3dpcGVPcHRpb25zKGdlc3R1cmVzKTtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5zd2lwZShzd2lwZU9wdHMuc3RhcnRYLCBzd2lwZU9wdHMuc3RhcnRZLCBzd2lwZU9wdHMuZW5kWCxcbiAgICAgICAgc3dpcGVPcHRzLmVuZFksIHN3aXBlT3B0cy5kdXJhdGlvbiwgc3dpcGVPcHRzLnRvdWNoQ291bnQsXG4gICAgICAgIHN3aXBlT3B0cy5lbGVtZW50KTtcbiAgfVxuICBsZXQgYWN0aW9ucyA9IF8ubWFwKGdlc3R1cmVzLCAnYWN0aW9uJyk7XG5cbiAgaWYgKGFjdGlvbnNbMF0gPT09ICdsb25nUHJlc3MnICYmIGFjdGlvbnNbMV0gPT09ICdtb3ZlVG8nICYmIGFjdGlvbnNbMl0gPT09ICdyZWxlYXNlJykge1xuICAgIC8vIHNvbWUgdGhpbmdzIGFyZSBzcGVjaWFsXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuZG9Ub3VjaERyYWcoZ2VzdHVyZXMpO1xuICB9IGVsc2Uge1xuICAgIGlmIChhY3Rpb25zLmxlbmd0aCA9PT0gMikge1xuICAgICAgLy8gYHByZXNzYCB3aXRob3V0IGEgd2FpdCBpcyB0b28gc2xvdyBhbmQgZ2V0cyBpbnRlcnByZXR0ZWQgYXMgYSBgbG9uZ1ByZXNzYFxuICAgICAgaWYgKF8uaGVhZChhY3Rpb25zKSA9PT0gJ3ByZXNzJyAmJiBfLmxhc3QoYWN0aW9ucykgPT09ICdyZWxlYXNlJykge1xuICAgICAgICBhY3Rpb25zWzBdID0gJ3RhcCc7XG4gICAgICAgIGdlc3R1cmVzWzBdLmFjdGlvbiA9ICd0YXAnO1xuICAgICAgfVxuXG4gICAgICAvLyB0aGUgYGxvbmdQcmVzc2AgYW5kIGB0YXBgIG1ldGhvZHMgcmVsZWFzZSBvbiB0aGVpciBvd25cbiAgICAgIGlmICgoXy5oZWFkKGFjdGlvbnMpID09PSAndGFwJyB8fCBfLmhlYWQoYWN0aW9ucykgPT09ICdsb25nUHJlc3MnKSAmJiBfLmxhc3QoYWN0aW9ucykgPT09ICdyZWxlYXNlJykge1xuICAgICAgICBnZXN0dXJlcy5wb3AoKTtcbiAgICAgICAgYWN0aW9ucy5wb3AoKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gbG9uZ3ByZXNzIGZvbGxvd2VkIGJ5IGFueXRoaW5nIG90aGVyIHRoYW4gcmVsZWFzZSBzaG91bGQgYmVjb21lIGEgcHJlc3MgYW5kIHdhaXRcbiAgICAgIGlmIChhY3Rpb25zWzBdID09PSAnbG9uZ1ByZXNzJykge1xuICAgICAgICBhY3Rpb25zID0gWydwcmVzcycsICd3YWl0JywgLi4uYWN0aW9ucy5zbGljZSgxKV07XG5cbiAgICAgICAgbGV0IHByZXNzID0gZ2VzdHVyZXMuc2hpZnQoKTtcbiAgICAgICAgcHJlc3MuYWN0aW9uID0gJ3ByZXNzJztcbiAgICAgICAgbGV0IHdhaXQgPSB7XG4gICAgICAgICAgYWN0aW9uOiAnd2FpdCcsXG4gICAgICAgICAgb3B0aW9uczoge21zOiBwcmVzcy5vcHRpb25zLmR1cmF0aW9uIHx8IDEwMDB9XG4gICAgICAgIH07XG4gICAgICAgIGRlbGV0ZSBwcmVzcy5vcHRpb25zLmR1cmF0aW9uO1xuICAgICAgICBnZXN0dXJlcyA9IFtwcmVzcywgd2FpdCwgLi4uZ2VzdHVyZXNdO1xuICAgICAgfVxuICAgIH1cblxuICAgIGxldCBmaXhlZEdlc3R1cmVzID0gYXdhaXQgdGhpcy5wYXJzZVRvdWNoKGdlc3R1cmVzLCBmYWxzZSk7XG4gICAgLy8gZml4IHJlbGVhc2UgYWN0aW9uIHRoZW4gcGVyZm9ybSBhbGwgYWN0aW9uc1xuICAgIGlmIChhY3Rpb25zW2FjdGlvbnMubGVuZ3RoIC0gMV0gPT09ICdyZWxlYXNlJykge1xuICAgICAgYWN0aW9uc1thY3Rpb25zLmxlbmd0aCAtIDFdID0gYXdhaXQgdGhpcy5maXhSZWxlYXNlKGdlc3R1cmVzKTtcbiAgICB9XG4gICAgZm9yIChsZXQgZyBvZiBmaXhlZEdlc3R1cmVzKSB7XG4gICAgICBhd2FpdCB0aGlzLnBlcmZvcm1HZXN0dXJlKGcpO1xuICAgIH1cbiAgfVxufTtcblxuaGVscGVycy5wYXJzZVRvdWNoID0gYXN5bmMgZnVuY3Rpb24gcGFyc2VUb3VjaCAoZ2VzdHVyZXMsIG11bHRpKSB7XG4gIC8vIGJlY2F1c2UgbXVsdGktdG91Y2ggcmVsZWFzZXMgYXQgdGhlIGVuZCBieSBkZWZhdWx0XG4gIGlmIChtdWx0aSAmJiBfLmxhc3QoZ2VzdHVyZXMpLmFjdGlvbiA9PT0gJ3JlbGVhc2UnKSB7XG4gICAgZ2VzdHVyZXMucG9wKCk7XG4gIH1cblxuICBsZXQgdG91Y2hTdGF0ZU9iamVjdHMgPSBhd2FpdCBhc3luY21hcChnZXN0dXJlcywgYXN5bmMgKGdlc3R1cmUpID0+IHtcbiAgICBsZXQgb3B0aW9ucyA9IGdlc3R1cmUub3B0aW9ucyB8fCB7fTtcbiAgICBpZiAoXy5pbmNsdWRlcyhbJ3ByZXNzJywgJ21vdmVUbycsICd0YXAnLCAnbG9uZ1ByZXNzJ10sIGdlc3R1cmUuYWN0aW9uKSkge1xuICAgICAgb3B0aW9ucy5vZmZzZXQgPSBmYWxzZTtcbiAgICAgIGxldCBlbGVtZW50SWQgPSBnZXN0dXJlLm9wdGlvbnMuZWxlbWVudDtcbiAgICAgIGlmIChlbGVtZW50SWQpIHtcbiAgICAgICAgbGV0IHBvcyA9IGF3YWl0IHRoaXMuZ2V0TG9jYXRpb25JblZpZXcoZWxlbWVudElkKTtcbiAgICAgICAgaWYgKGdlc3R1cmUub3B0aW9ucy54IHx8IGdlc3R1cmUub3B0aW9ucy55KSB7XG4gICAgICAgICAgb3B0aW9ucy54ID0gcG9zLnggKyAoZ2VzdHVyZS5vcHRpb25zLnggfHwgMCk7XG4gICAgICAgICAgb3B0aW9ucy55ID0gcG9zLnkgKyAoZ2VzdHVyZS5vcHRpb25zLnkgfHwgMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3Qge3dpZHRoLCBoZWlnaHR9ID0gYXdhaXQgdGhpcy5nZXRTaXplKGVsZW1lbnRJZCk7XG4gICAgICAgICAgb3B0aW9ucy54ID0gcG9zLnggKyAod2lkdGggLyAyKTtcbiAgICAgICAgICBvcHRpb25zLnkgPSBwb3MueSArIChoZWlnaHQgLyAyKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgdG91Y2hTdGF0ZU9iamVjdCA9IHtcbiAgICAgICAgICBhY3Rpb246IGdlc3R1cmUuYWN0aW9uLFxuICAgICAgICAgIG9wdGlvbnMsXG4gICAgICAgICAgdGltZU9mZnNldDogMC4wMDUsXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB0b3VjaFN0YXRlT2JqZWN0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3B0aW9ucy54ID0gKGdlc3R1cmUub3B0aW9ucy54IHx8IDApO1xuICAgICAgICBvcHRpb25zLnkgPSAoZ2VzdHVyZS5vcHRpb25zLnkgfHwgMCk7XG5cbiAgICAgICAgbGV0IHRvdWNoU3RhdGVPYmplY3QgPSB7XG4gICAgICAgICAgYWN0aW9uOiBnZXN0dXJlLmFjdGlvbixcbiAgICAgICAgICBvcHRpb25zLFxuICAgICAgICAgIHRpbWVPZmZzZXQ6IDAuMDA1LFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gdG91Y2hTdGF0ZU9iamVjdDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IG9mZnNldCA9IDAuMDA1O1xuICAgICAgaWYgKGdlc3R1cmUuYWN0aW9uID09PSAnd2FpdCcpIHtcbiAgICAgICAgb3B0aW9ucyA9IGdlc3R1cmUub3B0aW9ucztcbiAgICAgICAgb2Zmc2V0ID0gKHBhcnNlSW50KGdlc3R1cmUub3B0aW9ucy5tcywgMTApIC8gMTAwMCk7XG4gICAgICB9XG4gICAgICBsZXQgdG91Y2hTdGF0ZU9iamVjdCA9IHtcbiAgICAgICAgYWN0aW9uOiBnZXN0dXJlLmFjdGlvbixcbiAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgdGltZU9mZnNldDogb2Zmc2V0LFxuICAgICAgfTtcbiAgICAgIHJldHVybiB0b3VjaFN0YXRlT2JqZWN0O1xuICAgIH1cbiAgfSwgZmFsc2UpO1xuICAvLyB3ZSBuZWVkIHRvIGNoYW5nZSB0aGUgdGltZSAod2hpY2ggaXMgbm93IGFuIG9mZnNldClcbiAgLy8gYW5kIHRoZSBwb3NpdGlvbiAod2hpY2ggbWF5IGJlIGFuIG9mZnNldClcbiAgbGV0IHByZXZQb3MgPSBudWxsLFxuICAgICAgdGltZSA9IDA7XG4gIGZvciAobGV0IHN0YXRlIG9mIHRvdWNoU3RhdGVPYmplY3RzKSB7XG4gICAgaWYgKF8uaXNVbmRlZmluZWQoc3RhdGUub3B0aW9ucy54KSAmJiBfLmlzVW5kZWZpbmVkKHN0YXRlLm9wdGlvbnMueSkgJiYgcHJldlBvcyAhPT0gbnVsbCkge1xuICAgICAgLy8gdGhpcyBoYXBwZW5zIHdpdGggd2FpdFxuICAgICAgc3RhdGUub3B0aW9ucy54ID0gcHJldlBvcy54O1xuICAgICAgc3RhdGUub3B0aW9ucy55ID0gcHJldlBvcy55O1xuICAgIH1cbiAgICBpZiAoc3RhdGUub3B0aW9ucy5vZmZzZXQgJiYgcHJldlBvcykge1xuICAgICAgLy8gdGhlIGN1cnJlbnQgcG9zaXRpb24gaXMgYW4gb2Zmc2V0XG4gICAgICBzdGF0ZS5vcHRpb25zLnggKz0gcHJldlBvcy54O1xuICAgICAgc3RhdGUub3B0aW9ucy55ICs9IHByZXZQb3MueTtcbiAgICB9XG4gICAgZGVsZXRlIHN0YXRlLm9wdGlvbnMub2Zmc2V0O1xuICAgIGlmICghXy5pc1VuZGVmaW5lZChzdGF0ZS5vcHRpb25zLngpICYmICFfLmlzVW5kZWZpbmVkKHN0YXRlLm9wdGlvbnMueSkpIHtcbiAgICAgIHByZXZQb3MgPSBzdGF0ZS5vcHRpb25zO1xuICAgIH1cblxuICAgIGlmIChtdWx0aSkge1xuICAgICAgbGV0IHRpbWVPZmZzZXQgPSBzdGF0ZS50aW1lT2Zmc2V0O1xuICAgICAgdGltZSArPSB0aW1lT2Zmc2V0O1xuICAgICAgc3RhdGUudGltZSA9IGFuZHJvaWRIZWxwZXJzLnRydW5jYXRlRGVjaW1hbHModGltZSwgMyk7XG5cbiAgICAgIC8vIG11bHRpIGdlc3R1cmVzIHJlcXVpcmUgJ3RvdWNoJyByYXRoZXIgdGhhbiAnb3B0aW9ucydcbiAgICAgIGlmICghXy5pc1VuZGVmaW5lZChzdGF0ZS5vcHRpb25zLngpICYmICFfLmlzVW5kZWZpbmVkKHN0YXRlLm9wdGlvbnMueSkpIHtcbiAgICAgICAgc3RhdGUudG91Y2ggPSB7XG4gICAgICAgICAgeDogc3RhdGUub3B0aW9ucy54LFxuICAgICAgICAgIHk6IHN0YXRlLm9wdGlvbnMueVxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgZGVsZXRlIHN0YXRlLm9wdGlvbnM7XG4gICAgfVxuICAgIGRlbGV0ZSBzdGF0ZS50aW1lT2Zmc2V0O1xuICB9XG4gIHJldHVybiB0b3VjaFN0YXRlT2JqZWN0cztcbn07XG5cblxuY29tbWFuZHMucGVyZm9ybU11bHRpQWN0aW9uID0gYXN5bmMgZnVuY3Rpb24gcGVyZm9ybU11bHRpQWN0aW9uIChhY3Rpb25zLCBlbGVtZW50SWQpIHtcbiAgLy8gQW5kcm9pZCBuZWVkcyBhdCBsZWFzdCB0d28gYWN0aW9ucyB0byBiZSBhYmxlIHRvIHBlcmZvcm0gYSBtdWx0aSBwb2ludGVyIGdlc3R1cmVcbiAgaWYgKGFjdGlvbnMubGVuZ3RoID09PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNdWx0aSBQb2ludGVyIEdlc3R1cmVzIG5lZWQgYXQgbGVhc3QgdHdvIGFjdGlvbnMuICcgK1xuICAgICAgICAnVXNlIFRvdWNoIEFjdGlvbnMgZm9yIGEgc2luZ2xlIGFjdGlvbi4nKTtcbiAgfVxuXG4gIGNvbnN0IHN0YXRlcyA9IGF3YWl0IGFzeW5jbWFwKGFjdGlvbnMsIGFzeW5jIChhY3Rpb24pID0+IGF3YWl0IHRoaXMucGFyc2VUb3VjaChhY3Rpb24sIHRydWUpLCBmYWxzZSk7XG5cbiAgcmV0dXJuIGF3YWl0IHRoaXMuZG9QZXJmb3JtTXVsdGlBY3Rpb24oZWxlbWVudElkLCBzdGF0ZXMpO1xufTtcblxuLyoqXG4gKiBSZWFzb24gZm9yIGlzb2xhdGluZyBkb1BlcmZvcm1NdWx0aUFjdGlvbiBmcm9tIHBlcmZvcm1NdWx0aUFjdGlvbiBpcyBmb3IgcmV1c2luZyBwZXJmb3JtTXVsdGlBY3Rpb25cbiAqIGFjcm9zcyBhbmRyb2lkLWRyaXZlcnMgKGxpa2UgYXBwaXVtLXVpYXV0b21hdG9yMi1kcml2ZXIpIGFuZCB0byBhdm9pZCBjb2RlIGR1cGxpY2F0aW9uLlxuICogT3RoZXIgYW5kcm9pZC1kcml2ZXJzIChsaWtlIGFwcGl1bS11aWF1dG9tYXRvcjItZHJpdmVyKSBuZWVkIHRvIG92ZXJyaWRlIGRvUGVyZm9ybU11bHRpQWN0aW9uXG4gKiB0byBmYWNpbGl0YXRlIHBlcmZvcm1NdWx0aUFjdGlvbi5cbiAqL1xuY29tbWFuZHMuZG9QZXJmb3JtTXVsdGlBY3Rpb24gPSBhc3luYyBmdW5jdGlvbiBkb1BlcmZvcm1NdWx0aUFjdGlvbiAoZWxlbWVudElkLCBzdGF0ZXMpIHtcbiAgbGV0IG9wdHM7XG4gIGlmIChlbGVtZW50SWQpIHtcbiAgICBvcHRzID0ge1xuICAgICAgZWxlbWVudElkLFxuICAgICAgYWN0aW9uczogc3RhdGVzXG4gICAgfTtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5ib290c3RyYXAuc2VuZEFjdGlvbignZWxlbWVudDpwZXJmb3JtTXVsdGlQb2ludGVyR2VzdHVyZScsIG9wdHMpO1xuICB9IGVsc2Uge1xuICAgIG9wdHMgPSB7XG4gICAgICBhY3Rpb25zOiBzdGF0ZXNcbiAgICB9O1xuICAgIHJldHVybiBhd2FpdCB0aGlzLmJvb3RzdHJhcC5zZW5kQWN0aW9uKCdwZXJmb3JtTXVsdGlQb2ludGVyR2VzdHVyZScsIG9wdHMpO1xuICB9XG59O1xuXG5PYmplY3QuYXNzaWduKGV4dGVuc2lvbnMsIGNvbW1hbmRzLCBoZWxwZXJzKTtcbmV4cG9ydCB7IGNvbW1hbmRzLCBoZWxwZXJzIH07XG5leHBvcnQgZGVmYXVsdCBleHRlbnNpb25zO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQUFBLElBQUFBLE9BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLGVBQUEsR0FBQUYsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFFLFNBQUEsR0FBQUgsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFHLE9BQUEsR0FBQUgsT0FBQTtBQUNBLElBQUFJLFNBQUEsR0FBQUosT0FBQTtBQUNBLElBQUFLLFFBQUEsR0FBQUwsT0FBQTtBQUVBLElBQUlNLFFBQVEsR0FBRyxDQUFDLENBQUM7RUFBRUMsT0FBTyxHQUFHLENBQUMsQ0FBQztFQUFFQyxVQUFVLEdBQUcsQ0FBQyxDQUFDO0FBQUNDLE9BQUEsQ0FBQUYsT0FBQSxHQUFBQSxPQUFBO0FBQUFFLE9BQUEsQ0FBQUgsUUFBQSxHQUFBQSxR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
|
|
345
|
+
exports.default = extensions;
|
|
346
|
+
//# sourceMappingURL=touch.js.map
|