Add core scripts for Black app automation and XML parsing
Implemented `CommonScript` as a base class with reusable functionality for automation workflows, including PIN input, app navigation, and server communication. Added specialized scripts like `GetCardInfoScript`, `GetProfileInfoScript`, and `LoginAndCheckAccountsScript` for card retrieval, profile parsing, and login validation. Introduced `ScreenXmlParser` for efficient XML-based UI parsing and node detection.
232
android/black/CommonScript.cpp
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
#include "CommonScript.h"
|
||||||
|
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QRandomGenerator>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
#include "adb/AdbUtils.h"
|
||||||
|
#include "dao/ApplicationDAO.h"
|
||||||
|
#include "net/NetworkService.h"
|
||||||
|
|
||||||
|
namespace Black {
|
||||||
|
|
||||||
|
CommonScript::CommonScript(QObject *parent)
|
||||||
|
: QObject(parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonScript::~CommonScript() = default;
|
||||||
|
|
||||||
|
void CommonScript::start() {
|
||||||
|
doStart();
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
Node CommonScript::swipeToButton(
|
||||||
|
const QString &deviceId,
|
||||||
|
const QString &text, int &counter, const int width, const int height
|
||||||
|
) {
|
||||||
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
if (Node button = xmlScreenParser.findButtonNode(text, true); button.x() > 0 && button.y() > 0) {
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
const int x = width / 2;
|
||||||
|
const int offset = height / 4;
|
||||||
|
AdbUtils::makeSwipe(deviceId, x, height - offset, x, offset);
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++counter));
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonScript::inputPinCode(const QString &deviceId, const QString &pinCode) {
|
||||||
|
// BlackBanx использует EditText с password=true, а не кнопочную сетку
|
||||||
|
Node editText = xmlScreenParser.findPinCodeEditText();
|
||||||
|
if (editText.isEmpty()) {
|
||||||
|
qWarning() << "[Black::inputPinCode] PIN EditText not found";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Тапаем по полю для фокуса
|
||||||
|
AdbUtils::makeTap(deviceId, editText.x(), editText.y());
|
||||||
|
QThread::msleep(500);
|
||||||
|
|
||||||
|
// Вводим PIN через текстовый ввод
|
||||||
|
AdbUtils::inputText(deviceId, pinCode);
|
||||||
|
QThread::msleep(500);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonScript::runAppAndGoToHomeScreen(
|
||||||
|
const QString &deviceId,
|
||||||
|
const QString &packageName,
|
||||||
|
const QString &pinCode,
|
||||||
|
const int width,
|
||||||
|
const int height
|
||||||
|
) {
|
||||||
|
// Убить приложение если запущено
|
||||||
|
if (const QString pid = AdbUtils::tryToGetRunningAppPid(deviceId, packageName); !pid.isEmpty()) {
|
||||||
|
qDebug() << "[Black] Process already running, pid:" << pid;
|
||||||
|
AdbUtils::getScreenDumpAsXml(deviceId, 1000);
|
||||||
|
AdbUtils::tryToKillApplication(deviceId, packageName);
|
||||||
|
}
|
||||||
|
if (!AdbUtils::tryToStartApplication(deviceId, packageName)) {
|
||||||
|
AdbUtils::takeScreenshot(deviceId, "run_app_error");
|
||||||
|
qWarning() << "[Black] Process has not started";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Даем время на запуск
|
||||||
|
QThread::msleep(4500);
|
||||||
|
int counter = 0;
|
||||||
|
bool findAndInputPincode = false;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
counter++;
|
||||||
|
|
||||||
|
if (counter > 10) {
|
||||||
|
AdbUtils::takeScreenshot(deviceId, "too_many_attempts");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(deviceId, ++m_counter));
|
||||||
|
|
||||||
|
if (xmlScreenParser.isHomeScreen()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем экран ввода PIN-кода
|
||||||
|
if (!findAndInputPincode && xmlScreenParser.isPinCodeScreen()) {
|
||||||
|
inputPinCode(deviceId, pinCode);
|
||||||
|
findAndInputPincode = true;
|
||||||
|
QThread::msleep(3000);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QThread::msleep(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommonScript::postAccountsData(const QList<QPair<AccountInfo, Node>> &accounts) {
|
||||||
|
if (accounts.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *thread = new QThread;
|
||||||
|
auto *worker = new NetworkService;
|
||||||
|
|
||||||
|
QJsonArray list;
|
||||||
|
for (const QPair<AccountInfo, Node> &pair : accounts) {
|
||||||
|
QJsonObject obj;
|
||||||
|
AccountInfo account = pair.first;
|
||||||
|
obj["appName"] = account.appCode;
|
||||||
|
obj["lastNumbers"] = account.lastNumbers;
|
||||||
|
obj["amount"] = account.amount;
|
||||||
|
obj["description"] = account.description;
|
||||||
|
obj["currency"] = account.currency;
|
||||||
|
obj["status"] = accountStatusToString(account.status);
|
||||||
|
list.append(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
worker->setDeviceId(accounts.first().first.deviceId);
|
||||||
|
worker->setPayload(QJsonDocument(list).toJson());
|
||||||
|
worker->moveToThread(thread);
|
||||||
|
connect(thread, &QThread::started, worker, &NetworkService::postAccountsData);
|
||||||
|
connect(worker, &NetworkService::finished, thread, &QThread::quit);
|
||||||
|
connect(worker, &NetworkService::finished, worker, &QObject::deleteLater);
|
||||||
|
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
|
||||||
|
thread->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommonScript::postNewTransactionData(const AccountInfo &account, const TransactionInfo &transaction) {
|
||||||
|
auto *thread = new QThread;
|
||||||
|
auto *worker = new NetworkService;
|
||||||
|
|
||||||
|
QJsonObject obj;
|
||||||
|
obj["id"] = transaction.id;
|
||||||
|
obj["amount"] = transaction.amount;
|
||||||
|
obj["name"] = transaction.name;
|
||||||
|
obj["fee"] = transaction.fee;
|
||||||
|
obj["status"] = transactionStatusToString(transaction.status);
|
||||||
|
obj["type"] = transactionTypeToString(transaction.type);
|
||||||
|
obj["phone"] = transaction.phone;
|
||||||
|
obj["description"] = transaction.description;
|
||||||
|
obj["updatedDescription"] = transaction.updatedDescription;
|
||||||
|
obj["bankName"] = transaction.bankName;
|
||||||
|
obj["bankTime"] = transaction.bankTime;
|
||||||
|
obj["bankTransactionId"] = transaction.bankTrExternalId;
|
||||||
|
|
||||||
|
worker->setDeviceId(account.deviceId);
|
||||||
|
worker->addExtra("lastNumbers", account.lastNumbers);
|
||||||
|
worker->addExtra("transactionId", transaction.id);
|
||||||
|
worker->setPayload(QJsonDocument(obj).toJson());
|
||||||
|
worker->moveToThread(thread);
|
||||||
|
connect(thread, &QThread::started, worker, &NetworkService::insertTransactionData);
|
||||||
|
connect(worker, &NetworkService::finished, thread, &QThread::quit);
|
||||||
|
connect(worker, &NetworkService::finished, worker, &QObject::deleteLater);
|
||||||
|
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
|
||||||
|
thread->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommonScript::updateTransactionData(
|
||||||
|
const AccountInfo &account,
|
||||||
|
const int transactionId,
|
||||||
|
const TransactionStatus status,
|
||||||
|
const QString &oldDesc,
|
||||||
|
const QString &newDesc
|
||||||
|
) {
|
||||||
|
auto *thread = new QThread;
|
||||||
|
auto *worker = new NetworkService;
|
||||||
|
|
||||||
|
QJsonObject obj;
|
||||||
|
obj["id"] = transactionId;
|
||||||
|
obj["status"] = transactionStatusToString(status);
|
||||||
|
obj["description"] = newDesc;
|
||||||
|
obj["updatedDescription"] = oldDesc;
|
||||||
|
|
||||||
|
worker->setDeviceId(account.deviceId);
|
||||||
|
worker->addExtra("lastNumbers", account.lastNumbers);
|
||||||
|
worker->setPayload(QJsonDocument(obj).toJson());
|
||||||
|
worker->moveToThread(thread);
|
||||||
|
connect(thread, &QThread::started, worker, &NetworkService::updateTransactionData);
|
||||||
|
connect(worker, &NetworkService::finished, thread, &QThread::quit);
|
||||||
|
connect(worker, &NetworkService::finished, worker, &QObject::deleteLater);
|
||||||
|
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
|
||||||
|
thread->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommonScript::createBankProfileIfNeeded(const QString &deviceId, const QString &appCode) {
|
||||||
|
const ApplicationInfo app = ApplicationDAO::getApplication(deviceId, appCode);
|
||||||
|
if (!app.bankProfileId.isEmpty()) {
|
||||||
|
qDebug() << "[Black] bankProfileId already exists:" << app.bankProfileId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QMap<QString, int> currencyCodes = {
|
||||||
|
{"RUB", 643}, {"USD", 840}, {"KRW", 410}, {"AZN", 944}
|
||||||
|
};
|
||||||
|
const int currencyCode = currencyCodes.value(app.currency.toUpper(), 840);
|
||||||
|
const QStringList parts = app.fullName.split(' ', Qt::SkipEmptyParts);
|
||||||
|
|
||||||
|
QJsonObject profileBody;
|
||||||
|
profileBody["first_name"] = parts.value(0);
|
||||||
|
profileBody["middle_name"] = parts.size() >= 3 ? parts.value(1) : QString("");
|
||||||
|
profileBody["last_name"] = parts.size() >= 3 ? parts.value(2) : parts.value(1);
|
||||||
|
profileBody["bank_name"] = appCode;
|
||||||
|
profileBody["phone_number"] = app.phone.simplified().remove(' ');
|
||||||
|
profileBody["balance"] = QString::number(qRound64(app.amount * 100));
|
||||||
|
profileBody["state"] = (app.status == "active") ? "enabled" : "disabled";
|
||||||
|
profileBody["currency"] = currencyCode;
|
||||||
|
|
||||||
|
NetworkService ns;
|
||||||
|
ns.setDeviceId(deviceId);
|
||||||
|
ns.setPayload(QJsonDocument(profileBody).toJson());
|
||||||
|
ns.addExtra("app_id", app.id);
|
||||||
|
ns.postBankProfile();
|
||||||
|
qDebug() << "[Black] createBankProfileIfNeeded: postBankProfile done";
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommonScript::stop() {
|
||||||
|
m_running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Black
|
||||||
70
android/black/CommonScript.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include "ScreenXmlParser.h"
|
||||||
|
#include "db/TransactionInfo.h"
|
||||||
|
|
||||||
|
namespace Black {
|
||||||
|
|
||||||
|
class CommonScript : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CommonScript(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
~CommonScript() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void doStart() = 0;
|
||||||
|
|
||||||
|
// Ввод PIN-кода через EditText (BlackBanx использует текстовое поле, а не кнопки)
|
||||||
|
bool inputPinCode(const QString &deviceId, const QString &pinCode);
|
||||||
|
|
||||||
|
bool runAppAndGoToHomeScreen(
|
||||||
|
const QString &deviceId,
|
||||||
|
const QString &packageName,
|
||||||
|
const QString &pinCode,
|
||||||
|
int width,
|
||||||
|
int height
|
||||||
|
);
|
||||||
|
|
||||||
|
Node swipeToButton(
|
||||||
|
const QString &deviceId,
|
||||||
|
const QString &text,
|
||||||
|
int &counter, int width, int height
|
||||||
|
);
|
||||||
|
|
||||||
|
void postAccountsData(const QList<QPair<AccountInfo, Node>> &accounts);
|
||||||
|
|
||||||
|
void postNewTransactionData(const AccountInfo &account, const TransactionInfo &transaction);
|
||||||
|
|
||||||
|
void updateTransactionData(
|
||||||
|
const AccountInfo &account,
|
||||||
|
int transactionId,
|
||||||
|
TransactionStatus status,
|
||||||
|
const QString &oldDesc,
|
||||||
|
const QString &newDesc
|
||||||
|
);
|
||||||
|
|
||||||
|
// Создаёт bank_profile на сервере если ещё не создан
|
||||||
|
void createBankProfileIfNeeded(const QString &deviceId, const QString &appCode);
|
||||||
|
|
||||||
|
bool m_running = true;
|
||||||
|
ScreenXmlParser xmlScreenParser;
|
||||||
|
int m_counter = 0;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished();
|
||||||
|
|
||||||
|
void finishedWithResult(const QString &result);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
virtual void start() final;
|
||||||
|
|
||||||
|
virtual void stop() final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q_DISABLE_COPY(CommonScript);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Black
|
||||||
132
android/black/GetCardInfoScript.cpp
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
#include "GetCardInfoScript.h"
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
#include "adb/AdbUtils.h"
|
||||||
|
#include "dao/AccountDAO.h"
|
||||||
|
#include "dao/ApplicationDAO.h"
|
||||||
|
#include "dao/DeviceDAO.h"
|
||||||
|
|
||||||
|
namespace Black {
|
||||||
|
|
||||||
|
GetCardInfoScript::GetCardInfoScript(
|
||||||
|
QString deviceId,
|
||||||
|
QString appCode,
|
||||||
|
QObject *parent
|
||||||
|
) : CommonScript(parent),
|
||||||
|
m_deviceId(std::move(deviceId)),
|
||||||
|
m_appCode(std::move(appCode)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
GetCardInfoScript::~GetCardInfoScript() = default;
|
||||||
|
|
||||||
|
void GetCardInfoScript::doStart() {
|
||||||
|
const DeviceInfo device = DeviceDAO::getDeviceById(m_deviceId);
|
||||||
|
const ApplicationInfo app = ApplicationDAO::getApplication(m_deviceId, m_appCode);
|
||||||
|
|
||||||
|
if (device.id.isEmpty() || app.id == -1) {
|
||||||
|
m_error = "Device or app not found: " + m_deviceId + " " + m_appCode;
|
||||||
|
qCritical() << m_error;
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Читаем текущий экран
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
|
||||||
|
// Если не на домашнем экране — перезапускаем
|
||||||
|
if (!xmlScreenParser.isHomeScreen()) {
|
||||||
|
qDebug() << "[Black::GetCardInfo] Not on home screen, restarting app...";
|
||||||
|
if (!runAppAndGoToHomeScreen(device.id, app.package, app.pinCode,
|
||||||
|
device.screenWidth, device.screenHeight)) {
|
||||||
|
m_error = "Cannot reach home screen: " + m_deviceId + " " + m_appCode;
|
||||||
|
qWarning() << m_error;
|
||||||
|
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Парсим баланс с домашнего экрана
|
||||||
|
const double balance = xmlScreenParser.parseBalanceFromHomeScreen();
|
||||||
|
qDebug() << "[Black::GetCardInfo] balance from home:" << balance;
|
||||||
|
ApplicationDAO::updateAmount(app.id, balance);
|
||||||
|
|
||||||
|
// 2. Нажимаем "Tu CVU" на домашнем экране
|
||||||
|
Node cvuButton = xmlScreenParser.findButtonNode("Tu CVU", false);
|
||||||
|
if (cvuButton.isEmpty()) {
|
||||||
|
m_error = "Cannot find Tu CVU button: " + m_deviceId;
|
||||||
|
qWarning() << m_error;
|
||||||
|
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdbUtils::makeTap(m_deviceId, cvuButton.x(), cvuButton.y());
|
||||||
|
QThread::msleep(2000);
|
||||||
|
|
||||||
|
// 3. Ждём экран CVU
|
||||||
|
bool cvuScreenFound = false;
|
||||||
|
for (int attempt = 0; attempt < 5; ++attempt) {
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
if (xmlScreenParser.isCVUScreen()) {
|
||||||
|
cvuScreenFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QThread::msleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cvuScreenFound) {
|
||||||
|
m_error = "CVU screen not detected: " + m_deviceId;
|
||||||
|
qWarning() << m_error;
|
||||||
|
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Парсим номер CVU
|
||||||
|
const QString cvuNumber = xmlScreenParser.parseCVUNumber();
|
||||||
|
qDebug() << "[Black::GetCardInfo] CVU number:" << cvuNumber;
|
||||||
|
|
||||||
|
if (cvuNumber.isEmpty()) {
|
||||||
|
m_error = "Cannot parse CVU number: " + m_deviceId;
|
||||||
|
qWarning() << m_error;
|
||||||
|
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Сохраняем аккаунт в БД (lastNumbers = последние 4 цифры CVU)
|
||||||
|
const QString lastNumbers = cvuNumber.right(4);
|
||||||
|
|
||||||
|
AccountInfo account;
|
||||||
|
account.deviceId = m_deviceId;
|
||||||
|
account.appCode = m_appCode;
|
||||||
|
account.lastNumbers = lastNumbers;
|
||||||
|
account.cardNumber = cvuNumber;
|
||||||
|
account.amount = balance;
|
||||||
|
account.currency = "USD";
|
||||||
|
account.description = "CVU";
|
||||||
|
account.status = AccountStatus::Active;
|
||||||
|
account.updateTime = QDateTime::currentDateTimeUtc();
|
||||||
|
|
||||||
|
if (!AccountDAO::upsertAccount(account)) {
|
||||||
|
qWarning() << "[Black::GetCardInfo] Failed to upsert account";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. Отправляем данные аккаунтов на сервер
|
||||||
|
AccountInfo savedAccount = AccountDAO::findAppAccount(m_deviceId, m_appCode, lastNumbers);
|
||||||
|
if (savedAccount.id != -1) {
|
||||||
|
QList<QPair<AccountInfo, Node>> accounts;
|
||||||
|
accounts.append({savedAccount, Node()});
|
||||||
|
postAccountsData(accounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "[Black::GetCardInfo] Done. CVU:" << cvuNumber << "balance:" << balance;
|
||||||
|
|
||||||
|
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Black
|
||||||
27
android/black/GetCardInfoScript.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "CommonScript.h"
|
||||||
|
|
||||||
|
namespace Black {
|
||||||
|
|
||||||
|
class GetCardInfoScript final : public CommonScript {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GetCardInfoScript(
|
||||||
|
QString deviceId,
|
||||||
|
QString appCode,
|
||||||
|
QObject *parent = nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
~GetCardInfoScript() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void doStart() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QString m_deviceId;
|
||||||
|
const QString m_appCode;
|
||||||
|
QString m_error;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Black
|
||||||
168
android/black/GetProfileInfoScript.cpp
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
#include "GetProfileInfoScript.h"
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
#include "adb/AdbUtils.h"
|
||||||
|
#include "dao/ApplicationDAO.h"
|
||||||
|
#include "dao/DeviceDAO.h"
|
||||||
|
#include "net/NetworkService.h"
|
||||||
|
|
||||||
|
namespace Black {
|
||||||
|
|
||||||
|
GetProfileInfoScript::GetProfileInfoScript(
|
||||||
|
QString deviceId,
|
||||||
|
QString appCode,
|
||||||
|
QObject *parent
|
||||||
|
) : CommonScript(parent),
|
||||||
|
m_deviceId(std::move(deviceId)),
|
||||||
|
m_appCode(std::move(appCode)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
GetProfileInfoScript::~GetProfileInfoScript() = default;
|
||||||
|
|
||||||
|
void GetProfileInfoScript::doStart() {
|
||||||
|
const DeviceInfo device = DeviceDAO::getDeviceById(m_deviceId);
|
||||||
|
const ApplicationInfo app = ApplicationDAO::getApplication(m_deviceId, m_appCode);
|
||||||
|
|
||||||
|
if (device.id.isEmpty() || app.id == -1) {
|
||||||
|
m_error = "Device or app not found: " + m_deviceId + " " + m_appCode;
|
||||||
|
qCritical() << m_error;
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Читаем текущий экран
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
|
||||||
|
// Если не на домашнем экране — перезапускаем
|
||||||
|
if (!xmlScreenParser.isHomeScreen()) {
|
||||||
|
qDebug() << "[Black::GetProfileInfo] Not on home screen, restarting app...";
|
||||||
|
if (!runAppAndGoToHomeScreen(device.id, app.package, app.pinCode,
|
||||||
|
device.screenWidth, device.screenHeight)) {
|
||||||
|
m_error = "Cannot reach home screen: " + m_deviceId + " " + m_appCode;
|
||||||
|
qWarning() << m_error;
|
||||||
|
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Тапаем по кнопке "¡Hola!" (аватар с именем) на домашнем экране
|
||||||
|
Node holaNode = xmlScreenParser.findHolaButton();
|
||||||
|
if (holaNode.isEmpty()) {
|
||||||
|
m_error = "Cannot find Hola button on home screen: " + m_deviceId;
|
||||||
|
qWarning() << m_error;
|
||||||
|
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Парсим имя и баланс с домашнего экрана
|
||||||
|
const QString fullName = xmlScreenParser.parseUserNameFromHomeScreen();
|
||||||
|
const double balance = xmlScreenParser.parseBalanceFromHomeScreen();
|
||||||
|
qDebug() << "[Black::GetProfileInfo] fullName from home:" << fullName << "balance:" << balance;
|
||||||
|
|
||||||
|
// Сохраняем баланс
|
||||||
|
ApplicationDAO::updateAmount(app.id, balance);
|
||||||
|
|
||||||
|
AdbUtils::makeTap(m_deviceId, holaNode.x(), holaNode.y());
|
||||||
|
QThread::msleep(2000);
|
||||||
|
|
||||||
|
// 2. Ждём боковое меню
|
||||||
|
bool sideMenuFound = false;
|
||||||
|
for (int attempt = 0; attempt < 5; ++attempt) {
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
if (xmlScreenParser.isSideMenu()) {
|
||||||
|
sideMenuFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QThread::msleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sideMenuFound) {
|
||||||
|
m_error = "Side menu not detected: " + m_deviceId;
|
||||||
|
qWarning() << m_error;
|
||||||
|
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Тапаем "Tu Información"
|
||||||
|
Node tuInfoNode = xmlScreenParser.findNodeByContentDesc(QString::fromUtf8("Tu Información"));
|
||||||
|
if (tuInfoNode.isEmpty()) {
|
||||||
|
m_error = "Cannot find Tu Información button: " + m_deviceId;
|
||||||
|
qWarning() << m_error;
|
||||||
|
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdbUtils::makeTap(m_deviceId, tuInfoNode.x(), tuInfoNode.y());
|
||||||
|
QThread::msleep(2500);
|
||||||
|
|
||||||
|
// 4. Ждём страницу профиля "Tu información"
|
||||||
|
bool profileFound = false;
|
||||||
|
for (int attempt = 0; attempt < 5; ++attempt) {
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
if (xmlScreenParser.isProfilePage()) {
|
||||||
|
profileFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QThread::msleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!profileFound) {
|
||||||
|
m_error = "Profile page not detected: " + m_deviceId;
|
||||||
|
qWarning() << m_error;
|
||||||
|
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Парсим данные профиля (первый экран: nombre, apellido, email)
|
||||||
|
const QString nombre = xmlScreenParser.parseProfileNombre();
|
||||||
|
const QString apellido = xmlScreenParser.parseProfileApellido();
|
||||||
|
const QString email = xmlScreenParser.parseProfileEmail();
|
||||||
|
|
||||||
|
// 6. Скроллим вниз чтобы увидеть телефон
|
||||||
|
const int x = device.screenWidth / 2;
|
||||||
|
const int fromY = device.screenHeight * 3 / 4;
|
||||||
|
const int toY = device.screenHeight / 4;
|
||||||
|
AdbUtils::makeSwipe(m_deviceId, x, fromY, x, toY);
|
||||||
|
QThread::msleep(1500);
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
|
||||||
|
const QString phone = xmlScreenParser.parseProfilePhone();
|
||||||
|
|
||||||
|
// Собираем полное имя: "имя фамилия"
|
||||||
|
QString parsedFullName;
|
||||||
|
if (!nombre.isEmpty() && !apellido.isEmpty()) {
|
||||||
|
parsedFullName = nombre + " " + apellido;
|
||||||
|
} else if (!nombre.isEmpty()) {
|
||||||
|
parsedFullName = nombre;
|
||||||
|
} else {
|
||||||
|
parsedFullName = fullName; // fallback с домашнего экрана
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "[Black::GetProfileInfo] nombre:" << nombre
|
||||||
|
<< "apellido:" << apellido
|
||||||
|
<< "email:" << email
|
||||||
|
<< "phone:" << phone
|
||||||
|
<< "fullName:" << parsedFullName;
|
||||||
|
|
||||||
|
// 7. Сохраняем в БД
|
||||||
|
if (!ApplicationDAO::updateProfileInfo(app.id, parsedFullName, phone, email)) {
|
||||||
|
qWarning() << "[Black::GetProfileInfo] Failed to save profile info to DB";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. Создаём bank profile если нет
|
||||||
|
createBankProfileIfNeeded(m_deviceId, m_appCode);
|
||||||
|
|
||||||
|
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Black
|
||||||
27
android/black/GetProfileInfoScript.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "CommonScript.h"
|
||||||
|
|
||||||
|
namespace Black {
|
||||||
|
|
||||||
|
class GetProfileInfoScript final : public CommonScript {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
~GetProfileInfoScript() override;
|
||||||
|
|
||||||
|
explicit GetProfileInfoScript(
|
||||||
|
QString deviceId,
|
||||||
|
QString appCode,
|
||||||
|
QObject *parent = nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void doStart() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QString m_deviceId;
|
||||||
|
const QString m_appCode;
|
||||||
|
QString m_error;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Black
|
||||||
64
android/black/LoginAndCheckAccountsScript.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include "LoginAndCheckAccountsScript.h"
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
#include "adb/AdbUtils.h"
|
||||||
|
#include "dao/ApplicationDAO.h"
|
||||||
|
#include "dao/DeviceDAO.h"
|
||||||
|
#include "AppLogger.h"
|
||||||
|
#include "GetProfileInfoScript.h"
|
||||||
|
|
||||||
|
namespace Black {
|
||||||
|
|
||||||
|
LoginAndCheckAccountsScript::LoginAndCheckAccountsScript(
|
||||||
|
QString deviceId,
|
||||||
|
QString appCode,
|
||||||
|
QObject *parent
|
||||||
|
) : CommonScript(parent),
|
||||||
|
m_deviceId(std::move(deviceId)),
|
||||||
|
m_appCode(std::move(appCode)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
LoginAndCheckAccountsScript::~LoginAndCheckAccountsScript() = default;
|
||||||
|
|
||||||
|
void LoginAndCheckAccountsScript::doStart() {
|
||||||
|
const DeviceInfo device = DeviceDAO::getDeviceById(m_deviceId);
|
||||||
|
const ApplicationInfo app = ApplicationDAO::getApplication(m_deviceId, m_appCode);
|
||||||
|
|
||||||
|
if (device.id.isEmpty() || app.id == -1) {
|
||||||
|
m_error = "Device or app not found: " + m_deviceId + " " + m_appCode;
|
||||||
|
qCritical() << m_error;
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_deviceId, ++m_counter));
|
||||||
|
|
||||||
|
if (!runAppAndGoToHomeScreen(device.id, app.package, app.pinCode, device.screenWidth, device.screenHeight)) {
|
||||||
|
m_error = "Cant open the home screen: " + m_deviceId + " " + m_appCode;
|
||||||
|
qWarning() << m_error;
|
||||||
|
AppLogger::log("black/LoginAndCheck", m_deviceId, m_error,
|
||||||
|
AdbUtils::captureScreenshotBytes(m_deviceId),
|
||||||
|
"FETCH_PROFILE");
|
||||||
|
if (!ApplicationDAO::updatePinCodeStatus(app.id, "no", "Не прошла проверка [дата]")) {
|
||||||
|
qWarning() << "Cant update the pincode: " << m_deviceId << " " << m_appCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdbUtils::tryToKillApplication(m_deviceId, app.package);
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PIN-код прошёл
|
||||||
|
if (!ApplicationDAO::updatePinCodeStatus(app.id, "yes", "")) {
|
||||||
|
qWarning() << "Cant update the pincode: " << m_deviceId << " " << m_appCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем профиль и аккаунты (приложение уже на home screen)
|
||||||
|
GetProfileInfoScript profileScript(m_deviceId, m_appCode);
|
||||||
|
profileScript.start();
|
||||||
|
|
||||||
|
emit finishedWithResult(m_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Black
|
||||||
27
android/black/LoginAndCheckAccountsScript.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "CommonScript.h"
|
||||||
|
|
||||||
|
namespace Black {
|
||||||
|
|
||||||
|
class LoginAndCheckAccountsScript final : public CommonScript {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
~LoginAndCheckAccountsScript() override;
|
||||||
|
|
||||||
|
explicit LoginAndCheckAccountsScript(
|
||||||
|
QString deviceId,
|
||||||
|
QString appCode,
|
||||||
|
QObject *parent = nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void doStart() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QString m_deviceId;
|
||||||
|
const QString m_appCode;
|
||||||
|
QString m_error;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Black
|
||||||
309
android/black/ScreenXmlParser.cpp
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
#include "ScreenXmlParser.h"
|
||||||
|
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
#include <QDomDocument>
|
||||||
|
|
||||||
|
#include "android/xml/Node.h"
|
||||||
|
|
||||||
|
namespace Black {
|
||||||
|
|
||||||
|
static const QRegularExpression boundsRegex(R"(\[([0-9]+),([0-9]+)\]\[([0-9]+),([0-9]+)\])");
|
||||||
|
|
||||||
|
ScreenXmlParser::ScreenXmlParser(QObject *parent) : QObject(parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenXmlParser::~ScreenXmlParser() = default;
|
||||||
|
|
||||||
|
void ScreenXmlParser::parseAndSaveXml(const QString &xml) {
|
||||||
|
QDomDocument doc;
|
||||||
|
doc.setContent(xml);
|
||||||
|
m_xml = doc.documentElement();
|
||||||
|
m_nodes.clear();
|
||||||
|
|
||||||
|
QXmlStreamReader reader(xml);
|
||||||
|
while (!reader.atEnd()) {
|
||||||
|
reader.readNext();
|
||||||
|
if (reader.isStartElement() && reader.name() == u"node") {
|
||||||
|
Node node;
|
||||||
|
if (reader.attributes().hasAttribute("bounds")) {
|
||||||
|
QString bounds = reader.attributes().value("bounds").toString();
|
||||||
|
if (QRegularExpressionMatch match = boundsRegex.match(bounds); match.hasMatch()) {
|
||||||
|
node.setBounds(
|
||||||
|
match.captured(1).toInt(),
|
||||||
|
match.captured(2).toInt(),
|
||||||
|
match.captured(3).toInt(),
|
||||||
|
match.captured(4).toInt()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (reader.attributes().hasAttribute("text")) {
|
||||||
|
node.text = reader.attributes().value("text").toString();
|
||||||
|
}
|
||||||
|
if (reader.attributes().hasAttribute("content-desc")) {
|
||||||
|
node.contentDesc = reader.attributes().value("content-desc").toString();
|
||||||
|
}
|
||||||
|
if (reader.attributes().hasAttribute("class")) {
|
||||||
|
node.className = reader.attributes().value("class").toString();
|
||||||
|
}
|
||||||
|
if (reader.attributes().hasAttribute("clickable")) {
|
||||||
|
node.clickable = reader.attributes().value("clickable").toString() == "true";
|
||||||
|
}
|
||||||
|
if (reader.attributes().hasAttribute("focusable")) {
|
||||||
|
node.focusable = reader.attributes().value("focusable").toString() == "true";
|
||||||
|
}
|
||||||
|
if (reader.attributes().hasAttribute("resource-id")) {
|
||||||
|
node.resourceId = reader.attributes().value("resource-id").toString();
|
||||||
|
}
|
||||||
|
if (reader.attributes().hasAttribute("hint")) {
|
||||||
|
node.hint = reader.attributes().value("hint").toString();
|
||||||
|
}
|
||||||
|
if (reader.attributes().hasAttribute("password")) {
|
||||||
|
node.password = reader.attributes().value("password").toString() == "true";
|
||||||
|
}
|
||||||
|
m_nodes.append(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<Node> &ScreenXmlParser::findAllNodes() const {
|
||||||
|
return m_nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node ScreenXmlParser::findTextNode(const QString &text) {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.text.trimmed() == text) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Node ScreenXmlParser::findNodeByContentDesc(const QString &contentDesc) {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.contentDesc == contentDesc) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Node ScreenXmlParser::findNodeByContentDesc(const QString &contentDesc, bool contains) {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (contains) {
|
||||||
|
if (node.contentDesc.contains(contentDesc)) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (node.contentDesc == contentDesc) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Node ScreenXmlParser::findButtonNode(const QString &text, bool contains) {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (!node.clickable) continue;
|
||||||
|
if (contains) {
|
||||||
|
if (node.text.contains(text) || node.contentDesc.contains(text)) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (node.text.trimmed() == text || node.contentDesc == text) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Node ScreenXmlParser::findFirstEditText() {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.className == "android.widget.EditText") {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScreenXmlParser::isPinCodeScreen() {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.contentDesc.contains(QString::fromUtf8("¿Olvidaste tu PIN?"))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node.contentDesc.contains(QString::fromUtf8("Ingresá tu PIN"))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node ScreenXmlParser::findPinCodeEditText() {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.className == "android.widget.EditText" && node.password) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScreenXmlParser::isHomeScreen() {
|
||||||
|
bool hasSaldo = false;
|
||||||
|
bool hasInicio = false;
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.contentDesc == "Saldo disponible") {
|
||||||
|
hasSaldo = true;
|
||||||
|
}
|
||||||
|
if (node.contentDesc == "Inicio") {
|
||||||
|
hasInicio = true;
|
||||||
|
}
|
||||||
|
if (hasSaldo && hasInicio) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScreenXmlParser::isSideMenu() {
|
||||||
|
bool hasTuInfo = false;
|
||||||
|
bool hasCerrar = false;
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.contentDesc == QString::fromUtf8("Tu Información")) {
|
||||||
|
hasTuInfo = true;
|
||||||
|
}
|
||||||
|
if (node.contentDesc == QString::fromUtf8("Cerrar sesión")) {
|
||||||
|
hasCerrar = true;
|
||||||
|
}
|
||||||
|
if (hasTuInfo && hasCerrar) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node ScreenXmlParser::findHolaButton() {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.clickable && node.contentDesc.startsWith(QString::fromUtf8("¡Hola!"))) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScreenXmlParser::parseUserNameFromHomeScreen() {
|
||||||
|
// content-desc: "¡Hola!\nveronica cintia heredia \nvc"
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.contentDesc.startsWith(QString::fromUtf8("¡Hola!"))) {
|
||||||
|
QStringList lines = node.contentDesc.split('\n');
|
||||||
|
if (lines.size() >= 2) {
|
||||||
|
return lines[1].trimmed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
double ScreenXmlParser::parseBalanceFromHomeScreen() {
|
||||||
|
// Баланс идёт после "Saldo disponible", формат: "$1.857,00" или "$0,00"
|
||||||
|
bool afterSaldo = false;
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.contentDesc == "Saldo disponible") {
|
||||||
|
afterSaldo = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (afterSaldo && node.contentDesc.startsWith("$")) {
|
||||||
|
// "$1.857,00" → "1857.00"
|
||||||
|
QString raw = node.contentDesc.mid(1); // убираем "$"
|
||||||
|
raw.remove('.'); // убираем разделитель тысяч
|
||||||
|
raw.replace(',', '.'); // запятая → точка
|
||||||
|
bool ok = false;
|
||||||
|
double val = raw.toDouble(&ok);
|
||||||
|
if (ok) return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScreenXmlParser::isProfilePage() {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.contentDesc == QString::fromUtf8("Tu información")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScreenXmlParser::parseProfileNombre() {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.hint == "Nombre" && !node.text.isEmpty()) {
|
||||||
|
return node.text.trimmed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScreenXmlParser::parseProfileApellido() {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.hint == "Apellido" && !node.text.isEmpty()) {
|
||||||
|
return node.text.trimmed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScreenXmlParser::parseProfileEmail() {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.hint == "E-mail" && !node.text.isEmpty()) {
|
||||||
|
return node.text.trimmed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScreenXmlParser::parseProfilePhone() {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.hint == QString::fromUtf8("Teléfono celular") && !node.text.isEmpty()) {
|
||||||
|
return node.text.trimmed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScreenXmlParser::isCVUScreen() {
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.contentDesc == "CVU") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ScreenXmlParser::parseCVUNumber() {
|
||||||
|
// CVU номер идёт после content-desc="CVU", это 22-значный номер
|
||||||
|
bool afterCVU = false;
|
||||||
|
for (const Node &node : m_nodes) {
|
||||||
|
if (node.contentDesc == "CVU") {
|
||||||
|
afterCVU = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (afterCVU && !node.contentDesc.isEmpty()) {
|
||||||
|
// Проверяем что это числовая строка (CVU — 22 цифры)
|
||||||
|
QString cvu = node.contentDesc.trimmed();
|
||||||
|
bool allDigits = true;
|
||||||
|
for (const QChar &c : cvu) {
|
||||||
|
if (!c.isDigit()) {
|
||||||
|
allDigits = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allDigits && !cvu.isEmpty()) {
|
||||||
|
return cvu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Black
|
||||||
72
android/black/ScreenXmlParser.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDomElement>
|
||||||
|
#include "android/xml/Node.h"
|
||||||
|
#include "db/AccountInfo.h"
|
||||||
|
|
||||||
|
namespace Black {
|
||||||
|
|
||||||
|
class ScreenXmlParser final : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ScreenXmlParser(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
~ScreenXmlParser() override;
|
||||||
|
|
||||||
|
void parseAndSaveXml(const QString &xml);
|
||||||
|
|
||||||
|
const QList<Node> &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();
|
||||||
|
|
||||||
|
// Определяет экран ввода PIN-кода по content-desc "¿Olvidaste tu PIN?"
|
||||||
|
bool isPinCodeScreen();
|
||||||
|
|
||||||
|
// Находит EditText с password=true для ввода PIN
|
||||||
|
Node findPinCodeEditText();
|
||||||
|
|
||||||
|
bool isHomeScreen();
|
||||||
|
|
||||||
|
// Определяет боковое меню по content-desc "Tu Información" + "Cerrar sesión"
|
||||||
|
bool isSideMenu();
|
||||||
|
|
||||||
|
// Находит кнопку "¡Hola!" (аватар с именем) на домашнем экране
|
||||||
|
Node findHolaButton();
|
||||||
|
|
||||||
|
// Парсит имя пользователя из content-desc "¡Hola!\nимя\nинициалы"
|
||||||
|
QString parseUserNameFromHomeScreen();
|
||||||
|
|
||||||
|
// Парсит баланс с домашнего экрана (content-desc "$0,00" после "Saldo disponible")
|
||||||
|
double parseBalanceFromHomeScreen();
|
||||||
|
|
||||||
|
// Определяет страницу профиля "Tu información"
|
||||||
|
bool isProfilePage();
|
||||||
|
|
||||||
|
// Парсит данные профиля по hint полей
|
||||||
|
QString parseProfileNombre(); // hint="Nombre"
|
||||||
|
QString parseProfileApellido(); // hint="Apellido"
|
||||||
|
QString parseProfileEmail(); // hint="E-mail"
|
||||||
|
QString parseProfilePhone(); // hint="Teléfono celular"
|
||||||
|
|
||||||
|
// Определяет экран CVU (окно поверх домашнего экрана)
|
||||||
|
bool isCVUScreen();
|
||||||
|
|
||||||
|
// Парсит номер CVU (22-значный номер после content-desc="CVU")
|
||||||
|
QString parseCVUNumber();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<Node> m_nodes;
|
||||||
|
QDomElement m_xml;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Black
|
||||||
@ -6,6 +6,7 @@
|
|||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
#include "adb/AdbUtils.h"
|
#include "adb/AdbUtils.h"
|
||||||
|
#include "dao/ApplicationDAO.h"
|
||||||
#include "net/NetworkService.h"
|
#include "net/NetworkService.h"
|
||||||
|
|
||||||
namespace Ozon {
|
namespace Ozon {
|
||||||
@ -289,6 +290,37 @@ void CommonScript::updateTransactionData(
|
|||||||
thread->start();
|
thread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommonScript::createBankProfileIfNeeded(const QString &deviceId, const QString &appCode) {
|
||||||
|
const ApplicationInfo app = ApplicationDAO::getApplication(deviceId, appCode);
|
||||||
|
if (!app.bankProfileId.isEmpty()) {
|
||||||
|
qDebug() << "[Ozon] bankProfileId already exists:" << app.bankProfileId;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QMap<QString, int> currencyCodes = {
|
||||||
|
{"RUB", 643}, {"USD", 840}, {"KRW", 410}, {"AZN", 944}
|
||||||
|
};
|
||||||
|
const int currencyCode = currencyCodes.value(app.currency.toUpper(), 643);
|
||||||
|
const QStringList parts = app.fullName.split(' ', Qt::SkipEmptyParts);
|
||||||
|
|
||||||
|
QJsonObject profileBody;
|
||||||
|
profileBody["first_name"] = parts.value(0);
|
||||||
|
profileBody["middle_name"] = parts.size() >= 3 ? parts.value(1) : QString("");
|
||||||
|
profileBody["last_name"] = parts.size() >= 3 ? parts.value(2) : parts.value(1);
|
||||||
|
profileBody["bank_name"] = appCode;
|
||||||
|
profileBody["phone_number"] = app.phone.simplified().remove(' ');
|
||||||
|
profileBody["balance"] = QString::number(qRound64(app.amount * 100));
|
||||||
|
profileBody["state"] = (app.status == "active") ? "enabled" : "disabled";
|
||||||
|
profileBody["currency"] = currencyCode;
|
||||||
|
|
||||||
|
NetworkService ns;
|
||||||
|
ns.setDeviceId(deviceId);
|
||||||
|
ns.setPayload(QJsonDocument(profileBody).toJson());
|
||||||
|
ns.addExtra("app_id", app.id);
|
||||||
|
ns.postBankProfile();
|
||||||
|
qDebug() << "[Ozon] createBankProfileIfNeeded: postBankProfile done";
|
||||||
|
}
|
||||||
|
|
||||||
void CommonScript::stop() {
|
void CommonScript::stop() {
|
||||||
m_running = false;
|
m_running = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,6 +57,9 @@ protected:
|
|||||||
const QString &deviceId, int width, int height
|
const QString &deviceId, int width, int height
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Создаёт bank_profile на сервере если ещё не создан
|
||||||
|
void createBankProfileIfNeeded(const QString &deviceId, const QString &appCode);
|
||||||
|
|
||||||
bool m_running = true;
|
bool m_running = true;
|
||||||
ScreenXmlParser xmlScreenParser;
|
ScreenXmlParser xmlScreenParser;
|
||||||
int m_counter = 0;
|
int m_counter = 0;
|
||||||
|
|||||||
@ -53,6 +53,10 @@ void LoginAndCheckAccountsScript::doStart() {
|
|||||||
if (!ApplicationDAO::updatePinCodeStatus(app.id, "yes", "")) {
|
if (!ApplicationDAO::updatePinCodeStatus(app.id, "yes", "")) {
|
||||||
qWarning() << "Cant update the pincode: " << m_deviceId << " " << m_appCode;
|
qWarning() << "Cant update the pincode: " << m_deviceId << " " << m_appCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Создаём bank profile если ещё не создан
|
||||||
|
createBankProfileIfNeeded(m_deviceId, m_appCode);
|
||||||
|
|
||||||
if (goToAllProducts(device.id, device.screenWidth, device.screenHeight)) {
|
if (goToAllProducts(device.id, device.screenWidth, device.screenHeight)) {
|
||||||
QList<QPair<AccountInfo, Node> > accounts = xmlScreenParser.parseAccountsInfo();
|
QList<QPair<AccountInfo, Node> > accounts = xmlScreenParser.parseAccountsInfo();
|
||||||
for (auto &[account, node]: accounts) {
|
for (auto &[account, node]: accounts) {
|
||||||
|
|||||||
BIN
assets/black/accounts.png
Normal file
|
After Width: | Height: | Size: 160 KiB |
123
assets/black/accounts.xml
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||||
|
<hierarchy rotation="0">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="android:id/content" class="android.widget.FrameLayout"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="2" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="true" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,136][1080,2337]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[26,1256][1054,2337]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[89,1309][991,2059]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node NAF="true" index="0" text="" resource-id=""
|
||||||
|
class="android.view.View" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[928,1309][991,1372]" drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Datos de tu cuenta"
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[89,1372][478,1437]" drawing-order="0" hint=""/>
|
||||||
|
<node index="2" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="CVU" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[89,1516][165,1571]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="3" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="0000177501057000175004"
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[89,1579][492,1626]" drawing-order="0" hint=""/>
|
||||||
|
<node NAF="true" index="4" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[938,1545][991,1598]" drawing-order="0" hint=""/>
|
||||||
|
<node index="5" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Alias"
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[89,1653][173,1708]" drawing-order="0" hint=""/>
|
||||||
|
<node index="6" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="27335723320.black"
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[89,1716][378,1763]" drawing-order="0" hint=""/>
|
||||||
|
<node NAF="true" index="7" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[938,1682][991,1734]" drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="1" text="" resource-id="" class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar" content-desc="Compartir datos"
|
||||||
|
checkable="false" checked="false" clickable="true" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[47,2143][1033,2316]" drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="1" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Cerrar" checkable="false" checked="false"
|
||||||
|
clickable="true" enabled="true" focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</hierarchy>
|
||||||
BIN
assets/black/home_screen.png
Normal file
|
After Width: | Height: | Size: 246 KiB |
248
assets/black/home_screen.xml
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||||
|
<hierarchy rotation="0">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="android:id/content" class="android.widget.FrameLayout"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="2" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.ScrollView"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="true" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar"
|
||||||
|
content-desc="¡Hola! veronica cintia heredia vc"
|
||||||
|
checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,158][1080,347]" drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="1" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Tu wallet"
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[107,465][414,570]" drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="2" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Saldo disponible"
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[107,596][370,643]" drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node NAF="true" index="3" text="" resource-id=""
|
||||||
|
class="android.view.View" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[440,495][484,539]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="4" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Tu CVU"
|
||||||
|
checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[783,484][974,597]" drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="5" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="$0,00"
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[107,643][316,761]" drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="6" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Accesos rápidos"
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[53,1116][378,1179]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="7" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="QR Personal" checkable="false" checked="false"
|
||||||
|
clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[53,1218][315,1488]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="8" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="Enviar a CBU o alias" checkable="false"
|
||||||
|
checked="false" clickable="true" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[409,1218][671,1536]" drawing-order="0" hint=""/>
|
||||||
|
<node index="9" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="Solicitar con link" checkable="false"
|
||||||
|
checked="false" clickable="true" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[765,1218][1028,1536]" drawing-order="0" hint=""/>
|
||||||
|
<node index="10" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Tu actividad"
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[53,1667][297,1730]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="11" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Ver más"
|
||||||
|
checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[802,1667][1028,1730]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="12" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,1756][1080,2229]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,1756][1080,2229]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar"
|
||||||
|
content-desc="Transferencia 21 de febrero de 2026 - 09:39 $-1.857, 00"
|
||||||
|
checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[0,1756][1080,1880]" drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="1" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar"
|
||||||
|
content-desc="Transferencia 21 de febrero de 2026 - 09:38 $-123, 45"
|
||||||
|
checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[0,1880][1080,2003]" drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
<node index="2" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar"
|
||||||
|
content-desc="Transferencia externa de NOELIA ISABEL LEZCANO 21 de febrero de 2026 - 09:35 $123, 45"
|
||||||
|
checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[0,2003][1080,2179]" drawing-order="0"
|
||||||
|
hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node index="13" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Tarjetas"
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[53,2255][215,2318]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="14" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Ver más"
|
||||||
|
checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[802,2255][1028,2318]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="15" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar"
|
||||||
|
content-desc="No hay tarjetas en tu billetera"
|
||||||
|
checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[302,2344][778,2391]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node NAF="true" index="1" text="" resource-id="" class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="true" enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[456,2106][624,2274]" drawing-order="0" hint=""/>
|
||||||
|
<node index="2" text="" resource-id="" class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar" content-desc="Inicio" checkable="false"
|
||||||
|
checked="false" clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[88,2229][162,2350]" drawing-order="0" hint=""/>
|
||||||
|
<node index="3" text="" resource-id="" class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar" content-desc="Enviar" checkable="false"
|
||||||
|
checked="false" clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[251,2229][336,2350]" drawing-order="0" hint=""/>
|
||||||
|
<node index="4" text="" resource-id="" class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar" content-desc="Recibir" checkable="false"
|
||||||
|
checked="false" clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[729,2229][824,2350]" drawing-order="0" hint=""/>
|
||||||
|
<node index="5" text="" resource-id="" class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar" content-desc="Pagar" checkable="false"
|
||||||
|
checked="false" clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[913,2229][992,2350]" drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</hierarchy>
|
||||||
BIN
assets/black/pin_code.png
Normal file
|
After Width: | Height: | Size: 127 KiB |
97
assets/black/pin_code.xml
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||||
|
<hierarchy rotation="0">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="android:id/content" class="android.widget.FrameLayout"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="2" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="true" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,283]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Registrate" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[42,173][315,246]" drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="1" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,283][1080,2018]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar"
|
||||||
|
content-desc="Ingresá tu código PIN Es un código de seguridad que te va a permitir operar con más seguridad Ingresá tu PIN"
|
||||||
|
checkable="false" checked="false" clickable="true" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,283][1080,1396]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node NAF="true" index="1" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="true" password="false"
|
||||||
|
selected="false" bounds="[263,1449][818,1514]" drawing-order="0" hint=""/>
|
||||||
|
<node index="2" text="" resource-id="" class="android.widget.EditText"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="true"
|
||||||
|
focused="true" scrollable="false" long-clickable="false" password="true"
|
||||||
|
selected="false" bounds="[263,1449][818,1556]" drawing-order="0" hint=""/>
|
||||||
|
<node index="3" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="¿Olvidaste tu PIN?"
|
||||||
|
checkable="false" checked="false" clickable="true" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[357,1687][723,1750]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="4" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar"
|
||||||
|
content-desc="Tengo un código de verificación" checkable="false"
|
||||||
|
checked="false" clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[218,1803][862,1866]" drawing-order="0" hint=""/>
|
||||||
|
<node index="5" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Cerrar sesión"
|
||||||
|
checkable="false" checked="false" clickable="true" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[435,1918][645,1966]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</hierarchy>
|
||||||
BIN
assets/black/profile_page.png
Normal file
|
After Width: | Height: | Size: 139 KiB |
184
assets/black/profile_page.xml
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||||
|
<hierarchy rotation="0">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="android:id/content" class="android.widget.FrameLayout"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="2" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="true" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,283]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.Button"
|
||||||
|
package="app.blackwallet.ar" content-desc="Atrás" checkable="false"
|
||||||
|
checked="false" clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,136][147,283]" drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Tu información"
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[189,173][581,246]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="1" text="" resource-id="" class="android.widget.ScrollView"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="true" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,283][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="vc" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[496,494][584,597]" drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="veronica cintia heredia "
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[205,716][875,800]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="2" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="12 de febrero 1989"
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[348,826][732,882]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="3" text="" resource-id="" class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[66,951][118,1043]" drawing-order="0" hint=""/>
|
||||||
|
<node index="4" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Tu CVU" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[171,950][287,997]" drawing-order="0" hint=""/>
|
||||||
|
<node index="5" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="0000177501057000175004"
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[171,997][606,1044]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node NAF="true" index="6" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[962,934][1041,1060]" drawing-order="0" hint=""/>
|
||||||
|
<node index="7" text="" resource-id="" class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[66,1106][118,1198]" drawing-order="0" hint=""/>
|
||||||
|
<node index="8" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Tu Alias" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[171,1105][294,1152]" drawing-order="0" hint=""/>
|
||||||
|
<node index="9" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="27335723320.black"
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[171,1152][481,1199]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node NAF="true" index="10" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[883,1089][962,1215]" drawing-order="0" hint=""/>
|
||||||
|
<node NAF="true" index="11" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[962,1089][1041,1215]" drawing-order="0" hint=""/>
|
||||||
|
<node index="12" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Editá tu información"
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[79,1359][449,1414]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="13" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[79,1467][1001,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="veronica cintia " resource-id=""
|
||||||
|
class="android.view.View" package="app.blackwallet.ar" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[79,1467][1001,1635]" drawing-order="0" hint="Nombre"/>
|
||||||
|
<node index="1" text="heredia " resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[79,1714][1001,1882]"
|
||||||
|
drawing-order="0" hint="Apellido"/>
|
||||||
|
<node index="2" text="Fiorinogriselda4@gmail.com" resource-id=""
|
||||||
|
class="android.view.View" package="app.blackwallet.ar" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[79,1960][1001,2128]" drawing-order="0" hint="E-mail"/>
|
||||||
|
<node index="3" text="12/2/1989" resource-id=""
|
||||||
|
class="android.widget.EditText" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[79,2207][1001,2375]" drawing-order="0"
|
||||||
|
hint="Fecha de nacimiento"/>
|
||||||
|
<node index="4" text="" resource-id="" class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[875,2228][1001,2354]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="5" text="" resource-id="" class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][0,0]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</hierarchy>
|
||||||
BIN
assets/black/profile_page_2.png
Normal file
|
After Width: | Height: | Size: 112 KiB |
142
assets/black/profile_page_2.xml
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||||
|
<hierarchy rotation="0">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="android:id/content" class="android.widget.FrameLayout"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="2" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="true" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,283]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.Button"
|
||||||
|
package="app.blackwallet.ar" content-desc="Atrás" checkable="false"
|
||||||
|
checked="false" clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,136][147,283]" drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Tu información"
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[189,173][581,246]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="1" text="" resource-id="" class="android.widget.ScrollView"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="true" focused="false"
|
||||||
|
scrollable="true" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,283][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="Editá tu información"
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[79,283][449,305]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[79,358][1001,2295]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="veronica cintia " resource-id=""
|
||||||
|
class="android.view.View" package="app.blackwallet.ar" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[79,358][1001,526]" drawing-order="0" hint="Nombre"/>
|
||||||
|
<node index="1" text="heredia " resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[79,605][1001,773]"
|
||||||
|
drawing-order="0" hint="Apellido"/>
|
||||||
|
<node index="2" text="Fiorinogriselda4@gmail.com" resource-id=""
|
||||||
|
class="android.view.View" package="app.blackwallet.ar" content-desc=""
|
||||||
|
checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[79,851][1001,1019]" drawing-order="0" hint="E-mail"/>
|
||||||
|
<node index="3" text="12/2/1989" resource-id=""
|
||||||
|
class="android.widget.EditText" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[79,1098][1001,1266]" drawing-order="0"
|
||||||
|
hint="Fecha de nacimiento"/>
|
||||||
|
<node index="4" text="" resource-id="" class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[875,1119][1001,1245]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="5" text="" resource-id="" class="android.widget.Button"
|
||||||
|
package="app.blackwallet.ar" content-desc="Género Femenino"
|
||||||
|
checkable="false" checked="false" clickable="true" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[79,1345][1001,1513]" drawing-order="0" hint=""/>
|
||||||
|
<node index="6" text="3543554877" resource-id=""
|
||||||
|
class="android.widget.EditText" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="true"
|
||||||
|
enabled="true" focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[79,1592][1001,1760]" drawing-order="0"
|
||||||
|
hint="Teléfono celular"/>
|
||||||
|
<node index="7" text="********" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[79,1838][1001,2006]"
|
||||||
|
drawing-order="0" hint="Contraseña"/>
|
||||||
|
<node index="8" text="" resource-id="" class="android.widget.ImageView"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[875,1856][1001,1989]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="9" text="" resource-id="" class="android.widget.Button"
|
||||||
|
package="app.blackwallet.ar" content-desc="Guardar cambios"
|
||||||
|
checkable="false" checked="false" clickable="true" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[79,2111][1001,2243]" drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</hierarchy>
|
||||||
BIN
assets/black/side_menu.png
Normal file
|
After Width: | Height: | Size: 173 KiB |
169
assets/black/side_menu.xml
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||||
|
<hierarchy rotation="0">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="android:id/content" class="android.widget.FrameLayout"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false" clickable="false"
|
||||||
|
enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="2" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="true" focused="true" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="1" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
|
||||||
|
focusable="false" focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="false" enabled="true" focusable="false" focused="false"
|
||||||
|
scrollable="false" long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false" password="false"
|
||||||
|
selected="false" bounds="[0,0][1080,2400]" drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,2400]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar"
|
||||||
|
content-desc="vc veronica cintia heredia " checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,0][1080,1856]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node NAF="true" index="0" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[42,178][134,238]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="Tu Información" checkable="false"
|
||||||
|
checked="false" clickable="true" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[42,685][1038,763]" drawing-order="0" hint=""/>
|
||||||
|
<node index="2" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="Notificaciones" checkable="false"
|
||||||
|
checked="false" clickable="true" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[42,845][1038,923]" drawing-order="0" hint=""/>
|
||||||
|
<node index="3" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="Ajustes y preferencias" checkable="false"
|
||||||
|
checked="false" clickable="true" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[42,1005][1038,1084]" drawing-order="0" hint=""/>
|
||||||
|
<node index="4" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="Ayuda" checkable="false" checked="false"
|
||||||
|
clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[42,1165][1038,1244]" drawing-order="0" hint=""/>
|
||||||
|
<node index="5" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="Invitar a Black Wallet" checkable="false"
|
||||||
|
checked="false" clickable="true" enabled="true"
|
||||||
|
focusable="true" focused="false" scrollable="false"
|
||||||
|
long-clickable="false" password="false" selected="false"
|
||||||
|
bounds="[42,1325][1038,1404]" drawing-order="0" hint=""/>
|
||||||
|
<node index="6" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="Cerrar sesión" checkable="false" checked="false"
|
||||||
|
clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[42,1669][1038,1748]" drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
<node index="1" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,1856][1080,1882]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="2" text="" resource-id="" class="android.view.View"
|
||||||
|
package="app.blackwallet.ar" content-desc="" checkable="false"
|
||||||
|
checked="false" clickable="false" enabled="true" focusable="false"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[0,1882][1080,2223]"
|
||||||
|
drawing-order="0" hint="">
|
||||||
|
<node index="0" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="Inicio" checkable="false" checked="false"
|
||||||
|
clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false" bounds="[88,2024][162,2145]"
|
||||||
|
drawing-order="0" hint=""/>
|
||||||
|
<node index="1" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="Enviar" checkable="false" checked="false"
|
||||||
|
clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[251,2024][336,2145]" drawing-order="0" hint=""/>
|
||||||
|
<node NAF="true" index="2" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="" checkable="false" checked="false"
|
||||||
|
clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[456,1898][624,2066]" drawing-order="0" hint=""/>
|
||||||
|
<node index="3" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="Recibir" checkable="false" checked="false"
|
||||||
|
clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[729,2024][824,2145]" drawing-order="0" hint=""/>
|
||||||
|
<node index="4" text="" resource-id=""
|
||||||
|
class="android.widget.ImageView" package="app.blackwallet.ar"
|
||||||
|
content-desc="Pagar" checkable="false" checked="false"
|
||||||
|
clickable="true" enabled="true" focusable="true"
|
||||||
|
focused="false" scrollable="false" long-clickable="false"
|
||||||
|
password="false" selected="false"
|
||||||
|
bounds="[913,2024][992,2145]" drawing-order="0" hint=""/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</hierarchy>
|
||||||
@ -1,5 +1,5 @@
|
|||||||
[apps]
|
[apps]
|
||||||
list=ozon
|
list=ozon, black
|
||||||
|
|
||||||
[common]
|
[common]
|
||||||
currencies=USD, KRW, AZN, RUB
|
currencies=USD, KRW, AZN, RUB
|
||||||
@ -25,6 +25,11 @@ paymentsGet=http://localhost:9999/api/v1/payments
|
|||||||
transactionInsert=http://localhost:9999/api/v1/transaction/insert
|
transactionInsert=http://localhost:9999/api/v1/transaction/insert
|
||||||
transactionUpdate=http://localhost:9999/api/v1/transaction/update
|
transactionUpdate=http://localhost:9999/api/v1/transaction/update
|
||||||
|
|
||||||
|
[black]
|
||||||
|
android_package_name=app.blackwallet.ar
|
||||||
|
currency=USD
|
||||||
|
name=Black
|
||||||
|
|
||||||
[ozon]
|
[ozon]
|
||||||
android_package_name=ru.ozon.fintech.finance
|
android_package_name=ru.ozon.fintech.finance
|
||||||
currency=RUB
|
currency=RUB
|
||||||
|
|||||||
@ -128,6 +128,7 @@ void DatabaseManager::initSchema() {
|
|||||||
install TEXT DEFAULT 'no',
|
install TEXT DEFAULT 'no',
|
||||||
comment TEXT,
|
comment TEXT,
|
||||||
phone TEXT DEFAULT '',
|
phone TEXT DEFAULT '',
|
||||||
|
email TEXT DEFAULT '',
|
||||||
full_name TEXT DEFAULT '',
|
full_name TEXT DEFAULT '',
|
||||||
bank_profile_id TEXT DEFAULT '',
|
bank_profile_id TEXT DEFAULT '',
|
||||||
currency TEXT DEFAULT '',
|
currency TEXT DEFAULT '',
|
||||||
@ -223,6 +224,15 @@ void DatabaseManager::initSchema() {
|
|||||||
q.exec("PRAGMA user_version = 1");
|
q.exec("PRAGMA user_version = 1");
|
||||||
qDebug() << "[DB] Migration 1 applied";
|
qDebug() << "[DB] Migration 1 applied";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Версия 2: добавляем email в applications ─────────────────────────────
|
||||||
|
if (version < 2) {
|
||||||
|
db.transaction();
|
||||||
|
q.exec("ALTER TABLE applications ADD COLUMN email TEXT DEFAULT ''");
|
||||||
|
db.commit();
|
||||||
|
q.exec("PRAGMA user_version = 2");
|
||||||
|
qDebug() << "[DB] Migration 2 applied";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseManager::closeConnection() {
|
void DatabaseManager::closeConnection() {
|
||||||
|
|||||||
@ -10,13 +10,14 @@ bool AccountDAO::upsertAccount(const AccountInfo &info) {
|
|||||||
QSqlQuery query(DatabaseManager::instance().database());
|
QSqlQuery query(DatabaseManager::instance().database());
|
||||||
|
|
||||||
query.prepare(R"(
|
query.prepare(R"(
|
||||||
INSERT INTO accounts (device_id, app_code, last_numbers, amount, update_time, status, description, currency)
|
INSERT INTO accounts (device_id, app_code, last_numbers, card_number, amount, update_time, status, description, currency)
|
||||||
VALUES (:device_id, :app_code, :last_numbers, :amount, :update_time, :status, :description, :currency)
|
VALUES (:device_id, :app_code, :last_numbers, :card_number, :amount, :update_time, :status, :description, :currency)
|
||||||
ON CONFLICT(device_id, app_code, last_numbers)
|
ON CONFLICT(device_id, app_code, last_numbers)
|
||||||
DO UPDATE SET
|
DO UPDATE SET
|
||||||
amount = excluded.amount,
|
amount = excluded.amount,
|
||||||
update_time = excluded.update_time,
|
update_time = excluded.update_time,
|
||||||
last_numbers = excluded.last_numbers,
|
last_numbers = excluded.last_numbers,
|
||||||
|
card_number = excluded.card_number,
|
||||||
status = excluded.status,
|
status = excluded.status,
|
||||||
description = excluded.description,
|
description = excluded.description,
|
||||||
currency = excluded.currency
|
currency = excluded.currency
|
||||||
@ -25,6 +26,7 @@ bool AccountDAO::upsertAccount(const AccountInfo &info) {
|
|||||||
query.bindValue(":device_id", info.deviceId);
|
query.bindValue(":device_id", info.deviceId);
|
||||||
query.bindValue(":app_code", info.appCode);
|
query.bindValue(":app_code", info.appCode);
|
||||||
query.bindValue(":last_numbers", info.lastNumbers);
|
query.bindValue(":last_numbers", info.lastNumbers);
|
||||||
|
query.bindValue(":card_number", info.cardNumber);
|
||||||
query.bindValue(":currency", info.currency);
|
query.bindValue(":currency", info.currency);
|
||||||
query.bindValue(":description", info.description);
|
query.bindValue(":description", info.description);
|
||||||
query.bindValue(":amount", info.amount);
|
query.bindValue(":amount", info.amount);
|
||||||
|
|||||||
@ -128,6 +128,7 @@ ApplicationInfo parseApplication(const QSqlQuery &query) {
|
|||||||
app.install = query.value("install").toString() == "yes";
|
app.install = query.value("install").toString() == "yes";
|
||||||
app.pinCodeChecked = query.value("pin_code_checked").toString() == "yes";
|
app.pinCodeChecked = query.value("pin_code_checked").toString() == "yes";
|
||||||
app.phone = query.value("phone").toString();
|
app.phone = query.value("phone").toString();
|
||||||
|
app.email = query.value("email").toString();
|
||||||
app.fullName = query.value("full_name").toString();
|
app.fullName = query.value("full_name").toString();
|
||||||
app.bankProfileId = query.value("bank_profile_id").toString();
|
app.bankProfileId = query.value("bank_profile_id").toString();
|
||||||
app.currency = query.value("currency").toString();
|
app.currency = query.value("currency").toString();
|
||||||
@ -139,7 +140,7 @@ ApplicationInfo ApplicationDAO::getApplication(const QString &deviceId, const QS
|
|||||||
QSqlQuery query(DatabaseManager::instance().database());
|
QSqlQuery query(DatabaseManager::instance().database());
|
||||||
|
|
||||||
query.prepare(R"(
|
query.prepare(R"(
|
||||||
SELECT id, device_id, pin_code, code, name, package, status, comment, install, pin_code_checked, phone, full_name, bank_profile_id, currency, amount
|
SELECT id, device_id, pin_code, code, name, package, status, comment, install, pin_code_checked, phone, email, full_name, bank_profile_id, currency, amount
|
||||||
FROM applications
|
FROM applications
|
||||||
WHERE device_id = :device_id AND code = :code
|
WHERE device_id = :device_id AND code = :code
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
@ -164,7 +165,7 @@ QList<ApplicationInfo> ApplicationDAO::getApplicationsByDeviceId(const QString &
|
|||||||
QList<ApplicationInfo> list;
|
QList<ApplicationInfo> list;
|
||||||
|
|
||||||
query.prepare(R"(
|
query.prepare(R"(
|
||||||
SELECT id, device_id, pin_code, code, name, package, status, comment, install, pin_code_checked, phone, full_name, bank_profile_id, currency, amount
|
SELECT id, device_id, pin_code, code, name, package, status, comment, install, pin_code_checked, phone, email, full_name, bank_profile_id, currency, amount
|
||||||
FROM applications
|
FROM applications
|
||||||
WHERE device_id = :device_id AND install = 'yes'
|
WHERE device_id = :device_id AND install = 'yes'
|
||||||
)");
|
)");
|
||||||
@ -185,19 +186,21 @@ QList<ApplicationInfo> ApplicationDAO::getApplicationsByDeviceId(const QString &
|
|||||||
bool ApplicationDAO::updateProfileInfo(
|
bool ApplicationDAO::updateProfileInfo(
|
||||||
const int &appId,
|
const int &appId,
|
||||||
const QString &fullName,
|
const QString &fullName,
|
||||||
const QString &phone
|
const QString &phone,
|
||||||
|
const QString &email
|
||||||
) {
|
) {
|
||||||
QSqlQuery query(DatabaseManager::instance().database());
|
QSqlQuery query(DatabaseManager::instance().database());
|
||||||
|
|
||||||
query.prepare(R"(
|
query.prepare(R"(
|
||||||
UPDATE applications
|
UPDATE applications
|
||||||
SET full_name = :full_name, phone = :phone
|
SET full_name = :full_name, phone = :phone, email = :email
|
||||||
WHERE id = :id
|
WHERE id = :id
|
||||||
)");
|
)");
|
||||||
|
|
||||||
query.bindValue(":id", appId);
|
query.bindValue(":id", appId);
|
||||||
query.bindValue(":full_name", fullName);
|
query.bindValue(":full_name", fullName);
|
||||||
query.bindValue(":phone", phone);
|
query.bindValue(":phone", phone);
|
||||||
|
query.bindValue(":email", email);
|
||||||
|
|
||||||
if (!query.exec()) {
|
if (!query.exec()) {
|
||||||
qWarning() << "Ошибка при обновлении профиля приложения:" << query.lastError().text();
|
qWarning() << "Ошибка при обновлении профиля приложения:" << query.lastError().text();
|
||||||
|
|||||||
@ -24,7 +24,8 @@ public:
|
|||||||
[[nodiscard]] static bool updateProfileInfo(
|
[[nodiscard]] static bool updateProfileInfo(
|
||||||
const int &appId,
|
const int &appId,
|
||||||
const QString &fullName,
|
const QString &fullName,
|
||||||
const QString &phone
|
const QString &phone,
|
||||||
|
const QString &email = ""
|
||||||
);
|
);
|
||||||
|
|
||||||
[[nodiscard]] static bool updateBankProfileId(int appId, const QString &bankProfileId);
|
[[nodiscard]] static bool updateBankProfileId(int appId, const QString &bankProfileId);
|
||||||
|
|||||||
BIN
images/black_icon.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
@ -45,6 +45,7 @@ public:
|
|||||||
QString hint;
|
QString hint;
|
||||||
bool clickable = false;
|
bool clickable = false;
|
||||||
bool focusable = false;
|
bool focusable = false;
|
||||||
|
bool password = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_x1 = -1, m_y1 = -1, m_x2 = -1, m_y2 = -1;
|
int m_x1 = -1, m_y1 = -1, m_x2 = -1, m_y2 = -1;
|
||||||
|
|||||||
@ -16,6 +16,7 @@ struct ApplicationInfo {
|
|||||||
QString status;
|
QString status;
|
||||||
QString comment;
|
QString comment;
|
||||||
QString phone;
|
QString phone;
|
||||||
|
QString email;
|
||||||
QString fullName;
|
QString fullName;
|
||||||
QString bankProfileId;
|
QString bankProfileId;
|
||||||
QString currency;
|
QString currency;
|
||||||
|
|||||||
@ -17,6 +17,9 @@
|
|||||||
#include "ozon/GetCardInfoScript.h"
|
#include "ozon/GetCardInfoScript.h"
|
||||||
#include "ozon/GetLastTransactionsScript.h"
|
#include "ozon/GetLastTransactionsScript.h"
|
||||||
#include "toss/LoginAndCheckAccountsTossScript.h"
|
#include "toss/LoginAndCheckAccountsTossScript.h"
|
||||||
|
#include "black/LoginAndCheckAccountsScript.h"
|
||||||
|
#include "black/GetProfileInfoScript.h"
|
||||||
|
#include "black/GetCardInfoScript.h"
|
||||||
#include "dao/AccountDAO.h"
|
#include "dao/AccountDAO.h"
|
||||||
#include "dao/ApplicationDAO.h"
|
#include "dao/ApplicationDAO.h"
|
||||||
#include "bank/TransactionWindow.h"
|
#include "bank/TransactionWindow.h"
|
||||||
@ -238,6 +241,80 @@ AccountSettingsWindow::AccountSettingsWindow(
|
|||||||
layout->addLayout(ozonRow);
|
layout->addLayout(ozonRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_applicationInfo.code == "black" && m_applicationInfo.pinCodeChecked) {
|
||||||
|
QHBoxLayout *blackRow = new QHBoxLayout();
|
||||||
|
|
||||||
|
QPushButton *profileButton = new QPushButton("Обновить профиль");
|
||||||
|
profileButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
||||||
|
profileButton->setStyleSheet("background-color: #1565C0; color: white;");
|
||||||
|
QObject::connect(profileButton, &QPushButton::clicked, [this]() {
|
||||||
|
QMessageBox msgBox(this);
|
||||||
|
msgBox.setWindowTitle(tr("Обновить профиль?"));
|
||||||
|
msgBox.setText(
|
||||||
|
"Запустится скрипт получения профиля из " + m_applicationInfo.name +
|
||||||
|
". Окно с настройками закроется.");
|
||||||
|
QPushButton *runBtn = msgBox.addButton(tr("Запустить"), QMessageBox::AcceptRole);
|
||||||
|
QPushButton *cancelBtn = msgBox.addButton(tr("Отмена"), QMessageBox::RejectRole);
|
||||||
|
msgBox.setDefaultButton(cancelBtn);
|
||||||
|
msgBox.setModal(true);
|
||||||
|
msgBox.exec();
|
||||||
|
if (msgBox.clickedButton() == runBtn) {
|
||||||
|
startGetProfileInfo(m_applicationInfo.code);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QPushButton *cardButton = new QPushButton("Проверить аккаунты");
|
||||||
|
cardButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
||||||
|
cardButton->setStyleSheet("background-color: #1565C0; color: white;");
|
||||||
|
QObject::connect(cardButton, &QPushButton::clicked, [this]() {
|
||||||
|
QMessageBox msgBox(this);
|
||||||
|
msgBox.setWindowTitle(tr("Проверить аккаунты?"));
|
||||||
|
msgBox.setText(
|
||||||
|
"Запустится скрипт получения данных карты из " + m_applicationInfo.name +
|
||||||
|
". Окно с настройками закроется.");
|
||||||
|
QPushButton *runBtn = msgBox.addButton(tr("Запустить"), QMessageBox::AcceptRole);
|
||||||
|
QPushButton *cancelBtn = msgBox.addButton(tr("Отмена"), QMessageBox::RejectRole);
|
||||||
|
msgBox.setDefaultButton(cancelBtn);
|
||||||
|
msgBox.setModal(true);
|
||||||
|
msgBox.exec();
|
||||||
|
if (msgBox.clickedButton() == runBtn) {
|
||||||
|
startGetCardInfo(m_applicationInfo.code);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QPushButton *transactionsButton = new QPushButton("Проверить транзакции");
|
||||||
|
transactionsButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
||||||
|
transactionsButton->setStyleSheet("background-color: #1565C0; color: white;");
|
||||||
|
QObject::connect(transactionsButton, &QPushButton::clicked, [this]() {
|
||||||
|
QMessageBox msgBox(this);
|
||||||
|
msgBox.setWindowTitle(tr("Проверить транзакции?"));
|
||||||
|
msgBox.setText(
|
||||||
|
"Запустится скрипт получения последних транзакций из " + m_applicationInfo.name +
|
||||||
|
". Окно с настройками закроется.");
|
||||||
|
QPushButton *runBtn = msgBox.addButton(tr("За 24 часа"), QMessageBox::AcceptRole);
|
||||||
|
QPushButton *last5Btn = msgBox.addButton(tr("Последние 5"), QMessageBox::AcceptRole);
|
||||||
|
QPushButton *cancelBtn = msgBox.addButton(tr("Отмена"), QMessageBox::RejectRole);
|
||||||
|
msgBox.setDefaultButton(cancelBtn);
|
||||||
|
msgBox.setModal(true);
|
||||||
|
msgBox.exec();
|
||||||
|
if (msgBox.clickedButton() == runBtn) {
|
||||||
|
startGetLastTransactions(m_applicationInfo.code);
|
||||||
|
close();
|
||||||
|
} else if (msgBox.clickedButton() == last5Btn) {
|
||||||
|
startGetLastTransactions(m_applicationInfo.code, 5);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
blackRow->addWidget(profileButton);
|
||||||
|
blackRow->addWidget(cardButton);
|
||||||
|
blackRow->addWidget(transactionsButton);
|
||||||
|
blackRow->addStretch();
|
||||||
|
layout->addLayout(blackRow);
|
||||||
|
}
|
||||||
|
|
||||||
layout->addWidget(new QLabel("Счета"));
|
layout->addWidget(new QLabel("Счета"));
|
||||||
QTableWidget *tableWidget = new QTableWidget(this);
|
QTableWidget *tableWidget = new QTableWidget(this);
|
||||||
tableWidget->setSelectionMode(QAbstractItemView::NoSelection);
|
tableWidget->setSelectionMode(QAbstractItemView::NoSelection);
|
||||||
@ -315,6 +392,13 @@ void AccountSettingsWindow::startCheckPinCode(const QString &appCode) {
|
|||||||
connect(worker, &Ozon::LoginAndCheckAccountsScript::finished, thread, &QThread::quit);
|
connect(worker, &Ozon::LoginAndCheckAccountsScript::finished, thread, &QThread::quit);
|
||||||
connect(worker, &Ozon::LoginAndCheckAccountsScript::finished, worker, &QObject::deleteLater);
|
connect(worker, &Ozon::LoginAndCheckAccountsScript::finished, worker, &QObject::deleteLater);
|
||||||
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
||||||
|
} else if (appCode == "black") {
|
||||||
|
auto *worker = new Black::LoginAndCheckAccountsScript(m_deviceId, appCode, nullptr);
|
||||||
|
worker->moveToThread(thread);
|
||||||
|
connect(thread, &QThread::started, worker, &Black::LoginAndCheckAccountsScript::start);
|
||||||
|
connect(worker, &Black::LoginAndCheckAccountsScript::finished, thread, &QThread::quit);
|
||||||
|
connect(worker, &Black::LoginAndCheckAccountsScript::finished, worker, &QObject::deleteLater);
|
||||||
|
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
||||||
} else {
|
} else {
|
||||||
thread->deleteLater();
|
thread->deleteLater();
|
||||||
return;
|
return;
|
||||||
@ -324,21 +408,32 @@ void AccountSettingsWindow::startCheckPinCode(const QString &appCode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AccountSettingsWindow::startGetProfileInfo(const QString &appCode) {
|
void AccountSettingsWindow::startGetProfileInfo(const QString &appCode) {
|
||||||
if (appCode != "ozon") return;
|
|
||||||
|
|
||||||
QThread *thread = new QThread(nullptr);
|
QThread *thread = new QThread(nullptr);
|
||||||
|
|
||||||
|
if (appCode == "ozon") {
|
||||||
auto *worker = new Ozon::GetProfileInfoScript(m_deviceId, appCode, nullptr);
|
auto *worker = new Ozon::GetProfileInfoScript(m_deviceId, appCode, nullptr);
|
||||||
worker->moveToThread(thread);
|
worker->moveToThread(thread);
|
||||||
connect(thread, &QThread::started, worker, &Ozon::GetProfileInfoScript::start);
|
connect(thread, &QThread::started, worker, &Ozon::GetProfileInfoScript::start);
|
||||||
connect(worker, &Ozon::GetProfileInfoScript::finished, thread, &QThread::quit);
|
connect(worker, &Ozon::GetProfileInfoScript::finished, thread, &QThread::quit);
|
||||||
connect(worker, &Ozon::GetProfileInfoScript::finished, worker, &QObject::deleteLater);
|
connect(worker, &Ozon::GetProfileInfoScript::finished, worker, &QObject::deleteLater);
|
||||||
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
||||||
|
} else if (appCode == "black") {
|
||||||
|
auto *worker = new Black::GetProfileInfoScript(m_deviceId, appCode, nullptr);
|
||||||
|
worker->moveToThread(thread);
|
||||||
|
connect(thread, &QThread::started, worker, &Black::GetProfileInfoScript::start);
|
||||||
|
connect(worker, &Black::GetProfileInfoScript::finished, thread, &QThread::quit);
|
||||||
|
connect(worker, &Black::GetProfileInfoScript::finished, worker, &QObject::deleteLater);
|
||||||
|
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
||||||
|
} else {
|
||||||
|
thread->deleteLater();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
thread->start();
|
thread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountSettingsWindow::startGetCardInfo(const QString &appCode) {
|
void AccountSettingsWindow::startGetCardInfo(const QString &appCode) {
|
||||||
if (appCode != "ozon") return;
|
if (appCode == "ozon") {
|
||||||
|
|
||||||
QThread *thread = new QThread(nullptr);
|
QThread *thread = new QThread(nullptr);
|
||||||
auto *worker = new Ozon::GetCardInfoScript(m_deviceId, appCode, "", nullptr);
|
auto *worker = new Ozon::GetCardInfoScript(m_deviceId, appCode, "", nullptr);
|
||||||
worker->moveToThread(thread);
|
worker->moveToThread(thread);
|
||||||
@ -347,6 +442,16 @@ void AccountSettingsWindow::startGetCardInfo(const QString &appCode) {
|
|||||||
connect(worker, &Ozon::GetCardInfoScript::finished, worker, &QObject::deleteLater);
|
connect(worker, &Ozon::GetCardInfoScript::finished, worker, &QObject::deleteLater);
|
||||||
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
||||||
thread->start();
|
thread->start();
|
||||||
|
} else if (appCode == "black") {
|
||||||
|
QThread *thread = new QThread(nullptr);
|
||||||
|
auto *worker = new Black::GetCardInfoScript(m_deviceId, appCode, nullptr);
|
||||||
|
worker->moveToThread(thread);
|
||||||
|
connect(thread, &QThread::started, worker, &Black::GetCardInfoScript::start);
|
||||||
|
connect(worker, &Black::GetCardInfoScript::finished, thread, &QThread::quit);
|
||||||
|
connect(worker, &Black::GetCardInfoScript::finished, worker, &QObject::deleteLater);
|
||||||
|
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
||||||
|
thread->start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountSettingsWindow::startGetLastTransactions(const QString &appCode, int maxCount) {
|
void AccountSettingsWindow::startGetLastTransactions(const QString &appCode, int maxCount) {
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
#include "toss/LoginAndCheckAccountsTossScript.h"
|
#include "toss/LoginAndCheckAccountsTossScript.h"
|
||||||
#include "widget/common/CollapsibleSection.h"
|
#include "widget/common/CollapsibleSection.h"
|
||||||
#include "ziraat/LoginAndCheckAccountsZiraatScript.h"
|
#include "ziraat/LoginAndCheckAccountsZiraatScript.h"
|
||||||
|
#include "black/LoginAndCheckAccountsScript.h"
|
||||||
|
|
||||||
QTableWidgetItem *BankSettingsWindow::createTableWidget(const QString &text) {
|
QTableWidgetItem *BankSettingsWindow::createTableWidget(const QString &text) {
|
||||||
QTableWidgetItem *item = new QTableWidgetItem(text);
|
QTableWidgetItem *item = new QTableWidgetItem(text);
|
||||||
@ -87,6 +88,13 @@ void BankSettingsWindow::startCheckPinCode(const QString &appCode) {
|
|||||||
connect(worker, &LoginAndCheckAccountsTossScript::finished, thread, &QThread::quit);
|
connect(worker, &LoginAndCheckAccountsTossScript::finished, thread, &QThread::quit);
|
||||||
connect(worker, &LoginAndCheckAccountsTossScript::finished, worker, &QObject::deleteLater);
|
connect(worker, &LoginAndCheckAccountsTossScript::finished, worker, &QObject::deleteLater);
|
||||||
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
||||||
|
} else if (appCode == "black") {
|
||||||
|
auto *worker = new Black::LoginAndCheckAccountsScript(m_deviceId, appCode, nullptr);
|
||||||
|
worker->moveToThread(thread);
|
||||||
|
connect(thread, &QThread::started, worker, &Black::LoginAndCheckAccountsScript::start);
|
||||||
|
connect(worker, &Black::LoginAndCheckAccountsScript::finished, thread, &QThread::quit);
|
||||||
|
connect(worker, &Black::LoginAndCheckAccountsScript::finished, worker, &QObject::deleteLater);
|
||||||
|
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
||||||
} else {
|
} else {
|
||||||
thread->deleteLater();
|
thread->deleteLater();
|
||||||
return;
|
return;
|
||||||
|
|||||||