@skrillex1224/android-toolkit 1.0.9 → 1.0.10

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/index.js CHANGED
@@ -253,7 +253,7 @@ function safeJson(value) {
253
253
 
254
254
  // src/device.js
255
255
  var execFileAsync = promisify(execFile);
256
- var Device = {
256
+ var Device2 = {
257
257
  adbExec,
258
258
  adbShell,
259
259
  forceStopApp,
@@ -634,7 +634,7 @@ function createApifyKit(options = {}) {
634
634
  if (failActor) {
635
635
  let base64 = "";
636
636
  try {
637
- base64 = await Device.screenshotBase64(ctx);
637
+ base64 = await Device2.screenshotBase64(ctx);
638
638
  } catch (error) {
639
639
  base64 = `\u622A\u56FE\u5931\u8D25: ${error?.message || String(error)}`;
640
640
  }
@@ -752,7 +752,7 @@ var DeviceView = {
752
752
  normalizeSelector
753
753
  };
754
754
  async function snapshot(ctx, options = {}) {
755
- const xml = options.xml || await Device.dumpUiXml(ctx);
755
+ const xml = options.xml || await Device2.dumpUiXml(ctx);
756
756
  const parsed = parser.parse(xml);
757
757
  const roots = toArray(parsed?.hierarchy?.node).map((node) => normalizeNode(node, null, 0));
758
758
  const flat = [];
@@ -936,6 +936,12 @@ function selectorLabel(selector) {
936
936
  }
937
937
 
938
938
  // src/device-input.js
939
+ var SCROLL_MAX_SWIPES = 24;
940
+ var SCROLL_STABLE_ROUNDS = 1;
941
+ var SCROLL_SWIPE_RATIO = 0.72;
942
+ var SCROLL_DURATION_MS = 360;
943
+ var SCROLL_SETTLE_MS = 500;
944
+ var SCROLL_HASH_SOURCE = "screenshot";
939
945
  var DeviceInput = {
940
946
  click,
941
947
  tap: click,
@@ -949,12 +955,12 @@ var DeviceInput = {
949
955
  };
950
956
  async function click(ctx, selectorOrPoint, options = {}) {
951
957
  if (isPoint(selectorOrPoint)) {
952
- await Device.tapAbsolute(ctx, selectorOrPoint.x, selectorOrPoint.y);
958
+ await Device2.tapAbsolute(ctx, selectorOrPoint.x, selectorOrPoint.y);
953
959
  return { point: selectorOrPoint };
954
960
  }
955
961
  if (isBounds(selectorOrPoint)) {
956
962
  const point2 = centerOf(selectorOrPoint);
957
- await Device.tapAbsolute(ctx, point2.x, point2.y);
963
+ await Device2.tapAbsolute(ctx, point2.x, point2.y);
958
964
  return { point: point2 };
959
965
  }
960
966
  const target = await DeviceView.find(ctx, selectorOrPoint, options);
@@ -973,7 +979,7 @@ async function click(ctx, selectorOrPoint, options = {}) {
973
979
  actual: simplifyNode(actual),
974
980
  point
975
981
  });
976
- await Device.tapAbsolute(ctx, point.x, point.y);
982
+ await Device2.tapAbsolute(ctx, point.x, point.y);
977
983
  await sleep(Number(options.settleMs || 250));
978
984
  return { target, actual, point };
979
985
  }
@@ -984,7 +990,7 @@ async function fill(ctx, selector, text2, options = {}) {
984
990
  settleMs: Number(options.focusSettleMs || 350)
985
991
  });
986
992
  try {
987
- await Device.typeText(ctx, value);
993
+ await Device2.typeText(ctx, value);
988
994
  } catch (error) {
989
995
  throw new CrawlerError({
990
996
  message: `automation_failed: View \u5199\u5165\u6587\u672C\u5931\u8D25 ${JSON.stringify(selector)}`,
@@ -1001,10 +1007,10 @@ async function fill(ctx, selector, text2, options = {}) {
1001
1007
  return { target: clicked.actual || clicked.target, chars: value.length };
1002
1008
  }
1003
1009
  async function press(ctx, key) {
1004
- await Device.pressKey(ctx, key);
1010
+ await Device2.pressKey(ctx, key);
1005
1011
  }
1006
1012
  async function pressEnter2(ctx) {
1007
- await Device.pressEnter(ctx);
1013
+ await Device2.pressEnter(ctx);
1008
1014
  }
1009
1015
  async function scroll(ctx, selector, direction, options = {}) {
1010
1016
  const node = await DeviceView.find(ctx, selector, options);
@@ -1012,8 +1018,8 @@ async function scroll(ctx, selector, direction, options = {}) {
1012
1018
  }
1013
1019
  async function scrollBounds(ctx, bounds2, direction, options = {}) {
1014
1020
  const box = bounds2;
1015
- const ratio = Number(options.swipeRatio || 0.72);
1016
- const durationMs = Number(options.durationMs || 360);
1021
+ const ratio = Number(options.swipeRatio || SCROLL_SWIPE_RATIO);
1022
+ const durationMs = Number(options.durationMs || SCROLL_DURATION_MS);
1017
1023
  const x = box.centerX;
1018
1024
  const distance = Math.max(40, box.height * ratio);
1019
1025
  const down = String(direction || "").toLowerCase() === "down";
@@ -1025,8 +1031,8 @@ async function scrollBounds(ctx, bounds2, direction, options = {}) {
1025
1031
  x,
1026
1032
  y: down ? Math.min(box.bottom - 10, from.y + distance) : Math.max(box.top + 10, from.y - distance)
1027
1033
  };
1028
- await Device.swipe(ctx, from, to, durationMs);
1029
- await sleep(Number(options.settleMs || 500));
1034
+ await Device2.swipe(ctx, from, to, durationMs);
1035
+ await sleep(Number(options.settleMs || SCROLL_SETTLE_MS));
1030
1036
  }
1031
1037
  async function scrollToEnd(ctx, selector, options = {}) {
1032
1038
  return scrollUntilStable(ctx, selector, "up", options);
@@ -1035,56 +1041,30 @@ async function scrollToTop(ctx, selector, options = {}) {
1035
1041
  return scrollUntilStable(ctx, selector, "down", options);
1036
1042
  }
1037
1043
  async function scrollUntilStable(ctx, selector, direction, options = {}) {
1038
- const maxSwipes = Math.max(1, Number(options.maxSwipes || 20));
1039
- const stableRoundsTarget = Math.max(1, Number(options.stableRounds || 2));
1040
- const hashSource = String(options.stability || options.hashSource || "view");
1041
- if (hashSource === "screenshot") {
1042
- return scrollUntilScreenshotStable(ctx, selector, direction, options, maxSwipes, stableRoundsTarget, hashSource);
1043
- }
1044
- let lastHash = "";
1045
- let stableRounds = 0;
1046
- for (let index = 0; index < maxSwipes; index += 1) {
1047
- const currentHash = await scrollStateHash(ctx, selector, options, hashSource);
1048
- if (currentHash === lastHash) {
1049
- stableRounds += 1;
1050
- if (stableRounds >= stableRoundsTarget) {
1051
- return { swipes: index, stableRounds, hash: currentHash, hashSource, capped: false };
1052
- }
1053
- } else {
1054
- stableRounds = 0;
1055
- lastHash = currentHash;
1056
- }
1057
- await scroll(ctx, selector, direction, options);
1058
- }
1059
- return { swipes: maxSwipes, stableRounds, hash: lastHash, hashSource, capped: true };
1060
- }
1061
- async function scrollUntilScreenshotStable(ctx, selector, direction, options, maxSwipes, stableRoundsTarget, hashSource) {
1044
+ const maxSwipes = Math.max(1, Number(options.maxSwipes || SCROLL_MAX_SWIPES));
1045
+ const stableRoundsTarget = Math.max(1, Number(options.stableRounds || SCROLL_STABLE_ROUNDS));
1062
1046
  const node = await DeviceView.find(ctx, selector, options);
1063
1047
  const bounds2 = node.bounds;
1064
- let lastHash = await scrollStateHash(ctx, selector, options, hashSource);
1048
+ let lastHash = await scrollStateHash(ctx);
1065
1049
  let stableRounds = 0;
1066
1050
  for (let index = 0; index < maxSwipes; index += 1) {
1067
1051
  await scrollBounds(ctx, bounds2, direction, options);
1068
- const currentHash = await scrollStateHash(ctx, selector, options, hashSource);
1052
+ const currentHash = await scrollStateHash(ctx);
1069
1053
  if (currentHash === lastHash) {
1070
1054
  stableRounds += 1;
1071
1055
  if (stableRounds >= stableRoundsTarget) {
1072
- return { swipes: index + 1, stableRounds, hash: currentHash, hashSource, capped: false };
1056
+ return { swipes: index + 1, stableRounds, hash: currentHash, hashSource: SCROLL_HASH_SOURCE, capped: false };
1073
1057
  }
1074
1058
  } else {
1075
1059
  stableRounds = 0;
1076
1060
  lastHash = currentHash;
1077
1061
  }
1078
1062
  }
1079
- return { swipes: maxSwipes, stableRounds, hash: lastHash, hashSource, capped: true };
1063
+ return { swipes: maxSwipes, stableRounds, hash: lastHash, hashSource: SCROLL_HASH_SOURCE, capped: true };
1080
1064
  }
1081
- async function scrollStateHash(ctx, selector, options, hashSource) {
1082
- if (hashSource === "screenshot") {
1083
- const png = await Device.screenshotPng(ctx);
1084
- return createHash2("sha256").update(png).digest("hex");
1085
- }
1086
- const node = await DeviceView.find(ctx, selector, options);
1087
- return DeviceView.hashNode(node);
1065
+ async function scrollStateHash(ctx) {
1066
+ const png = await Device2.screenshotPng(ctx);
1067
+ return createHash2("sha256").update(png).digest("hex");
1088
1068
  }
1089
1069
  function nearestClickable(node) {
1090
1070
  let current = node;
@@ -1251,7 +1231,7 @@ async function pullDatabaseSnapshot(ctx, dbPath, localDir) {
1251
1231
  }
1252
1232
  }
1253
1233
  async function adbSuShell(ctx, command, options = {}) {
1254
- return Device.adbShell(ctx, [`su -c ${shellQuote(command)}`], options);
1234
+ return Device2.adbShell(ctx, [`su -c ${shellQuote(command)}`], options);
1255
1235
  }
1256
1236
  async function queryLocalSQLite(dbPath, config) {
1257
1237
  const payloadPath = `${dbPath}.query.json`;
@@ -1688,6 +1668,11 @@ var DEFAULT_COLUMNS = 3;
1688
1668
  var DEFAULT_SETTLE_MS = 550;
1689
1669
  var DEFAULT_TIMEOUT_MS = 5e4;
1690
1670
  var DEFAULT_POLL_INTERVAL_MS = 800;
1671
+ var RESET_TO_TOP_MAX_SWIPES = 16;
1672
+ var RESET_TO_TOP_STABLE_ROUNDS = 1;
1673
+ var CAPTURE_SCROLL_STEP_RATIO = 0.56;
1674
+ var CAPTURE_SCROLL_DURATION_MS = 360;
1675
+ var SPRITE_GAP = 16;
1691
1676
  var Share = {
1692
1677
  captureScreen,
1693
1678
  captureLink
@@ -1697,15 +1682,13 @@ async function captureScreen(ctx, options = {}) {
1697
1682
  const frameBuffers = [];
1698
1683
  const seen = /* @__PURE__ */ new Set();
1699
1684
  const targetSelector = options.selector || { id: "message_list" };
1700
- const shouldHideKeyboard = options.hideKeyboard !== false;
1701
- if (shouldHideKeyboard) await Device.hideKeyboard(ctx, { attempts: 2, settleMs: 350 }).catch(() => {
1702
- });
1703
- try {
1704
- const topResult = await DeviceInput.scrollToTop(ctx, targetSelector, {
1705
- maxSwipes: Number(options.scrollToTopMaxSwipes || 12),
1706
- stableRounds: Number(options.scrollToTopStableRounds || 2),
1707
- settleMs: 400,
1708
- stability: options.scrollStability || options.stability || "view"
1685
+ const resetToTop = options.resetToTop !== false;
1686
+ let topResult = null;
1687
+ if (resetToTop) {
1688
+ topResult = await DeviceInput.scrollToTop(ctx, targetSelector, {
1689
+ maxSwipes: RESET_TO_TOP_MAX_SWIPES,
1690
+ stableRounds: RESET_TO_TOP_STABLE_ROUNDS,
1691
+ settleMs: 400
1709
1692
  });
1710
1693
  Logger.info("captureScreen scrollToTop", {
1711
1694
  swipes: topResult?.swipes,
@@ -1713,13 +1696,20 @@ async function captureScreen(ctx, options = {}) {
1713
1696
  hashSource: topResult?.hashSource,
1714
1697
  capped: topResult?.capped === true
1715
1698
  });
1716
- } catch (error) {
1717
- if (options.strictScrollToTop === true) throw error;
1718
- Logger.warn("captureScreen scrollToTop skipped", { message: error?.message || String(error) });
1699
+ if (topResult?.capped === true) {
1700
+ throw new CrawlerError({
1701
+ message: `source_extraction_failed: \u622A\u56FE\u524D\u672A\u80FD\u786E\u8BA4\u56DE\u5230\u9876\u90E8 swipes=${topResult.swipes} stableRounds=${topResult.stableRounds}`,
1702
+ code: Code.SourceExtractionFailed,
1703
+ context: {
1704
+ selector: targetSelector,
1705
+ swipes: topResult.swipes,
1706
+ stableRounds: topResult.stableRounds,
1707
+ hashSource: topResult.hashSource
1708
+ }
1709
+ });
1710
+ }
1719
1711
  }
1720
1712
  for (let index = 0; index < DEFAULT_CAPTURE_COUNT; index += 1) {
1721
- if (shouldHideKeyboard) await Device.hideKeyboard(ctx, { attempts: 1, settleMs: 250 }).catch(() => {
1722
- });
1723
1713
  await sleep(DEFAULT_SETTLE_MS);
1724
1714
  const png = await Device.screenshotPng(ctx);
1725
1715
  const hash = createHash3("sha256").update(png).digest("hex");
@@ -1728,18 +1718,21 @@ async function captureScreen(ctx, options = {}) {
1728
1718
  frameBuffers.push(png);
1729
1719
  if (index >= DEFAULT_CAPTURE_COUNT - 1) break;
1730
1720
  await DeviceInput.scroll(ctx, targetSelector, "up", {
1731
- swipeRatio: 0.72,
1732
- durationMs: 360,
1721
+ swipeRatio: CAPTURE_SCROLL_STEP_RATIO,
1722
+ durationMs: CAPTURE_SCROLL_DURATION_MS,
1733
1723
  settleMs: DEFAULT_SETTLE_MS
1734
1724
  }).catch(() => {
1735
1725
  });
1736
1726
  }
1737
- const sprite = await composeSprite(frameBuffers, { columns: DEFAULT_COLUMNS, gap: 16 });
1727
+ const sprite = await composeSprite(frameBuffers, { columns: DEFAULT_COLUMNS, gap: SPRITE_GAP });
1738
1728
  const compression = resolveImageCompression(options);
1739
1729
  const base64 = await compressImageBufferToBase64(sprite, compression);
1740
1730
  Logger.success("Share.captureScreen", {
1741
1731
  duration: Logger.duration(startedAt),
1742
1732
  frameCount: frameBuffers.length,
1733
+ scrollStepRatio: CAPTURE_SCROLL_STEP_RATIO,
1734
+ resetToTop,
1735
+ topCapped: topResult?.capped === true,
1743
1736
  base64Bytes: Math.ceil(base64.length)
1744
1737
  });
1745
1738
  return `data:image/jpeg;base64,${base64}`;
@@ -1754,7 +1747,6 @@ async function captureLink(ctx, options = {}) {
1754
1747
  });
1755
1748
  }
1756
1749
  const timeoutMs = Number(options.timeoutMs || DEFAULT_TIMEOUT_MS);
1757
- const pollIntervalMs = Number(options.pollIntervalMs || DEFAULT_POLL_INTERVAL_MS);
1758
1750
  const deadline = Date.now() + timeoutMs;
1759
1751
  const prefix = String(share.prefix || "").trim();
1760
1752
  Logger.start("Share.captureLink", { actor: actorInfo.key, prefix, timeoutMs });
@@ -1776,7 +1768,7 @@ async function captureLink(ctx, options = {}) {
1776
1768
  if (link && link === beforeLink) {
1777
1769
  lastEvent = { ...event, rejected: "same_as_baseline", beforeLink };
1778
1770
  }
1779
- await sleep(pollIntervalMs);
1771
+ await sleep(DEFAULT_POLL_INTERVAL_MS);
1780
1772
  }
1781
1773
  throw new CrawlerError({
1782
1774
  message: "source_extraction_failed: \u672A\u6355\u83B7\u5206\u4EAB\u94FE\u63A5",
@@ -1872,7 +1864,7 @@ async function run(handler, options = {}) {
1872
1864
  const kit = {
1873
1865
  Launch,
1874
1866
  ApifyKit: apifyKit,
1875
- Device,
1867
+ Device: Device2,
1876
1868
  DeviceInput,
1877
1869
  DeviceView,
1878
1870
  DeviceSQLite,
@@ -1923,7 +1915,7 @@ var useAndroidToolKit = () => {
1923
1915
  DeviceInput,
1924
1916
  DeviceView,
1925
1917
  DeviceSQLite,
1926
- Device,
1918
+ Device: Device2,
1927
1919
  Mutation,
1928
1920
  Share,
1929
1921
  Constants: constants_exports,