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.
Files changed (151) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/build/index.js +43 -40
  3. package/build/lib/android-helpers.d.ts +136 -0
  4. package/build/lib/android-helpers.d.ts.map +1 -0
  5. package/build/lib/android-helpers.js +760 -679
  6. package/build/lib/android-helpers.js.map +1 -1
  7. package/build/lib/bootstrap.d.ts +29 -0
  8. package/build/lib/bootstrap.d.ts.map +1 -0
  9. package/build/lib/bootstrap.js +192 -179
  10. package/build/lib/bootstrap.js.map +1 -1
  11. package/build/lib/commands/actions.d.ts +209 -0
  12. package/build/lib/commands/actions.d.ts.map +1 -0
  13. package/build/lib/commands/actions.js +327 -265
  14. package/build/lib/commands/actions.js.map +1 -1
  15. package/build/lib/commands/alert.d.ts +10 -0
  16. package/build/lib/commands/alert.d.ts.map +1 -0
  17. package/build/lib/commands/alert.js +12 -18
  18. package/build/lib/commands/alert.js.map +1 -1
  19. package/build/lib/commands/app-management.d.ts +314 -0
  20. package/build/lib/commands/app-management.d.ts.map +1 -0
  21. package/build/lib/commands/app-management.js +278 -110
  22. package/build/lib/commands/app-management.js.map +1 -1
  23. package/build/lib/commands/context.d.ts +94 -0
  24. package/build/lib/commands/context.d.ts.map +1 -0
  25. package/build/lib/commands/context.js +412 -260
  26. package/build/lib/commands/context.js.map +1 -1
  27. package/build/lib/commands/coverage.d.ts +5 -0
  28. package/build/lib/commands/coverage.d.ts.map +1 -0
  29. package/build/lib/commands/coverage.js +14 -17
  30. package/build/lib/commands/coverage.js.map +1 -1
  31. package/build/lib/commands/element.d.ts +36 -0
  32. package/build/lib/commands/element.d.ts.map +1 -0
  33. package/build/lib/commands/element.js +97 -127
  34. package/build/lib/commands/element.js.map +1 -1
  35. package/build/lib/commands/emu-console.d.ts +49 -0
  36. package/build/lib/commands/emu-console.d.ts.map +1 -0
  37. package/build/lib/commands/emu-console.js +36 -25
  38. package/build/lib/commands/emu-console.js.map +1 -1
  39. package/build/lib/commands/execute.d.ts +6 -0
  40. package/build/lib/commands/execute.d.ts.map +1 -0
  41. package/build/lib/commands/execute.js +68 -69
  42. package/build/lib/commands/execute.js.map +1 -1
  43. package/build/lib/commands/file-actions.d.ts +129 -0
  44. package/build/lib/commands/file-actions.d.ts.map +1 -0
  45. package/build/lib/commands/file-actions.js +321 -178
  46. package/build/lib/commands/file-actions.js.map +1 -1
  47. package/build/lib/commands/find.d.ts +13 -0
  48. package/build/lib/commands/find.d.ts.map +1 -0
  49. package/build/lib/commands/find.js +69 -51
  50. package/build/lib/commands/find.js.map +1 -1
  51. package/build/lib/commands/general.d.ts +133 -0
  52. package/build/lib/commands/general.d.ts.map +1 -0
  53. package/build/lib/commands/general.js +275 -216
  54. package/build/lib/commands/general.js.map +1 -1
  55. package/build/lib/commands/ime.d.ts +11 -0
  56. package/build/lib/commands/ime.d.ts.map +1 -0
  57. package/build/lib/commands/ime.js +27 -33
  58. package/build/lib/commands/ime.js.map +1 -1
  59. package/build/lib/commands/index.d.ts +3 -0
  60. package/build/lib/commands/index.d.ts.map +1 -0
  61. package/build/lib/commands/index.js +32 -35
  62. package/build/lib/commands/index.js.map +1 -1
  63. package/build/lib/commands/intent.d.ts +418 -0
  64. package/build/lib/commands/intent.d.ts.map +1 -0
  65. package/build/lib/commands/intent.js +281 -151
  66. package/build/lib/commands/intent.js.map +1 -1
  67. package/build/lib/commands/keyboard.d.ts +6 -0
  68. package/build/lib/commands/keyboard.d.ts.map +1 -0
  69. package/build/lib/commands/keyboard.js +6 -14
  70. package/build/lib/commands/keyboard.js.map +1 -1
  71. package/build/lib/commands/log.d.ts +45 -0
  72. package/build/lib/commands/log.d.ts.map +1 -0
  73. package/build/lib/commands/log.js +117 -103
  74. package/build/lib/commands/log.js.map +1 -1
  75. package/build/lib/commands/media-projection.d.ts +144 -0
  76. package/build/lib/commands/media-projection.d.ts.map +1 -0
  77. package/build/lib/commands/media-projection.js +228 -171
  78. package/build/lib/commands/media-projection.js.map +1 -1
  79. package/build/lib/commands/network.d.ts +139 -0
  80. package/build/lib/commands/network.d.ts.map +1 -0
  81. package/build/lib/commands/network.js +249 -181
  82. package/build/lib/commands/network.js.map +1 -1
  83. package/build/lib/commands/performance.d.ts +101 -0
  84. package/build/lib/commands/performance.d.ts.map +1 -0
  85. package/build/lib/commands/performance.js +390 -236
  86. package/build/lib/commands/performance.js.map +1 -1
  87. package/build/lib/commands/permissions.d.ts +93 -0
  88. package/build/lib/commands/permissions.d.ts.map +1 -0
  89. package/build/lib/commands/permissions.js +133 -93
  90. package/build/lib/commands/permissions.js.map +1 -1
  91. package/build/lib/commands/recordscreen.d.ts +194 -0
  92. package/build/lib/commands/recordscreen.d.ts.map +1 -0
  93. package/build/lib/commands/recordscreen.js +293 -224
  94. package/build/lib/commands/recordscreen.js.map +1 -1
  95. package/build/lib/commands/shell.d.ts +8 -0
  96. package/build/lib/commands/shell.d.ts.map +1 -0
  97. package/build/lib/commands/shell.js +38 -43
  98. package/build/lib/commands/shell.js.map +1 -1
  99. package/build/lib/commands/streamscreen.d.ts +104 -0
  100. package/build/lib/commands/streamscreen.d.ts.map +1 -0
  101. package/build/lib/commands/streamscreen.js +364 -305
  102. package/build/lib/commands/streamscreen.js.map +1 -1
  103. package/build/lib/commands/system-bars.d.ts +100 -0
  104. package/build/lib/commands/system-bars.d.ts.map +1 -0
  105. package/build/lib/commands/system-bars.js +148 -90
  106. package/build/lib/commands/system-bars.js.map +1 -1
  107. package/build/lib/commands/touch.d.ts +30 -0
  108. package/build/lib/commands/touch.d.ts.map +1 -0
  109. package/build/lib/commands/touch.js +311 -287
  110. package/build/lib/commands/touch.js.map +1 -1
  111. package/build/lib/desired-caps.d.ts +353 -0
  112. package/build/lib/desired-caps.d.ts.map +1 -0
  113. package/build/lib/desired-caps.js +291 -292
  114. package/build/lib/desired-caps.js.map +1 -1
  115. package/build/lib/driver.d.ts +430 -0
  116. package/build/lib/driver.d.ts.map +1 -0
  117. package/build/lib/driver.js +449 -384
  118. package/build/lib/driver.js.map +1 -1
  119. package/build/lib/logger.d.ts +3 -0
  120. package/build/lib/logger.d.ts.map +1 -0
  121. package/build/lib/logger.js +5 -11
  122. package/build/lib/logger.js.map +1 -1
  123. package/build/lib/method-map.d.ts +389 -0
  124. package/build/lib/method-map.d.ts.map +1 -0
  125. package/build/lib/method-map.js +220 -394
  126. package/build/lib/method-map.js.map +1 -1
  127. package/build/lib/stubs.d.ts +8 -0
  128. package/build/lib/stubs.d.ts.map +1 -0
  129. package/build/lib/stubs.js +5 -0
  130. package/build/lib/stubs.js.map +1 -0
  131. package/build/lib/uiautomator.d.ts +24 -0
  132. package/build/lib/uiautomator.d.ts.map +1 -0
  133. package/build/lib/uiautomator.js +86 -82
  134. package/build/lib/uiautomator.js.map +1 -1
  135. package/build/lib/unlock-helpers.d.ts +38 -0
  136. package/build/lib/unlock-helpers.d.ts.map +1 -0
  137. package/build/lib/unlock-helpers.js +228 -204
  138. package/build/lib/unlock-helpers.js.map +1 -1
  139. package/build/lib/utils.d.ts +11 -0
  140. package/build/lib/utils.d.ts.map +1 -0
  141. package/build/lib/utils.js +23 -18
  142. package/build/lib/utils.js.map +1 -1
  143. package/build/lib/webview-helpers.d.ts +223 -0
  144. package/build/lib/webview-helpers.d.ts.map +1 -0
  145. package/build/lib/webview-helpers.js +476 -298
  146. package/build/lib/webview-helpers.js.map +1 -1
  147. package/index.js +3 -1
  148. package/lib/android-helpers.js +2 -1
  149. package/lib/stubs.ts +8 -0
  150. package/lib/unlock-helpers.js +2 -2
  151. package/package.json +23 -14
