@midscene/android 1.8.0 → 1.8.1

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/dist/lib/cli.js CHANGED
@@ -699,103 +699,30 @@ var __webpack_exports__ = {};
699
699
  }
700
700
  class AndroidDevice {
701
701
  actionSpace() {
702
- const defaultActions = [
703
- (0, device_namespaceObject.defineActionTap)(async (param)=>{
704
- const element = param.locate;
705
- external_node_assert_default()(element, 'Element not found, cannot tap');
706
- await this.mouseClick(element.center[0], element.center[1]);
707
- }),
708
- (0, device_namespaceObject.defineActionDoubleClick)(async (param)=>{
709
- const element = param.locate;
710
- external_node_assert_default()(element, 'Element not found, cannot double click');
711
- await this.mouseDoubleClick(element.center[0], element.center[1]);
712
- }),
713
- (0, device_namespaceObject.defineAction)({
714
- name: 'Input',
715
- description: 'Input text into the input field',
716
- interfaceAlias: 'aiInput',
717
- paramSchema: core_namespaceObject.z.object({
718
- value: core_namespaceObject.z.string().describe('The text to input. Provide the final content for replace/append modes, or an empty string when using clear mode to remove existing text.'),
719
- autoDismissKeyboard: core_namespaceObject.z.boolean().optional().describe('If true, the keyboard will be dismissed after the input is completed. Do not set it unless the user asks you to do so.'),
720
- mode: core_namespaceObject.z.preprocess((val)=>'append' === val ? 'typeOnly' : val, core_namespaceObject.z["enum"]([
721
- 'replace',
722
- 'clear',
723
- 'typeOnly'
724
- ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - clear the field without inputting new text.')),
725
- locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The input field to be filled').optional()
726
- }),
727
- sample: {
728
- value: 'test@example.com',
729
- locate: {
730
- prompt: 'the email input field'
731
- }
702
+ const mobileActionContext = {
703
+ input: this.inputPrimitives,
704
+ size: ()=>this.size(),
705
+ sleep: async (timeMs)=>{
706
+ await (0, core_utils_namespaceObject.sleep)(timeMs);
707
+ },
708
+ getDefaultAutoDismissKeyboard: ()=>this.options?.autoDismissKeyboard,
709
+ systemActions: {
710
+ backButton: {
711
+ name: 'AndroidBackButton',
712
+ description: 'Trigger the system "back" operation on Android devices'
732
713
  },
733
- call: async (param)=>{
734
- const element = param.locate;
735
- if ('typeOnly' !== param.mode) await this.clearInput(element);
736
- if ('clear' === param.mode) return;
737
- if (!param || !param.value) return;
738
- const autoDismissKeyboard = param.autoDismissKeyboard ?? this.options?.autoDismissKeyboard;
739
- await this.keyboardType(param.value, {
740
- autoDismissKeyboard
741
- });
742
- }
743
- }),
744
- (0, device_namespaceObject.defineActionScroll)(async (param)=>{
745
- const element = param.locate;
746
- const startingPoint = element ? {
747
- left: element.center[0],
748
- top: element.center[1]
749
- } : void 0;
750
- const scrollToEventName = param?.scrollType;
751
- if ('scrollToTop' === scrollToEventName) await this.scrollUntilTop(startingPoint);
752
- else if ('scrollToBottom' === scrollToEventName) await this.scrollUntilBottom(startingPoint);
753
- else if ('scrollToRight' === scrollToEventName) await this.scrollUntilRight(startingPoint);
754
- else if ('scrollToLeft' === scrollToEventName) await this.scrollUntilLeft(startingPoint);
755
- else if ('singleAction' !== scrollToEventName && scrollToEventName) throw new Error(`Unknown scroll event type: ${scrollToEventName}, param: ${JSON.stringify(param)}`);
756
- else {
757
- if (param?.direction !== 'down' && param && param.direction) if ('up' === param.direction) await this.scrollUp(param.distance || void 0, startingPoint);
758
- else if ('left' === param.direction) await this.scrollLeft(param.distance || void 0, startingPoint);
759
- else if ('right' === param.direction) await this.scrollRight(param.distance || void 0, startingPoint);
760
- else throw new Error(`Unknown scroll direction: ${param.direction}`);
761
- else await this.scrollDown(param?.distance || void 0, startingPoint);
762
- await (0, core_utils_namespaceObject.sleep)(500);
763
- }
764
- }),
765
- (0, device_namespaceObject.defineActionDragAndDrop)(async (param)=>{
766
- const from = param.from;
767
- const to = param.to;
768
- external_node_assert_default()(from, 'missing "from" param for drag and drop');
769
- external_node_assert_default()(to, 'missing "to" param for drag and drop');
770
- await this.mouseDrag({
771
- x: from.center[0],
772
- y: from.center[1]
773
- }, {
774
- x: to.center[0],
775
- y: to.center[1]
776
- });
777
- }),
778
- (0, device_namespaceObject.defineActionSwipe)(async (param)=>{
779
- const { startPoint, endPoint, duration, repeatCount } = (0, device_namespaceObject.normalizeMobileSwipeParam)(param, await this.size());
780
- for(let i = 0; i < repeatCount; i++)await this.mouseDrag(startPoint, endPoint, duration);
781
- }),
782
- (0, device_namespaceObject.defineActionKeyboardPress)(async (param)=>{
783
- await this.keyboardPress(param.keyName);
784
- }),
785
- (0, device_namespaceObject.defineActionCursorMove)(async (param)=>{
786
- const arrowKey = 'left' === param.direction ? 'ArrowLeft' : 'ArrowRight';
787
- const times = param.times ?? 1;
788
- for(let i = 0; i < times; i++){
789
- await this.keyboardPress(arrowKey);
790
- await (0, core_utils_namespaceObject.sleep)(100);
714
+ homeButton: {
715
+ name: 'AndroidHomeButton',
716
+ description: 'Trigger the system "home" operation on Android devices'
717
+ },
718
+ recentAppsButton: {
719
+ name: 'AndroidRecentAppsButton',
720
+ description: 'Trigger the system "recent apps" operation on Android devices'
791
721
  }
792
- }),
793
- (0, device_namespaceObject.defineActionLongPress)(async (param)=>{
794
- const element = param.locate;
795
- if (!element) throw new Error('LongPress requires an element to be located');
796
- const [x, y] = element.center;
797
- await this.longPress(x, y, param?.duration);
798
- }),
722
+ }
723
+ };
724
+ const defaultActions = [
725
+ ...(0, device_namespaceObject.createDefaultMobileActions)(mobileActionContext),
799
726
  (0, device_namespaceObject.defineAction)({
800
727
  name: 'PullGesture',
801
728
  description: 'Trigger pull down to refresh or pull up actions',
@@ -825,19 +752,6 @@ var __webpack_exports__ = {};
825
752
  else if ('up' === param.direction) await this.pullUp(startPoint, param.distance, param.duration);
826
753
  else throw new Error(`Unknown pull direction: ${param.direction}`);
827
754
  }
828
- }),
829
- (0, device_namespaceObject.defineActionPinch)(async (param)=>{
830
- const { centerX, centerY, startDistance, endDistance, duration } = (0, device_namespaceObject.normalizePinchParam)(param, await this.size());
831
- const { x: adjCenterX, y: adjCenterY } = await this.adjustCoordinates(centerX, centerY);
832
- const ratio = 0 !== adjCenterX && 0 !== centerX ? adjCenterX / centerX : 1;
833
- const adjStartDist = Math.round(startDistance * ratio);
834
- const adjEndDist = Math.round(endDistance * ratio);
835
- await this.ensureYadb();
836
- const adb = await this.getAdb();
837
- await adb.shell(`app_process${this.getDisplayArg()} -Djava.class.path=/data/local/tmp/yadb /data/local/tmp com.ysbing.yadb.Main -pinch ${adjCenterX} ${adjCenterY} ${adjStartDist} ${adjEndDist} ${duration}`);
838
- }),
839
- (0, device_namespaceObject.defineActionClearInput)(async (param)=>{
840
- await this.clearInput(param.locate);
841
755
  })
842
756
  ];
843
757
  const platformSpecificActions = Object.values(createPlatformActions(this));
@@ -848,6 +762,27 @@ var __webpack_exports__ = {};
848
762
  ...customActions
849
763
  ];
850
764
  }
765
+ async performActionScroll(param) {
766
+ const element = param.locate;
767
+ const startingPoint = element ? {
768
+ left: element.center[0],
769
+ top: element.center[1]
770
+ } : void 0;
771
+ const scrollToEventName = param?.scrollType;
772
+ if ('scrollToTop' === scrollToEventName) await this.scrollUntilTop(startingPoint);
773
+ else if ('scrollToBottom' === scrollToEventName) await this.scrollUntilBottom(startingPoint);
774
+ else if ('scrollToRight' === scrollToEventName) await this.scrollUntilRight(startingPoint);
775
+ else if ('scrollToLeft' === scrollToEventName) await this.scrollUntilLeft(startingPoint);
776
+ else if ('singleAction' !== scrollToEventName && scrollToEventName) throw new Error(`Unknown scroll event type: ${scrollToEventName}, param: ${JSON.stringify(param)}`);
777
+ else {
778
+ if (param?.direction !== 'down' && param && param.direction) if ('up' === param.direction) await this.scrollUp(param.distance || void 0, startingPoint);
779
+ else if ('left' === param.direction) await this.scrollLeft(param.distance || void 0, startingPoint);
780
+ else if ('right' === param.direction) await this.scrollRight(param.distance || void 0, startingPoint);
781
+ else throw new Error(`Unknown scroll direction: ${param.direction}`);
782
+ else await this.scrollDown(param?.distance || void 0, startingPoint);
783
+ await (0, core_utils_namespaceObject.sleep)(500);
784
+ }
785
+ }
851
786
  describe() {
852
787
  return this.description || `DeviceId: ${this.deviceId}`;
853
788
  }
@@ -1335,14 +1270,20 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1335
1270
  return result;
1336
1271
  }
1337
1272
  async clearInput(element) {
1338
- if (element) await this.mouseClick(element.center[0], element.center[1]);
1273
+ if (element) await this.tapPoint({
1274
+ x: element.center[0],
1275
+ y: element.center[1]
1276
+ });
1339
1277
  await this.ensureYadb();
1340
1278
  const adb = await this.getAdb();
1341
1279
  const IME_STRATEGY = (this.options?.imeStrategy || env_namespaceObject.globalConfigManager.getEnvConfigValue(env_namespaceObject.MIDSCENE_ANDROID_IME_STRATEGY)) ?? IME_STRATEGY_YADB_FOR_NON_ASCII;
1342
1280
  if (IME_STRATEGY === IME_STRATEGY_YADB_FOR_NON_ASCII) await adb.clearTextField(100);
1343
1281
  else await adb.shell(`app_process${this.getDisplayArg()} -Djava.class.path=/data/local/tmp/yadb /data/local/tmp com.ysbing.yadb.Main -keyboardClear`);
1344
1282
  if (await adb.isSoftKeyboardPresent()) return;
1345
- if (element) await this.mouseClick(element.center[0], element.center[1]);
1283
+ if (element) await this.tapPoint({
1284
+ x: element.center[0],
1285
+ y: element.center[1]
1286
+ });
1346
1287
  }
1347
1288
  async forceScreenshot(path) {
1348
1289
  await this.ensureYadb();
@@ -1363,7 +1304,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1363
1304
  x: start.x,
1364
1305
  y: Math.round(height)
1365
1306
  };
1366
- await (0, utils_namespaceObject.repeat)(defaultScrollUntilTimes, ()=>this.mouseDrag(start, end, defaultFastScrollDuration));
1307
+ await (0, utils_namespaceObject.repeat)(defaultScrollUntilTimes, ()=>this.dragPoint(start, end, defaultFastScrollDuration));
1367
1308
  await (0, core_utils_namespaceObject.sleep)(1000);
1368
1309
  return;
1369
1310
  }
@@ -1380,7 +1321,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1380
1321
  x: start.x,
1381
1322
  y: 0
1382
1323
  };
1383
- await (0, utils_namespaceObject.repeat)(defaultScrollUntilTimes, ()=>this.mouseDrag(start, end, defaultFastScrollDuration));
1324
+ await (0, utils_namespaceObject.repeat)(defaultScrollUntilTimes, ()=>this.dragPoint(start, end, defaultFastScrollDuration));
1384
1325
  await (0, core_utils_namespaceObject.sleep)(1000);
1385
1326
  return;
1386
1327
  }
@@ -1398,7 +1339,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1398
1339
  x: Math.round(width),
1399
1340
  y: start.y
1400
1341
  };
