#pragma once #include #include #include #include "android/xml/Node.h" #include "db/MaterialInfo.h" namespace Dushanbe { class ScreenXmlParser final : public QObject { Q_OBJECT public: explicit ScreenXmlParser(QObject *parent = nullptr); ~ScreenXmlParser() override; void parseAndSaveXml(const QString &xml); const QList &findAllNodes() const; Node findTextNode(const QString &text); Node findNodeByContentDesc(const QString &contentDesc); Node findNodeByContentDesc(const QString &contentDesc, bool contains); Node findButtonNode(const QString &text, bool contains); Node findFirstEditText(); // TODO: реализовать после снятия XML дампов экранов bool isPinCodeScreen(); Node findPinCodeEditText(); bool isHomeScreen(); // Парсит баланс с домашнего экрана double parseBalanceFromHomeScreen(); // Находит кнопку обновления данных в блоке "TJS\n<дата>" — правый clickable // ImageView (рядом слева сидит глазик-Button, его не трогаем). Node findRefreshButtonOnHomeScreen(); // Парсит имя пользователя с домашнего экрана QString parseUserNameFromHomeScreen(); // Определяет боковое меню (профиль) bool isSideMenu(); // Парсит данные профиля из бокового меню // content-desc: "Имя Фамилия\n+992...\nВерсия:...\nСборка:..." QString parseProfileFullName(); QString parseProfilePhone(); // Определяет экран "Мои карты" bool isCardsScreen(); // Структура для карты из экрана "Мои карты" struct CardInfo { double amount = 0.0; QString currency; QString lastNumbers; // "3258" QString expiry; // "11/35" QString holderName; // "IMOMKULZODA MEKHRUBON" QString description; // "Кредитная карта" и т.д. }; // Парсит все карты с экрана "Мои карты" (lastNumbers только) QList parseCards(); // Определяет экран детали карты (заголовок "Карта") bool isCardDetailScreen(); // Парсит полный номер карты с экрана детали ("9762 0002 0711 3258") QString parseFullCardNumber(); // Парсит баланс с экрана детали ("0,00 TJS") double parseCardDetailBalance(); // Парсит имя держателя с экрана детали QString parseCardDetailHolder(); // Кнопка "Настройки карты" на экране детали карты Node findCardSettingsButton(); // Bottom sheet с пунктами "Реквизиты карты" / "Заблокировать карту" и т.д. bool isCardSettingsBottomSheet(); // Кнопка "Реквизиты карты" внутри bottom sheet "Настройки карты" Node findCardRequisitesMenuItem(); // Экран "Реквизиты и информация" с табами "Реквизиты карты" / "Реквизиты счета" bool isCardRequisitesScreen(); // Таб "Реквизиты счета" (правый) на экране "Реквизиты и информация" Node findAccountRequisitesTab(); // Значение под лейблом "Номер счета" — длинная цифровая строка QString parseAccountNumber(); // Определяет экран истории операций (табы "Операции" + "Выписка") bool isHistoryScreen(); // Структура для транзакции из экрана истории struct TransactionItem { QString cardMask; // "9762***3258" QString phone; // "992882770011" double amount = 0.0; // 493.00 QString description; // "DC (по номеру телефона)" QString time; // "18:57:10" }; // Парсит транзакции с экрана истории QList parseTransactionItems(); // Определяет экран детали транзакции (содержит "Дата операции:" и "Номер операции:") bool isTransactionDetailScreen(); // Структура для деталей транзакции struct TransactionDetail { QString date; // "03.04.2026" QString time; // "18:57:10" QString operationId; // "1593369670" QString provider; // "DC (по номеру телефона)" QString senderAccount; // "9762***3258" QString receiverAccount;// "992882770011" double amount = 0.0; // 493.00 double fee = 0.0; // 0.00 QString status; // "Успешный" }; // Парсит детали транзакции TransactionDetail parseTransactionDetail(); // Находит EditText по hint // Парсит пары "Лейбл: " → "Значение" для экранов, где поля разложены по // отдельным View-узлам в две колонки (формат с 3.2.33). Метод сканирует // все ноды: лейблом считается контент, оканчивающийся на ':', значением — // ближайший справа узел на той же Y-полосе. Возвращает map без двоеточий. QMap parseLabelValuePairs(); Node findEditTextByHint(const QString &hint); // Поле ввода суммы на экране перевода. У EditText'а нет hint/content-desc // (NAF), поэтому ищем по якорю — View "Мин. сумма: ..." под полем — // и берём ближайший EditText выше якоря. Node findSumEditText(); // Находит кнопку закрытия Google Play in-app update bottom sheet // ("com.android.vending" оверлей "Доступно обновление"), если он показан Node tryToFindGooglePlayBanner(int screenWidth, int screenHeight); // Находит кнопку "ЗАПРЕТИТЬ" в системном диалоге запроса разрешения Android // (com.google.android.permissioncontroller). Возвращает пустой Node если диалог не виден. Node tryToFindSystemPermissionDenyButton(); private: QList m_nodes; QDomElement m_xml; }; } // namespace Dushanbe