@skrillex1224/android-toolkit 1.0.7 → 1.0.9

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
@@ -28,7 +28,7 @@ var Code = Object.freeze({
28
28
  ContentUnavailable: 30010003,
29
29
  SourceExtractionFailed: 30010004,
30
30
  AutomationFailed: 30010005,
31
- DataAccessUnavailable: 30010008,
31
+ AppRuntimeUnavailable: 30010008,
32
32
  AppNotInstalled: 30010009
33
33
  });
34
34
  var Status = Object.freeze({
@@ -1008,7 +1008,10 @@ async function pressEnter2(ctx) {
1008
1008
  }
1009
1009
  async function scroll(ctx, selector, direction, options = {}) {
1010
1010
  const node = await DeviceView.find(ctx, selector, options);
1011
- const box = node.bounds;
1011
+ await scrollBounds(ctx, node.bounds, direction, options);
1012
+ }
1013
+ async function scrollBounds(ctx, bounds2, direction, options = {}) {
1014
+ const box = bounds2;
1012
1015
  const ratio = Number(options.swipeRatio || 0.72);
1013
1016
  const durationMs = Number(options.durationMs || 360);
1014
1017
  const x = box.centerX;
@@ -1035,6 +1038,9 @@ async function scrollUntilStable(ctx, selector, direction, options = {}) {
1035
1038
  const maxSwipes = Math.max(1, Number(options.maxSwipes || 20));
1036
1039
  const stableRoundsTarget = Math.max(1, Number(options.stableRounds || 2));
1037
1040
  const hashSource = String(options.stability || options.hashSource || "view");
1041
+ if (hashSource === "screenshot") {
1042
+ return scrollUntilScreenshotStable(ctx, selector, direction, options, maxSwipes, stableRoundsTarget, hashSource);
1043
+ }
1038
1044
  let lastHash = "";
1039
1045
  let stableRounds = 0;
1040
1046
  for (let index = 0; index < maxSwipes; index += 1) {
@@ -1042,7 +1048,7 @@ async function scrollUntilStable(ctx, selector, direction, options = {}) {
1042
1048
  if (currentHash === lastHash) {
1043
1049
  stableRounds += 1;
1044
1050
  if (stableRounds >= stableRoundsTarget) {
1045
- return { swipes: index, stableRounds, hash: currentHash, hashSource };
1051
+ return { swipes: index, stableRounds, hash: currentHash, hashSource, capped: false };
1046
1052
  }
1047
1053
  } else {
1048
1054
  stableRounds = 0;
@@ -1050,7 +1056,27 @@ async function scrollUntilStable(ctx, selector, direction, options = {}) {
1050
1056
  }
1051
1057
  await scroll(ctx, selector, direction, options);
1052
1058
  }
1053
- return { swipes: maxSwipes, stableRounds, hash: lastHash, hashSource };
1059
+ return { swipes: maxSwipes, stableRounds, hash: lastHash, hashSource, capped: true };
1060
+ }
1061
+ async function scrollUntilScreenshotStable(ctx, selector, direction, options, maxSwipes, stableRoundsTarget, hashSource) {
1062
+ const node = await DeviceView.find(ctx, selector, options);
1063
+ const bounds2 = node.bounds;
1064
+ let lastHash = await scrollStateHash(ctx, selector, options, hashSource);
1065
+ let stableRounds = 0;
1066
+ for (let index = 0; index < maxSwipes; index += 1) {
1067
+ await scrollBounds(ctx, bounds2, direction, options);
1068
+ const currentHash = await scrollStateHash(ctx, selector, options, hashSource);
1069
+ if (currentHash === lastHash) {
1070
+ stableRounds += 1;
1071
+ if (stableRounds >= stableRoundsTarget) {
1072
+ return { swipes: index + 1, stableRounds, hash: currentHash, hashSource, capped: false };
1073
+ }
1074
+ } else {
1075
+ stableRounds = 0;
1076
+ lastHash = currentHash;
1077
+ }
1078
+ }
1079
+ return { swipes: maxSwipes, stableRounds, hash: lastHash, hashSource, capped: true };
1054
1080
  }
1055
1081
  async function scrollStateHash(ctx, selector, options, hashSource) {
1056
1082
  if (hashSource === "screenshot") {
@@ -1135,8 +1161,8 @@ async function query(ctx, options = {}) {
1135
1161
  const dbPaths = await resolveDeviceDbPaths(ctx, config);
1136
1162
  if (dbPaths.length === 0) {
1137
1163
  throw new CrawlerError({
1138
- message: "data_access_unavailable: sqlite database not found",
1139
- code: Code.DataAccessUnavailable,
1164
+ message: "app_runtime_unavailable: sqlite database not found",
1165
+ code: Code.AppRuntimeUnavailable,
1140
1166
  context: { dbDir: config.dbDir, dbPath: config.dbPath, dbNamePrefix: config.dbNamePrefix }
1141
1167
  });
1142
1168
  }
@@ -1185,8 +1211,8 @@ async function resolveDeviceDbPaths(ctx, config) {
1185
1211
  maxBuffer: 2 * 1024 * 1024
1186
1212
  }).catch((error) => {
1187
1213
  throw new CrawlerError({
1188
- message: `data_access_unavailable: sqlite dbDir unavailable ${error?.message || String(error)}`,
1189
- code: Code.DataAccessUnavailable,
1214
+ message: `app_runtime_unavailable: sqlite dbDir unavailable ${error?.message || String(error)}`,
1215
+ code: Code.AppRuntimeUnavailable,
1190
1216
  context: { dbDir: config.dbDir }
1191
1217
  });
1192
1218
  });
@@ -1211,8 +1237,8 @@ async function pullDatabaseSnapshot(ctx, dbPath, localDir) {
1211
1237
  await adbSuShell(ctx, copyCommand, { timeoutMs: 3e4, maxBuffer: 4 * 1024 * 1024 });
1212
1238
  await adbPull(adbPath, serial, remoteDb, localDb).catch((error) => {
1213
1239
  throw new CrawlerError({
1214
- message: `data_access_unavailable: sqlite snapshot pull failed ${error?.message || String(error)}`,
1215
- code: Code.DataAccessUnavailable,
1240
+ message: `app_runtime_unavailable: sqlite snapshot pull failed ${error?.message || String(error)}`,
1241
+ code: Code.AppRuntimeUnavailable,
1216
1242
  context: { dbPath }
1217
1243
  });
1218
1244
  });
@@ -1671,17 +1697,28 @@ async function captureScreen(ctx, options = {}) {
1671
1697
  const frameBuffers = [];
1672
1698
  const seen = /* @__PURE__ */ new Set();
1673
1699
  const targetSelector = options.selector || { id: "message_list" };
1674
- await Device.hideKeyboard(ctx, { attempts: 2, settleMs: 350 }).catch(() => {
1700
+ const shouldHideKeyboard = options.hideKeyboard !== false;
1701
+ if (shouldHideKeyboard) await Device.hideKeyboard(ctx, { attempts: 2, settleMs: 350 }).catch(() => {
1675
1702
  });
1676
- await DeviceInput.scrollToTop(ctx, targetSelector, {
1677
- maxSwipes: Number(options.scrollToTopMaxSwipes || 12),
1678
- stableRounds: 2,
1679
- settleMs: 400
1680
- }).catch((error) => {
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"
1709
+ });
1710
+ Logger.info("captureScreen scrollToTop", {
1711
+ swipes: topResult?.swipes,
1712
+ stableRounds: topResult?.stableRounds,
1713
+ hashSource: topResult?.hashSource,
1714
+ capped: topResult?.capped === true
1715
+ });
1716
+ } catch (error) {
1717
+ if (options.strictScrollToTop === true) throw error;
1681
1718
  Logger.warn("captureScreen scrollToTop skipped", { message: error?.message || String(error) });
1682
- });
1719
+ }
1683
1720
  for (let index = 0; index < DEFAULT_CAPTURE_COUNT; index += 1) {
1684
- await Device.hideKeyboard(ctx, { attempts: 1, settleMs: 250 }).catch(() => {
1721
+ if (shouldHideKeyboard) await Device.hideKeyboard(ctx, { attempts: 1, settleMs: 250 }).catch(() => {
1685
1722
  });
1686
1723
  await sleep(DEFAULT_SETTLE_MS);
1687
1724
  const png = await Device.screenshotPng(ctx);