1401
- await (0, utils_namespaceObject.repeat)(defaultScrollUntilTimes, ()=>this.mouseDrag(start, end, defaultFastScrollDuration));
1342
+ await (0, utils_namespaceObject.repeat)(defaultScrollUntilTimes, ()=>this.dragPoint(start, end, defaultFastScrollDuration));
1402
1343
  await (0, core_utils_namespaceObject.sleep)(1000);
1403
1344
  return;
1404
1345
  }
@@ -1415,7 +1356,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1415
1356
  x: 0,
1416
1357
  y: start.y
1417
1358
  };
1418
- await (0, utils_namespaceObject.repeat)(defaultScrollUntilTimes, ()=>this.mouseDrag(start, end, defaultFastScrollDuration));
1359
+ await (0, utils_namespaceObject.repeat)(defaultScrollUntilTimes, ()=>this.dragPoint(start, end, defaultFastScrollDuration));
1419
1360
  await (0, core_utils_namespaceObject.sleep)(1000);
1420
1361
  return;
1421
1362
  }
@@ -1433,7 +1374,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1433
1374
  };
1434
1375
  const end = this.calculateScrollEndPoint(start, 0, scrollDistance, 0, height);
1435
1376
  if (hasExplicitDistance) this.warnScrollDistanceClamped('up', scrollDistance, Math.abs(end.y - start.y));
