From bac36aa5d22a192e5c1b9a45c833d338b9122556 Mon Sep 17 00:00:00 2001 From: slava Date: Sat, 18 Apr 2026 19:46:06 +0700 Subject: [PATCH] Refine date header visibility logic and scroll behavior in `GetLastTransactionsScript`: - Add `computeDateYCount` to detect overlapping date headers and improve visibility checks. - Adjust swipe logic for better handling of target and older dates during transaction fetching. - --- android/ozon/GetLastTransactionsScript.cpp | 75 +++++++++++++++------- 1 file changed, 52 insertions(+), 23 deletions(-) diff --git a/android/ozon/GetLastTransactionsScript.cpp b/android/ozon/GetLastTransactionsScript.cpp index bca8662..38a2736 100644 --- a/android/ozon/GetLastTransactionsScript.cpp +++ b/android/ozon/GetLastTransactionsScript.cpp @@ -277,17 +277,36 @@ void GetLastTransactionsScript::searchTransaction(const DeviceInfo &device, int return QDate(searchDate.year(), month, day); }; - auto hasDateOnScreen = [&]() -> bool { + // Ozon WebView сворачивает заголовки дат вне вьюпорта в один y (0 или общий + // верхний y). Несколько разных дат на одной y-позиции — pile-up скрытых + // заголовков, их надо считать невидимыми. + auto computeDateYCount = [&]() -> QMap { + QMap cnt; for (const Node &node : xmlScreenParser.getNodes()) { if (node.className != "android.widget.TextView") continue; + if (node.y() <= 0) continue; + if (parseDateHeader(node.text.trimmed()).isValid()) cnt[node.y()]++; + } + return cnt; + }; + + auto hasDateOnScreen = [&]() -> bool { + const QMap yCount = computeDateYCount(); + for (const Node &node : xmlScreenParser.getNodes()) { + if (node.className != "android.widget.TextView") continue; + if (node.y() <= 0) continue; + if (yCount.value(node.y(), 0) != 1) continue; if (parseDateHeader(node.text.trimmed()) == searchDate) return true; } return false; }; auto hasOlderDateOnScreen = [&]() -> bool { + const QMap yCount = computeDateYCount(); for (const Node &node : xmlScreenParser.getNodes()) { if (node.className != "android.widget.TextView") continue; + if (node.y() <= 0) continue; + if (yCount.value(node.y(), 0) != 1) continue; const QDate d = parseDateHeader(node.text.trimmed()); if (d.isValid() && d < searchDate) return true; } @@ -345,6 +364,9 @@ void GetLastTransactionsScript::searchTransaction(const DeviceInfo &device, int // видна ниже (или не видна вовсе), dateY = 0 — все кнопки выше nextDateY // принадлежат нашему дню. auto findDateYRange = [&]() -> QPair { + const QMap yCount = computeDateYCount(); + auto isVisible = [&](int y) { return y > 0 && yCount.value(y, 0) == 1; }; + int dateY = -1; int nextDateY = device.screenHeight; bool foundOlderDate = false; @@ -353,23 +375,18 @@ void GetLastTransactionsScript::searchTransaction(const DeviceInfo &device, int const QDate d = parseDateHeader(node.text.trimmed()); if (!d.isValid()) continue; if (d == searchDate) { - dateY = node.y(); + if (isVisible(node.y())) dateY = node.y(); } else if (d < searchDate) { - // Заголовок более старой даты — граница снизу - if (dateY >= 0 && node.y() > dateY) { - nextDateY = node.y(); - } else if (dateY < 0) { - // Заголовок нужной даты ушёл вверх, но видна более старая дата - nextDateY = node.y(); - dateY = 0; // всё выше nextDateY принадлежит нашему дню - } foundOlderDate = true; - break; + if (isVisible(node.y()) && (dateY < 0 || node.y() > dateY) + && node.y() < nextDateY) { + nextDateY = node.y(); + } } } - // Заголовок ушёл вверх и нет более старых дат на экране — - // весь экран всё ещё внутри нашей даты - if (dateY < 0 && !foundOlderDate && dateFound) { + // Target-header не виден, но видна более старая дата → target ушёл вверх: + // всё выше nextDateY принадлежит нашему дню. + if (dateY < 0 && nextDateY < device.screenHeight) { dateY = 0; } qDebug() << "[FetchTransactions] findDateYRange: dateY=" << dateY @@ -405,11 +422,13 @@ void GetLastTransactionsScript::searchTransaction(const DeviceInfo &device, int // Находим Y-диапазон заголовка нужной даты const auto [dateHeaderY, nextDateHeaderY] = findDateYRange(); if (dateHeaderY < 0) { - qDebug() << "[FetchTransactions] Date completely off screen, scrolling up"; + // Target-header не виден и ни одной более старой даты не видно → + // target скорее всего ниже вьюпорта. Скроллим вниз (swipe вверх). + qDebug() << "[FetchTransactions] Target not visible, no older date — scrolling down"; AdbUtils::makeSwipe(m_deviceId, device.screenWidth / 2, - device.screenHeight / 3, + device.screenHeight * 2 / 3, device.screenWidth / 2, - device.screenHeight * 2 / 3, 600); + device.screenHeight / 3, 500); QThread::msleep(1500); continue; } @@ -641,23 +660,33 @@ void GetLastTransactionsScript::searchTransaction(const DeviceInfo &device, int noProgressCount = 0; } - // Скроллим вниз если не нашли нужную транзакцию + // Скроллим если не нашли нужную транзакцию if (!tapped || !hasNewButton) { - qDebug() << "[FetchTransactions] Scrolling down (tapped=" << tapped + qDebug() << "[FetchTransactions] Scrolling (tapped=" << tapped << "hasNew=" << hasNewButton << "inRange=" << buttonsInRange - << "noProgress=" << noProgressCount << ")"; + << "noProgress=" << noProgressCount + << "dateHeaderY=" << dateHeaderY + << "nextDateHeaderY=" << nextDateHeaderY << ")"; - if (dateHeaderY > 0 && dateHeaderY < device.screenHeight / 2) { + if (dateHeaderY == 0 && nextDateHeaderY < device.screenHeight) { + // Target-header ушёл вверх, под ним видна более старая дата — + // скроллим обратно наверх (swipe вниз) чтобы вернуться к target. + const int fromY = device.screenHeight / 3; + const int toY = device.screenHeight * 2 / 3; + qDebug() << "[FetchTransactions] Scroll UP: from" << fromY << "to" << toY; + AdbUtils::makeSwipe(m_deviceId, device.screenWidth / 2, fromY, + device.screenWidth / 2, toY, 500); + } else if (dateHeaderY > 0 && dateHeaderY < device.screenHeight / 2) { // Заголовок в верхней половине — маленький скролл чтобы показать // больше кнопок под этой датой const int fromY = device.screenHeight * 2 / 3; const int toY = device.screenHeight / 3; - qDebug() << "[FetchTransactions] Small scroll: from" << fromY << "to" << toY + qDebug() << "[FetchTransactions] Small scroll down: from" << fromY << "to" << toY << "(dateHeaderY=" << dateHeaderY << ")"; AdbUtils::makeSwipe(m_deviceId, device.screenWidth / 2, fromY, device.screenWidth / 2, toY, 500); } else { - // Заголовок в нижней половине или за экраном — полный скролл + // Заголовок в нижней половине или не найден — скролл вниз const int fromY = device.screenHeight * 3 / 4; const int toY = device.screenHeight / 4; qDebug() << "[FetchTransactions] Full scroll down: from" << fromY << "to" << toY