diff --git a/android/dushanbe/CommonScript.h b/android/dushanbe/CommonScript.h index 42e35dc..a1bb32e 100644 --- a/android/dushanbe/CommonScript.h +++ b/android/dushanbe/CommonScript.h @@ -51,11 +51,15 @@ protected: ScreenXmlParser xmlScreenParser; int m_counter = 0; + QByteArray m_resultScreenshot; + signals: void finished(); void finishedWithResult(const QString &result); + void screenshotReady(const QByteArray &screenshot); + public slots: virtual void start() final; diff --git a/android/dushanbe/GetLastTransactionsScript.cpp b/android/dushanbe/GetLastTransactionsScript.cpp index 0465034..972be62 100644 --- a/android/dushanbe/GetLastTransactionsScript.cpp +++ b/android/dushanbe/GetLastTransactionsScript.cpp @@ -391,6 +391,18 @@ void GetLastTransactionsScript::doStart() { } xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter)); + // Верх нижнего меню: минимальный y1() среди табов и FAB "Сканировать". + // Тап по строке с y >= navTopY - navMargin промахивается и попадает в FAB/таб. + int navTopY = device.screenHeight; + for (const QString &lbl : { + QString::fromUtf8("Главная"), QString::fromUtf8("История"), + QString::fromUtf8("Переводы"), QString::fromUtf8("Сканировать")}) { + Node nav = xmlScreenParser.findNodeByContentDesc(lbl); + if (!nav.isEmpty() && nav.y1() > 0 && nav.y1() < navTopY) navTopY = nav.y1(); + } + const int navMargin = 20; + qDebug() << "[Dushanbe::GetLastTransactions] navTopY=" << navTopY; + // 1. Собираем список дат-групп + извлекаем "встроенную" верхнюю транзакцию, // которая впечатана в content-desc родительского ImageView "Обновлено: ..." // вместо отдельного android.view.View (самая свежая запись в Выписке). @@ -600,7 +612,17 @@ void GetLastTransactionsScript::doStart() { continue; } - AdbUtils::makeTap(m_deviceId, txNode.x(), txNode.y()); + // Строка под нижним меню — тап попадёт в FAB "Сканировать" или таб. + // Пропускаем кандидата, ищем совпадение выше; если таких нет — скролл. + if (txNode.y() >= navTopY - navMargin) { + qDebug() << "[Dushanbe::GetLastTransactions] Candidate y=" << txNode.y() + << "behind nav (navTopY=" << navTopY << "), skipping, will scroll"; + continue; + } + + // Тап по левому краю ряда — уходим от центра экрана, где FAB "Сканировать". + const int tapX = txNode.x1() + 80; + AdbUtils::makeTap(m_deviceId, tapX, txNode.y()); QThread::msleep(3000); if (interrupted()) { m_error = "Interrupted"; emit finishedWithResult(m_error); return; } @@ -716,6 +738,11 @@ void GetLastTransactionsScript::doStart() { emit transactionParsed(txJson); } + // Скриншот экрана деталей транзакции — отправляем в мониторинг + m_resultScreenshot = AdbUtils::captureScreenshotBytes(m_deviceId); + if (!m_resultScreenshot.isEmpty()) + emit screenshotReady(m_resultScreenshot); + // Назад к истории Node nazadBtn = xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Назад")); if (nazadBtn.x() > 0 && nazadBtn.y() > 0) { @@ -753,7 +780,9 @@ void GetLastTransactionsScript::doStart() { qWarning() << "[Dushanbe::GetLastTransactions]" << m_error; // Отправляем скриншот списка транзакций, сделанный до начала поиска - if (!listScreenshot.isEmpty()) emit screenshotReady(listScreenshot); + m_resultScreenshot = listScreenshot.isEmpty() + ? AdbUtils::captureScreenshotBytes(m_deviceId) : listScreenshot; + if (!m_resultScreenshot.isEmpty()) emit screenshotReady(m_resultScreenshot); // Возвращаемся на главную Node glavnayaBtn = xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Главная")); diff --git a/android/dushanbe/GetLastTransactionsScript.h b/android/dushanbe/GetLastTransactionsScript.h index 49de28b..5d9a900 100644 --- a/android/dushanbe/GetLastTransactionsScript.h +++ b/android/dushanbe/GetLastTransactionsScript.h @@ -27,9 +27,6 @@ signals: // повторного чтения из БД. void transactionParsed(const QJsonObject &tx); - // Скриншот списка транзакций (при ошибке отправляется в мониторинг) - void screenshotReady(const QByteArray &screenshot); - protected: void doStart() override; diff --git a/android/dushanbe/LoginAndCheckAccountsScript.cpp b/android/dushanbe/LoginAndCheckAccountsScript.cpp index c5323c0..a798f29 100644 --- a/android/dushanbe/LoginAndCheckAccountsScript.cpp +++ b/android/dushanbe/LoginAndCheckAccountsScript.cpp @@ -45,6 +45,8 @@ void LoginAndCheckAccountsScript::doStart() { if (!runAppAndGoToHomeScreen(m_deviceId, app.package, app.pinCode, device.screenWidth, device.screenHeight)) { m_error = "Cant open the home screen: " + device.name + " (" + m_deviceId + ") " + m_appCode; qWarning() << m_error; + m_resultScreenshot = AdbUtils::captureScreenshotBytes(m_deviceId); + if (!m_resultScreenshot.isEmpty()) emit screenshotReady(m_resultScreenshot); AppLogger::log("dushanbe/LoginAndCheck", m_deviceId, m_error, {}, "FETCH_PROFILE"); BankProfileDAO::updateComment(app.id, "Не прошла проверка " + QDateTime::currentDateTime().toString("dd.MM.yyyy HH:mm:ss")); @@ -54,6 +56,10 @@ void LoginAndCheckAccountsScript::doStart() { return; } + // Скриншот домашнего экрана — отправляем в мониторинг + m_resultScreenshot = AdbUtils::captureScreenshotBytes(m_deviceId); + if (!m_resultScreenshot.isEmpty()) emit screenshotReady(m_resultScreenshot); + if (m_pinCheckOnly) { emit finishedWithResult(m_error); return; diff --git a/android/dushanbe/PayByCardScript.cpp b/android/dushanbe/PayByCardScript.cpp index 4beda0d..ecf0deb 100644 --- a/android/dushanbe/PayByCardScript.cpp +++ b/android/dushanbe/PayByCardScript.cpp @@ -405,8 +405,11 @@ void PayByCardScript::makePayment( qDebug() << "[Dushanbe::PayByCard] Payment successful!"; m_error.clear(); - // Скриншот чека - const QByteArray receiptImage = AdbUtils::captureScreenshotBytes(deviceId); + // Скриншот чека — сохраняем как m_resultScreenshot и отправляем в мониторинг + m_resultScreenshot = AdbUtils::captureScreenshotBytes(deviceId); + const QByteArray &receiptImage = m_resultScreenshot; + if (!m_resultScreenshot.isEmpty()) + emit screenshotReady(m_resultScreenshot); // Парсим детали из content-desc "Платеж выполнен" // Формат: "Платеж выполнен\nПоставщик:\n...\nКомиссия:\n0.00\nДата:\n05.04.26\nВремя:\n20:19:56\nНа главную" diff --git a/android/dushanbe/PayByPhoneScript.cpp b/android/dushanbe/PayByPhoneScript.cpp index 4f231e6..d1c2590 100644 --- a/android/dushanbe/PayByPhoneScript.cpp +++ b/android/dushanbe/PayByPhoneScript.cpp @@ -397,8 +397,11 @@ void PayByPhoneScript::makePayment( qDebug() << "[Dushanbe::PayByPhone] Payment successful!"; m_error.clear(); - // Скриншот чека - const QByteArray receiptImage = AdbUtils::captureScreenshotBytes(deviceId); + // Скриншот чека — сохраняем как m_resultScreenshot и отправляем в мониторинг + m_resultScreenshot = AdbUtils::captureScreenshotBytes(deviceId); + const QByteArray &receiptImage = m_resultScreenshot; + if (!m_resultScreenshot.isEmpty()) + emit screenshotReady(m_resultScreenshot); // Парсим детали из content-desc "Платеж выполнен" QString bankTime; diff --git a/services/EventHandler.cpp b/services/EventHandler.cpp index 89782fc..a0a9015 100644 --- a/services/EventHandler.cpp +++ b/services/EventHandler.cpp @@ -450,6 +450,11 @@ void EventHandler::startThreadForTask(const MaterialInfo &account, const EventIn [this, key](const QByteArray &s) { m_screenshots[key] = s; }, Qt::DirectConnection); }; + auto connectScreenshotDushanbe = [this, key](Dushanbe::CommonScript *w) { + connect(w, &Dushanbe::CommonScript::screenshotReady, this, + [this, key](const QByteArray &s) { m_screenshots[key] = s; }, + Qt::DirectConnection); + }; if (event.type == EventType::FetchProfile) { if (appCode == "ozon") { @@ -457,7 +462,10 @@ void EventHandler::startThreadForTask(const MaterialInfo &account, const EventIn setup(w); connectScreenshot(w); } else if (appCode == "black") setup(new Black::LoginAndCheckAccountsScript(adbSerial, appCode)); - else if (appCode == "dushanbe_city_bank") setup(new Dushanbe::LoginAndCheckAccountsScript(adbSerial, appCode)); + else if (appCode == "dushanbe_city_bank") { + auto *w = new Dushanbe::LoginAndCheckAccountsScript(adbSerial, appCode); + setup(w); connectScreenshotDushanbe(w); + } else qWarning() << "[EventHandler] FETCH_PROFILE: unknown appCode:" << appCode; } @@ -479,13 +487,10 @@ void EventHandler::startThreadForTask(const MaterialInfo &account, const EventIn setup(new Black::GetLastTransactionsScript(adbSerial, appCode)); else if (appCode == "dushanbe_city_bank") { auto *w = new Dushanbe::GetLastTransactionsScript(adbSerial, appCode, searchAmount, searchTime); - setup(w); + setup(w); connectScreenshotDushanbe(w); connect(w, &Dushanbe::GetLastTransactionsScript::transactionParsed, this, [this, key](const QJsonObject &tx) { m_parsedTxs[key] = tx; }, Qt::DirectConnection); - connect(w, &Dushanbe::GetLastTransactionsScript::screenshotReady, this, - [this, key](const QByteArray &s) { m_screenshots[key] = s; }, - Qt::DirectConnection); } else qWarning() << "[EventHandler] FETCH_TRANSACTIONS: unknown appCode:" << appCode; } @@ -504,7 +509,10 @@ void EventHandler::startThreadForTask(const MaterialInfo &account, const EventIn setup(w); connectScreenshot(w); } else if (appCode == "black") setup(new Black::PayByCardScript(account, event.phone, event.amount)); - else if (appCode == "dushanbe_city_bank") setup(new Dushanbe::PayByCardScript(account, event.phone, event.amount)); + else if (appCode == "dushanbe_city_bank") { + auto *w = new Dushanbe::PayByCardScript(account, event.phone, event.amount); + setup(w); connectScreenshotDushanbe(w); + } else qWarning() << "[EventHandler] CREATE_TRANSACTION bank: unknown appCode:" << appCode; } else { // Перевод по номеру телефона (top-up) @@ -512,7 +520,10 @@ void EventHandler::startThreadForTask(const MaterialInfo &account, const EventIn auto *w = new Ozon::PayByPhoneScript(account, event.phone, recipientBank, event.amount); setup(w); connectScreenshot(w); } - else if (appCode == "dushanbe_city_bank") setup(new Dushanbe::PayByPhoneScript(account, event.phone, event.amount)); + else if (appCode == "dushanbe_city_bank") { + auto *w = new Dushanbe::PayByPhoneScript(account, event.phone, event.amount); + setup(w); connectScreenshotDushanbe(w); + } else qWarning() << "[EventHandler] CREATE_TRANSACTION: unknown appCode:" << appCode; } }