1436
- await this.mouseDrag(start, end);
1377
+ await this.dragPoint(start, end);
1437
1378
  return;
1438
1379
  }
1439
1380
  await this.scroll(0, -scrollDistance, void 0, hasExplicitDistance, 'up');
@@ -1449,7 +1390,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1449
1390
  };
1450
1391
  const end = this.calculateScrollEndPoint(start, 0, -scrollDistance, 0, height);
1451
1392
  if (hasExplicitDistance) this.warnScrollDistanceClamped('down', scrollDistance, Math.abs(end.y - start.y));
1452
- await this.mouseDrag(start, end);
1393
+ await this.dragPoint(start, end);
1453
1394
  return;
1454
1395
  }
1455
1396
  await this.scroll(0, scrollDistance, void 0, hasExplicitDistance, 'down');
@@ -1465,7 +1406,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1465
1406
  };
1466
1407
  const end = this.calculateScrollEndPoint(start, scrollDistance, 0, width, 0);
1467
1408
  if (hasExplicitDistance) this.warnScrollDistanceClamped('left', scrollDistance, Math.abs(end.x - start.x));
1468
- await this.mouseDrag(start, end);
1409
+ await this.dragPoint(start, end);
1469
1410
  return;
1470
1411
  }
1471
1412
  await this.scroll(-scrollDistance, 0, void 0, hasExplicitDistance, 'left');