@@ -1,322 +1,346 @@
1
1
  "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
- Object.defineProperty(exports, "__esModule", {
5
- value: true
6
- });
7
- exports.helpers = exports.default = exports.commands = void 0;
8
- require("source-map-support/register");
9
- var _lodash = _interopRequireDefault(require("lodash"));
10
- var _androidHelpers = _interopRequireDefault(require("../android-helpers"));
11
- var _bluebird = _interopRequireDefault(require("bluebird"));
12
- var _driver = require("appium/driver");
13
- var _asyncbox = require("asyncbox");
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
- return _support.util.hasValue(val) ? val : 0.5;
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
- let duration = 0.8;
25
- if (typeof waitGesture.options.ms !== 'undefined' && waitGesture.options.ms) {
26
- duration = waitGesture.options.ms / 1000;
27
- if (duration === 0) {
28
- duration = 0.1;
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
- const {
35
- element,
36
- x,
37
- y,
38
- count,
39
- ms,
40
- duration
41
- } = opts;
42
- switch (action) {
43
- case 'tap':
44
- return await this.tap(null, x, y, count);
45
- case 'press':
46
- return await this.touchDown(null, x, y);
47
- case 'release':
48
- return await this.touchUp(element, x, y);
49
- case 'moveTo':
50
- return await this.touchMove(null, x, y);
51
- case 'wait':
52
- return await _bluebird.default.delay(ms);
53
- case 'longPress':
54
- return await this.touchLongClick(null, x, y, duration || 1000);
55
- case 'cancel':
56
- this.log.warn('Cancel action currently has no effect');
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
- let longPress = gestures[0];
64
- let moveTo = gestures[1];
65
- let startX = longPress.options.x || 0,
66
- startY = longPress.options.y || 0,
67
- endX = moveTo.options.x || 0,
68
- endY = moveTo.options.y || 0;
69
- if (longPress.options.element) {
70
- let {
71
- x,
72
- y
73
- } = await this.getLocationInView(longPress.options.element);
74
- startX += x || 0;
75
- startY += y || 0;
76
- }
77
- if (moveTo.options.element) {
78
- let {
79
- x,
80
- y
81
- } = await this.getLocationInView(moveTo.options.element);
82
- endX += x || 0;
83
- endY += y || 0;
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
- let release = _lodash.default.last(gestures);
94
- release.options = release.options || {};
95
- if (release.options.element || release.options.x && release.options.y) {
96
- return;
97
- }
98
- gestures = _lodash.default.clone(gestures);
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
- if (ref) {
108
- let opts = ref.options;
109
- if (opts.element) {
110
- let loc = await this.getLocationInView(opts.element);
111
- if (opts.x && opts.y) {
112
- release.options = {
113
- x: loc.x + opts.x,
114
- y: loc.y + opts.y
115
- };
116
- } else {
117
- let size = await this.getSize(opts.element);
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
- return release;
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
- try {
131
- return await this.doTouchAction(gesture.action, gesture.options || {});
132
- } catch (e) {
133
- if ((0, _driver.isErrorType)(e, _driver.errors.NoSuchElementError) && gesture.action === 'release' && gesture.options.element) {
134
- delete gesture.options.element;
135
- this.log.debug(`retrying release without element opts: ${gesture.options}.`);
136
- return await this.doTouchAction(gesture.action, gesture.options || {});
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
- let startX = getCoordDefault(gestures[0].options.x),
143
- startY = getCoordDefault(gestures[0].options.y),
144
- endX = getCoordDefault(gestures[2].options.x),
145
- endY = getCoordDefault(gestures[2].options.y),
146
- duration = getSwipeTouchDuration(gestures[1]),
147
- element = gestures[0].options.element,
148
- destElement = gestures[2].options.element || gestures[0].options.element;
149
- if (_support.util.hasValue(destElement)) {
150
- let locResult = await this.getLocationInView(destElement);
151
- let sizeResult = await this.getSize(destElement);
152
- let offsetX = Math.abs(endX) < 1 && Math.abs(endX) > 0 ? sizeResult.width * endX : endX;
153
- let offsetY = Math.abs(endY) < 1 && Math.abs(endY) > 0 ? sizeResult.height * endY : endY;
154
- endX = locResult.x + offsetX;
155
- endY = locResult.y + offsetY;
156
- if (_support.util.hasValue(element)) {
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
- return {
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
- if (gestures.length === 4 && gestures[0].action === 'press' && gestures[1].action === 'wait' && gestures[2].action === 'moveTo' && gestures[3].action === 'release') {
174
- let swipeOpts = await this.getSwipeOptions(gestures);
175
- return await this.swipe(swipeOpts.startX, swipeOpts.startY, swipeOpts.endX, swipeOpts.endY, swipeOpts.duration, swipeOpts.touchCount, swipeOpts.element);
176
- }
177
- let actions = _lodash.default.map(gestures, 'action');
178
- if (actions[0] === 'longPress' && actions[1] === 'moveTo' && actions[2] === 'release') {
179
- return await this.doTouchDrag(gestures);
180
- } else {
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 fixedGestures = await this.parseTouch(gestures, false);
206
- if (actions[actions.length - 1] === 'release') {
207
- actions[actions.length - 1] = await this.fixRelease(gestures);
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
- for (let g of fixedGestures) {
210
- await this.performGesture(g);
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
- if (multi && _lodash.default.last(gestures).action === 'release') {
216
- gestures.pop();
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
- if (multi) {
282
- let timeOffset = state.timeOffset;
283
- time += timeOffset;
284
- state.time = _androidHelpers.default.truncateDecimals(time, 3);
285
- if (!_lodash.default.isUndefined(state.options.x) && !_lodash.default.isUndefined(state.options.y)) {
286
- state.touch = {
287
- x: state.options.x,
288
- y: state.options.y
289
- };
290
- }
291
- delete state.options;
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
- delete state.timeOffset;
294
- }
295
- return touchStateObjects;
311
+ return touchStateObjects;
296
312
  };
297
313
  commands.performMultiAction = async function performMultiAction(actions, elementId) {
298
- if (actions.length === 1) {
299
- throw new Error('Multi Pointer Gestures need at least two actions. ' + 'Use Touch Actions for a single action.');
300
- }
301
- const states = await (0, _asyncbox.asyncmap)(actions, async action => await this.parseTouch(action, true), false);
302
- return await this.doPerformMultiAction(elementId, states);
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
- let opts;
306
- if (elementId) {
307
- opts = {
308
- elementId,
309
- actions: states
310
- };
311
- return await this.bootstrap.sendAction('element:performMultiPointerGesture', opts);
312
- } else {
313
- opts = {
314
- actions: states
315
- };
316
- return await this.bootstrap.sendAction('performMultiPointerGesture', opts);
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
- var _default = extensions;
321
- exports.default = _default;
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