Include appVersion and clientVersion in error reporting for task failures. Add fallback logic for bottom navigation taps in GetLastTransactionsScript using icon-based detection.
This commit is contained in:
parent
b486e922b3
commit
3391591e33
@ -1,7 +1,6 @@
|
||||
#include "GetLastTransactionsScript.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QHash>
|
||||
#include <QRegularExpression>
|
||||
#include <QSet>
|
||||
#include <QThread>
|
||||
@ -437,34 +436,51 @@ void GetLastTransactionsScript::doStart() {
|
||||
}
|
||||
|
||||
QPoint GetLastTransactionsScript::bottomNavPoint(const QString &label, const DeviceInfo &device) {
|
||||
const Node n = xmlScreenParser.findNodeByContentDesc(label);
|
||||
// Реальные bounds принимаем только если они «вменяемые» для НИЖНЕГО меню:
|
||||
// непустой узел, ненулевой центр И центр в нижней полосе экрана (>= 80%
|
||||
// высоты). Это отсекает не только вырожденные [0,0][0,0] (Infinix XOS), но и
|
||||
// НЕнулевые, но негодные координаты — напр. одноимённый элемент не в нав-баре
|
||||
// или частичные bounds. Иначе нав-бар у самого низа, центр таба ~95% высоты.
|
||||
if (!n.isEmpty() && n.x() > 0 && n.y() >= static_cast<int>(device.screenHeight * 0.80))
|
||||
return {n.x(), n.y()};
|
||||
// 1) Норма: у таба есть реальные bounds в нижней полосе экрана. Проверка
|
||||
// «центр в нижних 80% высоты» отсекает и вырожденные [0,0][0,0], и
|
||||
// НЕнулевые-но-негодные координаты (одноимённый элемент не в нав-баре).
|
||||
const Node lbl = xmlScreenParser.findNodeByContentDesc(label);
|
||||
if (!lbl.isEmpty() && lbl.x() > 0
|
||||
&& lbl.y() >= static_cast<int>(device.screenHeight * 0.80))
|
||||
return {lbl.x(), lbl.y()};
|
||||
|
||||
// Узел нав-таба отсутствует или негоден. На части устройств
|
||||
// (наблюдалось на Infinix X669D, app 3.2.41 — гибридный UI) uiautomator не
|
||||
// отдаёт bounds нижнего меню, хотя оно отрисовано в полосе у самого низа
|
||||
// экрана (ниже всего дерева доступности). Тапаем по геометрии: 5 равных
|
||||
// слотов — Главная · Переводы · [FAB] · MiniApps · История; центр слота —
|
||||
// доля ширины, высота — у самого низа экрана.
|
||||
static const QHash<QString, double> kFx{
|
||||
{QString::fromUtf8("Главная"), 0.10},
|
||||
{QString::fromUtf8("Переводы"), 0.30},
|
||||
{QString::fromUtf8("MiniApps"), 0.70},
|
||||
{QString::fromUtf8("История"), 0.90},
|
||||
};
|
||||
const auto it = kFx.constFind(label);
|
||||
if (it == kFx.constEnd()) return {-1, -1};
|
||||
const int x = static_cast<int>(device.screenWidth * it.value());
|
||||
const int y = static_cast<int>(device.screenHeight * 0.95);
|
||||
qWarning() << "[Dushanbe::GetLastTransactions] nav tab" << label
|
||||
<< "has no usable bounds — geometric fallback tap at" << x << y;
|
||||
return {x, y};
|
||||
// 2) Лейбл нав-таба вырожден ([0,0][0,0] — гибридный UI, напр. Infinix XOS не
|
||||
// отдаёт bounds нижнего меню). Но ИКОНКИ табов имеют реальные координаты.
|
||||
// Берём самый нижний ряд небольших нод и в нём крайнюю по X: История —
|
||||
// самая правая иконка, Главная — самая левая (FAB по центру никогда не
|
||||
// крайний; контентные плитки выше нижнего ряда и отсекаются по y2). Это
|
||||
// фактические координаты → не зависит от размера экрана, плотности и
|
||||
// высоты системной навигации Android (её фикс-высота в dp ломала бы доли).
|
||||
const bool rightmost = (label == QString::fromUtf8("История"));
|
||||
const bool leftmost = (label == QString::fromUtf8("Главная"));
|
||||
if (rightmost || leftmost) {
|
||||
const int H = device.screenHeight, W = device.screenWidth;
|
||||
const auto nodes = xmlScreenParser.findAllNodes();
|
||||
auto isNavIcon = [&](const Node &n) {
|
||||
return n.x1() >= 0 && n.width() > 0 && n.height() >= 12
|
||||
&& n.width() <= W / 3 && n.y() >= H / 2; // не контейнер, нижняя половина
|
||||
};
|
||||
int rowBottom = -1;
|
||||
for (const Node &n : nodes)
|
||||
if (isNavIcon(n)) rowBottom = qMax(rowBottom, n.y2());
|
||||
if (rowBottom > 0) {
|
||||
const int tol = qMax(8, H / 100); // «тот же ряд» — у самой нижней кромки
|
||||
Node pick;
|
||||
for (const Node &n : nodes) {
|
||||
if (!isNavIcon(n) || n.y2() < rowBottom - tol) continue;
|
||||
if (pick.isEmpty()
|
||||
|| (rightmost && n.x() > pick.x())
|
||||
|| (leftmost && n.x() < pick.x()))
|
||||
pick = n;
|
||||
}
|
||||
if (!pick.isEmpty()) {
|
||||
qWarning() << "[Dushanbe::GetLastTransactions] nav tab" << label
|
||||
<< "— icon-row fallback tap at" << pick.x() << pick.y();
|
||||
return {pick.x(), pick.y()};
|
||||
}
|
||||
}
|
||||
}
|
||||
return {-1, -1};
|
||||
}
|
||||
|
||||
void GetLastTransactionsScript::searchAll(
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QMap>
|
||||
#include <QSettings>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
#include <QTimeZone>
|
||||
@ -230,27 +231,35 @@ static void sendTaskError(const QString &type, const QString &materialId, const
|
||||
// api-токен общий на нескольких операторов — по нему не отличить, чей
|
||||
// профиль упал. Резолвим банковский профиль по accountId и пишем его
|
||||
// серверный UUID + материал + телефон профиля.
|
||||
QString profileUuid, profilePhone;
|
||||
QString profileUuid, profilePhone, appVersion;
|
||||
if (accountId > 0) {
|
||||
const MaterialInfo acc = MaterialDAO::getAccountById(accountId);
|
||||
if (acc.id != -1) {
|
||||
const BankProfileInfo app = BankProfileDAO::getApplication(acc.deviceId, acc.appCode);
|
||||
profileUuid = app.bankProfileId;
|
||||
profilePhone = app.phone;
|
||||
appVersion = app.appVersion;
|
||||
}
|
||||
}
|
||||
const QString desktopId = SettingsDAO::get("desktop_id");
|
||||
// Версия самого ARC-десктопа (клиента), не банковского приложения.
|
||||
const QString clientVersion =
|
||||
QSettings("config.ini", QSettings::IniFormat).value("common/version").toString();
|
||||
QStringList lines;
|
||||
lines << QStringLiteral("<b>[TASK_ERROR] [%1] [%2]</b>")
|
||||
.arg(type.toHtmlEscaped(), bankName.toUpper().toHtmlEscaped());
|
||||
if (!desktopId.isEmpty())
|
||||
lines << QStringLiteral("Desktop: %1").arg(desktopId.toHtmlEscaped());
|
||||
if (!clientVersion.isEmpty())
|
||||
lines << QStringLiteral("DesktopVersion: %1").arg(clientVersion.toHtmlEscaped());
|
||||
if (!profileUuid.isEmpty())
|
||||
lines << QStringLiteral("Profile: %1").arg(profileUuid.toHtmlEscaped());
|
||||
if (!materialId.isEmpty())
|
||||
lines << QStringLiteral("Material: %1").arg(materialId.toHtmlEscaped());
|
||||
if (!profilePhone.isEmpty())
|
||||
lines << QStringLiteral("Phone: %1").arg(profilePhone.toHtmlEscaped());
|
||||
if (!appVersion.isEmpty())
|
||||
lines << QStringLiteral("AppVersion: %1").arg(appVersion.toHtmlEscaped());
|
||||
lines << QStringLiteral("Error: %1").arg(description.toHtmlEscaped());
|
||||
const QString message = lines.join(QStringLiteral("\n"));
|
||||
sendMonitoringLog("error", "task_error", message, screenshot, eventId);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user