@@ -1481,7 +1422,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1481
1422
  };
1482
1423
  const end = this.calculateScrollEndPoint(start, -scrollDistance, 0, width, 0);
1483
1424
  if (hasExplicitDistance) this.warnScrollDistanceClamped('right', scrollDistance, Math.abs(end.x - start.x));
1484
- await this.mouseDrag(start, end);
1425
+ await this.dragPoint(start, end);
1485
1426
  return;
1486
1427
  }
1487
1428
  await this.scroll(scrollDistance, 0, void 0, hasExplicitDistance, 'right');
@@ -1502,7 +1443,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1502
1443
  const hasBothQuotes = text.includes('"') && text.includes("'");
1503
1444
  return hasNonAscii || hasFormatSpecifiers || hasShellSpecialChars || hasBothQuotes;
1504
1445
  }
1505
- async keyboardType(text, options) {
1446
+ async typeText(text, options) {
1506
1447
  if (!text) return;
1507
1448
  const adb = await this.getAdb();
1508
1449
  const IME_STRATEGY = (this.options?.imeStrategy || env_namespaceObject.globalConfigManager.getEnvConfigValue(env_namespaceObject.MIDSCENE_ANDROID_IME_STRATEGY)) ?? IME_STRATEGY_YADB_FOR_NON_ASCII;
@@ -1539,7 +1480,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1539
1480
  const lowerKey = key.toLowerCase();
1540
1481
  return keyMap[lowerKey] || key;
1541
1482
  }
1542
- async keyboardPress(key) {
1483
+ async pressKey(key) {
1543
1484
  const keyCodeMap = {
1544
1485
  Enter: 66,
1545
1486
  Backspace: 67,
@@ -1561,14 +1502,14 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1561
1502
  if (asciiCode >= 65 && asciiCode <= 90) await adb.keyevent(asciiCode - 36);
1562
1503
  }
1563
1504
  }
1564
- async mouseClick(x, y) {
1505
+ async tapPoint(point) {
1565
1506
  const adb = await this.getAdb();
1566
- const { x: adjustedX, y: adjustedY } = await this.adjustCoordinates(x, y);
1507
+ const { x: adjustedX, y: adjustedY } = await this.adjustCoordinates(point.x, point.y);
1567
1508
  await adb.shell(`input${this.getDisplayArg()} swipe ${adjustedX} ${adjustedY} ${adjustedX} ${adjustedY} 150`);
1568
1509
  }
1569
- async mouseDoubleClick(x, y) {
1510
+ async doubleTapPoint(point) {
1570
1511
  const adb = await this.getAdb();
1571
- const { x: adjustedX, y: adjustedY } = await this.adjustCoordinates(x, y);
1512
+ const { x: adjustedX, y: adjustedY } = await this.adjustCoordinates(point.x, point.y);
1572
1513
  const tapCommand = `input${this.getDisplayArg()} tap ${adjustedX} ${adjustedY}`;
1573
1514
  await adb.shell(tapCommand);
1574
1515
  await (0, core_utils_namespaceObject.sleep)(50);
@@ -1577,12 +1518,14 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1577
1518
  async mouseMove() {
1578
1519
  return Promise.resolve();
1579
1520
  }
1580
- async mouseDrag(from, to, duration) {
1521
+ async dragPoint(from, to, duration) {
1522
+ await this.swipePoint(from, to, duration ?? defaultNormalScrollDuration);
1523
+ }
1524
+ async swipePoint(from, to, duration) {
1581
1525
  const adb = await this.getAdb();
1582
1526
  const { x: fromX, y: fromY } = await this.adjustCoordinates(from.x, from.y);
1583
1527
  const { x: toX, y: toY } = await this.adjustCoordinates(to.x, to.y);
1584
- const swipeDuration = duration ?? defaultNormalScrollDuration;
1585
- await adb.shell(`input${this.getDisplayArg()} swipe ${fromX} ${fromY} ${toX} ${toY} ${swipeDuration}`);
1528
+ await adb.shell(`input${this.getDisplayArg()} swipe ${fromX} ${fromY} ${toX} ${toY} ${duration}`);
1586
1529
  }
1587
1530
  async scroll(deltaX, deltaY, duration, warnOnClamp = false, direction) {
1588
1531
  if (0 === deltaX && 0 === deltaY) throw new Error('Scroll distance cannot be zero in both directions');
@@ -1605,11 +1548,14 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1605
1548
  }
1606
1549
  const endX = Math.round(startX - deltaX);
1607
1550
  const endY = Math.round(startY - deltaY);
1608
- const { x: adjustedStartX, y: adjustedStartY } = await this.adjustCoordinates(startX, startY);
1609
- const { x: adjustedEndX, y: adjustedEndY } = await this.adjustCoordinates(endX, endY);
1610
- const adb = await this.getAdb();
1611
1551
  const swipeDuration = duration ?? defaultNormalScrollDuration;
1612
- await adb.shell(`input${this.getDisplayArg()} swipe ${adjustedStartX} ${adjustedStartY} ${adjustedEndX} ${adjustedEndY} ${swipeDuration}`);
1552
+ await this.swipePoint({
1553
+ x: startX,
1554
+ y: startY
1555
+ }, {
1556
+ x: endX,
1557
+ y: endY
1558
+ }, swipeDuration);
1613
1559
  }
1614
1560
  async destroy() {
1615
1561
  if (this.destroyed) return;
@@ -1657,9 +1603,9 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1657
1603
  const adb = await this.getAdb();
1658
1604
  await adb.shell(`input${this.getDisplayArg()} keyevent 187`);
1659
1605
  }
1660
- async longPress(x, y, duration = 2000) {
1606
+ async longPressPoint(point, duration = 2000) {
1661
1607
  const adb = await this.getAdb();
1662
- const { x: adjustedX, y: adjustedY } = await this.adjustCoordinates(x, y);
1608
+ const { x: adjustedX, y: adjustedY } = await this.adjustCoordinates(point.x, point.y);
1663
1609
  await adb.shell(`input${this.getDisplayArg()} swipe ${adjustedX} ${adjustedY} ${adjustedX} ${adjustedY} ${duration}`);
1664
1610
  }
1665
1611
  async pullDown(startPoint, distance, duration = 800) {
@@ -1680,10 +1626,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1680
1626
  await (0, core_utils_namespaceObject.sleep)(200);
1681
1627
  }
1682
1628
  async pullDrag(from, to, duration) {
1683
- const adb = await this.getAdb();
1684
- const { x: fromX, y: fromY } = await this.adjustCoordinates(from.x, from.y);
1685
- const { x: toX, y: toY } = await this.adjustCoordinates(to.x, to.y);
1686
- await adb.shell(`input${this.getDisplayArg()} swipe ${fromX} ${fromY} ${toX} ${toY} ${duration}`);
1629
+ await this.swipePoint(from, to, duration);
1687
1630
  }
1688
1631
  async pullUp(startPoint, distance, duration = 600) {
1689
1632
  const { width, height } = await this.size();
@@ -1784,6 +1727,56 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1784
1727
  device_define_property(this, "interfaceType", 'android');
1785
1728
  device_define_property(this, "uri", void 0);
1786
1729
  device_define_property(this, "options", void 0);
1730
+ device_define_property(this, "inputPrimitives", {
1731
+ pointer: {
1732
+ tap: (point)=>this.tapPoint(point),
1733
+ doubleClick: (point)=>this.doubleTapPoint(point),
1734
+ longPress: (point, opts)=>this.longPressPoint(point, opts?.duration),
1735
+ dragAndDrop: (from, to)=>this.dragPoint(from, to)
1736
+ },
1737
+ keyboard: {
1738
+ keyboardPress: (keyName)=>this.pressKey(keyName),
1739
+ typeText: async (value, opts)=>{
1740
+ const target = opts?.target;
1741
+ if (target && opts?.replace !== false) await this.clearInput(target);
1742
+ else if (target) await this.tapPoint({
1743
+ x: target.center[0],
1744
+ y: target.center[1]
1745
+ });
1746
+ if (opts?.focusOnly) return;
1747
+ await this.typeText(value, opts);
1748
+ },
1749
+ clearInput: (target)=>this.clearInput(target),
1750
+ cursorMove: async (direction, times = 1)=>{
1751
+ const arrowKey = 'left' === direction ? 'ArrowLeft' : 'ArrowRight';
1752
+ for(let i = 0; i < times; i++)await this.pressKey(arrowKey);
1753
+ }
1754
+ },
1755
+ touch: {
1756
+ swipe: async (start, end, opts)=>{
1757
+ const duration = opts?.duration ?? 300;
1758
+ const repeatCount = opts?.repeat ?? 1;
1759
+ for(let i = 0; i < repeatCount; i++)await this.dragPoint(start, end, duration);
1760
+ },
1761
+ pinch: async (center, opts)=>{
1762
+ const { x: adjCenterX, y: adjCenterY } = await this.adjustCoordinates(Math.round(center.x), Math.round(center.y));
1763
+ const ratio = 0 !== adjCenterX && 0 !== center.x ? adjCenterX / center.x : 1;
1764
+ const adjStartDist = Math.round(opts.startDistance * ratio);
1765
+ const adjEndDist = Math.round(opts.endDistance * ratio);
1766
+ await this.ensureYadb();
1767
+ const adb = await this.getAdb();
1768
+ await adb.shell(`app_process${this.getDisplayArg()} -Djava.class.path=/data/local/tmp/yadb /data/local/tmp com.ysbing.yadb.Main -pinch ${adjCenterX} ${adjCenterY} ${adjStartDist} ${adjEndDist} ${opts.duration}`);
1769
+ }
1770
+ },
1771
+ scroll: {
1772
+ scroll: (param)=>this.performActionScroll(param)
1773
+ },
1774
+ system: {
1775
+ backButton: ()=>this.back(),
1776
+ homeButton: ()=>this.home(),
1777
+ recentAppsButton: ()=>this.recentApps()
1778
+ }
1779
+ });
1787
1780
  external_node_assert_default()(deviceId, 'deviceId is required for AndroidDevice');
1788
1781
  this.deviceId = deviceId;
1789
1782
  this.options = options;
@@ -1834,37 +1827,10 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1834
1827
  description: 'Terminate (force-stop) an Android app by package name',
1835
1828
  interfaceAlias: 'terminate',
1836
1829
  paramSchema: terminateParamSchema,
1837
- delayBeforeRunner: 0,
1838
- delayAfterRunner: 0,
1839
1830
  call: async (param)=>{
1840
1831
  if (!param.uri || '' === param.uri.trim()) throw new Error('Terminate requires a non-empty uri parameter');
1841
1832
  await device.terminate(param.uri);
1842
1833
  }
1843
- }),
1844
- AndroidBackButton: (0, device_namespaceObject.defineAction)({
1845
- name: 'AndroidBackButton',
1846
- description: 'Trigger the system "back" operation on Android devices',
1847
- delayBeforeRunner: 0,
1848
- delayAfterRunner: 0,
1849
- call: async ()=>{
1850
- await device.back();
1851
- }
1852
- }),
1853
- AndroidHomeButton: (0, device_namespaceObject.defineAction)({
1854
- name: 'AndroidHomeButton',
1855
- description: 'Trigger the system "home" operation on Android devices',
1856
- delayBeforeRunner: 0,
1857
- delayAfterRunner: 0,
1858
- call: async ()=>{
1859
- await device.home();
1860
- }
1861
- }),
1862
- AndroidRecentAppsButton: (0, device_namespaceObject.defineAction)({
1863
- name: 'AndroidRecentAppsButton',
1864
- description: 'Trigger the system "recent apps" operation on Android devices',
1865
- call: async ()=>{
1866
- await device.recentApps();
1867
- }
1868
1834
  })
1869
1835
  });
1870
1836
  const debugUtils = (0, logger_.getDebug)('android:utils');
@@ -2031,7 +1997,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
2031
1997
  const tools = new AndroidMidsceneTools();
2032
1998
  (0, cli_namespaceObject.runToolsCLI)(tools, 'midscene-android', {
2033
1999
  stripPrefix: 'android_',
2034
- version: "1.8.0",
2000
+ version: "1.8.1",
2035
2001
  extraCommands: (0, core_namespaceObject.createReportCliCommands)()
2036
2002
  }).catch((e)=>{
2037
2003
  process.exit((0, cli_namespaceObject.reportCLIError)(e));