chore: minor ui fixes

This commit is contained in:
vladimir.kuznetsov 2025-02-22 14:42:09 +07:00
parent 6a424e9858
commit d19017f87b
16 changed files with 90 additions and 29 deletions

View file

@ -202,3 +202,13 @@ QQmlApplicationEngine *AmneziaApplication::qmlEngine() const
{ {
return m_engine; return m_engine;
} }
QNetworkAccessManager *AmneziaApplication::networkManager()
{
return m_nam;
}
QClipboard *AmneziaApplication::getClipboard()
{
return this->clipboard();
}

View file

@ -11,6 +11,7 @@
#else #else
#include <QApplication> #include <QApplication>
#endif #endif
#include <QClipboard>
#include "core/controllers/coreController.h" #include "core/controllers/coreController.h"
#include "settings.h" #include "settings.h"
@ -41,10 +42,8 @@ public:
#endif #endif
QQmlApplicationEngine *qmlEngine() const; QQmlApplicationEngine *qmlEngine() const;
QNetworkAccessManager *manager() QNetworkAccessManager *networkManager();
{ QClipboard *getClipboard();
return m_nam;
}
private: private:
QQmlApplicationEngine *m_engine {}; QQmlApplicationEngine *m_engine {};

View file

@ -24,6 +24,7 @@ namespace apiDefs
constexpr QLatin1String apiConfig("api_config"); constexpr QLatin1String apiConfig("api_config");
constexpr QLatin1String stackType("stack_type"); constexpr QLatin1String stackType("stack_type");
constexpr QLatin1String serviceType("service_type");
constexpr QLatin1String vpnKey("vpn_key"); constexpr QLatin1String vpnKey("vpn_key");

View file

@ -27,15 +27,19 @@ apiDefs::ConfigType apiUtils::getConfigType(const QJsonObject &serverConfigObjec
case apiDefs::ConfigSource::Telegram: { case apiDefs::ConfigSource::Telegram: {
}; };
case apiDefs::ConfigSource::AmneziaGateway: { case apiDefs::ConfigSource::AmneziaGateway: {
constexpr QLatin1String premium("prem"); constexpr QLatin1String stackPremium("prem");
constexpr QLatin1String free("free"); constexpr QLatin1String stackFree("free");
constexpr QLatin1String servicePremium("amnezia-premium");
constexpr QLatin1String serviceFree("amnezia-free");
auto apiConfigObject = serverConfigObject.value(apiDefs::key::apiConfig).toObject(); auto apiConfigObject = serverConfigObject.value(apiDefs::key::apiConfig).toObject();
auto stackType = apiConfigObject.value(apiDefs::key::stackType).toString(); auto stackType = apiConfigObject.value(apiDefs::key::stackType).toString();
auto serviceType = apiConfigObject.value(apiDefs::key::serviceType).toString();
if (stackType == premium) { if (serviceType == servicePremium || stackType == stackPremium) {
return apiDefs::ConfigType::AmneziaPremiumV2; return apiDefs::ConfigType::AmneziaPremiumV2;
} else if (stackType == free) { } else if (serviceType == serviceFree || stackType == stackFree) {
return apiDefs::ConfigType::AmneziaFreeV3; return apiDefs::ConfigType::AmneziaFreeV3;
} }
} }

View file

@ -47,7 +47,7 @@ ErrorCode GatewayController::get(const QString &endpoint, QByteArray &responseBo
request.setUrl(QString(endpoint).arg(m_gatewayEndpoint)); request.setUrl(QString(endpoint).arg(m_gatewayEndpoint));
QNetworkReply *reply; QNetworkReply *reply;
reply = amnApp->manager()->get(request); reply = amnApp->networkManager()->get(request);
QEventLoop wait; QEventLoop wait;
QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit); QObject::connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
@ -61,7 +61,7 @@ ErrorCode GatewayController::get(const QString &endpoint, QByteArray &responseBo
if (sslErrors.isEmpty() && shouldBypassProxy(reply, responseBody, false)) { if (sslErrors.isEmpty() && shouldBypassProxy(reply, responseBody, false)) {
auto requestFunction = [&request, &responseBody](const QString &url) { auto requestFunction = [&request, &responseBody](const QString &url) {
request.setUrl(url); request.setUrl(url);
return amnApp->manager()->get(request); return amnApp->networkManager()->get(request);
}; };
auto replyProcessingFunction = [&responseBody, &reply, &sslErrors, this](QNetworkReply *nestedReply, auto replyProcessingFunction = [&responseBody, &reply, &sslErrors, this](QNetworkReply *nestedReply,
@ -137,7 +137,7 @@ ErrorCode GatewayController::post(const QString &endpoint, const QJsonObject api
requestBody[configKey::keyPayload] = QString(encryptedKeyPayload.toBase64()); requestBody[configKey::keyPayload] = QString(encryptedKeyPayload.toBase64());
requestBody[configKey::apiPayload] = QString(encryptedApiPayload.toBase64()); requestBody[configKey::apiPayload] = QString(encryptedApiPayload.toBase64());
QNetworkReply *reply = amnApp->manager()->post(request, QJsonDocument(requestBody).toJson()); QNetworkReply *reply = amnApp->networkManager()->post(request, QJsonDocument(requestBody).toJson());
QEventLoop wait; QEventLoop wait;
connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit); connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
@ -151,7 +151,7 @@ ErrorCode GatewayController::post(const QString &endpoint, const QJsonObject api
if (sslErrors.isEmpty() && shouldBypassProxy(reply, encryptedResponseBody, false)) { if (sslErrors.isEmpty() && shouldBypassProxy(reply, encryptedResponseBody, false)) {
auto requestFunction = [&request, &encryptedResponseBody, &requestBody](const QString &url) { auto requestFunction = [&request, &encryptedResponseBody, &requestBody](const QString &url) {
request.setUrl(url); request.setUrl(url);
return amnApp->manager()->post(request, QJsonDocument(requestBody).toJson()); return amnApp->networkManager()->post(request, QJsonDocument(requestBody).toJson());
}; };
auto replyProcessingFunction = [&encryptedResponseBody, &reply, &sslErrors, &key, &iv, &salt, auto replyProcessingFunction = [&encryptedResponseBody, &reply, &sslErrors, &key, &iv, &salt,
@ -205,7 +205,7 @@ QStringList GatewayController::getProxyUrls()
for (const auto &proxyStorageUrl : proxyStorageUrl) { for (const auto &proxyStorageUrl : proxyStorageUrl) {
request.setUrl(proxyStorageUrl); request.setUrl(proxyStorageUrl);
reply = amnApp->manager()->get(request); reply = amnApp->networkManager()->get(request);
connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit); connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; }); connect(reply, &QNetworkReply::sslErrors, [this, &sslErrors](const QList<QSslError> &errors) { sslErrors = errors; });
@ -256,6 +256,8 @@ QStringList GatewayController::getProxyUrls()
bool GatewayController::shouldBypassProxy(QNetworkReply *reply, const QByteArray &responseBody, bool checkEncryption, const QByteArray &key, bool GatewayController::shouldBypassProxy(QNetworkReply *reply, const QByteArray &responseBody, bool checkEncryption, const QByteArray &key,
const QByteArray &iv, const QByteArray &salt) const QByteArray &iv, const QByteArray &salt)
{ {
qDebug() << reply->error();
qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (reply->error() == QNetworkReply::NetworkError::OperationCanceledError || reply->error() == QNetworkReply::NetworkError::TimeoutError) { if (reply->error() == QNetworkReply::NetworkError::OperationCanceledError || reply->error() == QNetworkReply::NetworkError::TimeoutError) {
qDebug() << "Timeout occurred"; qDebug() << "Timeout occurred";
return true; return true;

View file

@ -1,13 +1,13 @@
#include "apiConfigsController.h" #include "apiConfigsController.h"
#include <QEventLoop> #include <QEventLoop>
#include <QClipboard>
#include "amnezia_application.h" #include "amnezia_application.h"
#include "configurators/wireguard_configurator.h" #include "configurators/wireguard_configurator.h"
#include "core/api/apiDefs.h" #include "core/api/apiDefs.h"
#include "core/api/apiUtils.h" #include "core/api/apiUtils.h"
#include "core/controllers/gatewayController.h" #include "core/controllers/gatewayController.h"
#include "core/networkUtilities.h"
#include "core/qrCodeUtils.h" #include "core/qrCodeUtils.h"
#include "ui/controllers/systemController.h" #include "ui/controllers/systemController.h"
#include "version.h" #include "version.h"
@ -76,7 +76,6 @@ bool ApiConfigsController::exportNativeConfig(const QString &serverCountryCode,
apiPayload[configKey::serverCountryCode] = serverCountryCode; apiPayload[configKey::serverCountryCode] = serverCountryCode;
apiPayload[configKey::serviceType] = apiConfigObject.value(configKey::serviceType); apiPayload[configKey::serviceType] = apiConfigObject.value(configKey::serviceType);
apiPayload[configKey::authData] = serverConfigObject.value(configKey::authData); apiPayload[configKey::authData] = serverConfigObject.value(configKey::authData);
apiPayload[configKey::uuid] = m_settings->getInstallationUuid(true);
QByteArray responseBody; QByteArray responseBody;
ErrorCode errorCode = gatewayController.post(QString("%1v1/native_config"), apiPayload, responseBody); ErrorCode errorCode = gatewayController.post(QString("%1v1/native_config"), apiPayload, responseBody);
@ -124,6 +123,7 @@ void ApiConfigsController::prepareVpnKeyExport()
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject(); auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
auto vpnKey = apiConfigObject.value(apiDefs::key::vpnKey).toString(); auto vpnKey = apiConfigObject.value(apiDefs::key::vpnKey).toString();
m_vpnKey = vpnKey;
vpnKey.replace("vpn://", ""); vpnKey.replace("vpn://", "");
@ -132,6 +132,12 @@ void ApiConfigsController::prepareVpnKeyExport()
emit vpnKeyExportReady(); emit vpnKeyExportReady();
} }
void ApiConfigsController::copyVpnKeyToClipboard()
{
auto clipboard = amnApp->getClipboard();
clipboard->setText(m_vpnKey);
}
bool ApiConfigsController::fillAvailableServices() bool ApiConfigsController::fillAvailableServices()
{ {
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs); GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs);
@ -288,7 +294,7 @@ bool ApiConfigsController::updateServiceFromTelegram(const int serverIndex)
QByteArray requestBody = QJsonDocument(apiPayload).toJson(); QByteArray requestBody = QJsonDocument(apiPayload).toJson();
QNetworkReply *reply = amnApp->manager()->post(request, requestBody); QNetworkReply *reply = amnApp->networkManager()->post(request, requestBody);
QEventLoop wait; QEventLoop wait;
connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit); connect(reply, &QNetworkReply::finished, &wait, &QEventLoop::quit);
@ -477,3 +483,8 @@ int ApiConfigsController::getQrCodesCount()
{ {
return m_qrCodes.size(); return m_qrCodes.size();
} }
QString ApiConfigsController::getVpnKey()
{
return m_vpnKey;
}

View file

@ -16,12 +16,14 @@ public:
Q_PROPERTY(QList<QString> qrCodes READ getQrCodes NOTIFY vpnKeyExportReady) Q_PROPERTY(QList<QString> qrCodes READ getQrCodes NOTIFY vpnKeyExportReady)
Q_PROPERTY(int qrCodesCount READ getQrCodesCount NOTIFY vpnKeyExportReady) Q_PROPERTY(int qrCodesCount READ getQrCodesCount NOTIFY vpnKeyExportReady)
Q_PROPERTY(QString vpnKey READ getVpnKey NOTIFY vpnKeyExportReady)
public slots: public slots:
bool exportNativeConfig(const QString &serverCountryCode, const QString &fileName); bool exportNativeConfig(const QString &serverCountryCode, const QString &fileName);
bool revokeNativeConfig(const QString &serverCountryCode); bool revokeNativeConfig(const QString &serverCountryCode);
// bool exportVpnKey(const QString &fileName); // bool exportVpnKey(const QString &fileName);
void prepareVpnKeyExport(); void prepareVpnKeyExport();
void copyVpnKeyToClipboard();
bool fillAvailableServices(); bool fillAvailableServices();
bool importServiceFromGateway(); bool importServiceFromGateway();
@ -58,8 +60,10 @@ private:
QList<QString> getQrCodes(); QList<QString> getQrCodes();
int getQrCodesCount(); int getQrCodesCount();
QString getVpnKey();
QList<QString> m_qrCodes; QList<QString> m_qrCodes;
QString m_vpnKey;
QSharedPointer<ServersModel> m_serversModel; QSharedPointer<ServersModel> m_serversModel;
QSharedPointer<ApiServicesModel> m_apiServicesModel; QSharedPointer<ApiServicesModel> m_apiServicesModel;

View file

@ -1,5 +1,8 @@
#include "apiSettingsController.h" #include "apiSettingsController.h"
#include <QEventLoop>
#include <QTimer>
#include "core/api/apiUtils.h" #include "core/api/apiUtils.h"
#include "core/controllers/gatewayController.h" #include "core/controllers/gatewayController.h"
@ -35,8 +38,14 @@ ApiSettingsController::~ApiSettingsController()
{ {
} }
bool ApiSettingsController::getAccountInfo() bool ApiSettingsController::getAccountInfo(bool reload)
{ {
if (reload) {
QEventLoop wait;
QTimer::singleShot(1000, &wait, &QEventLoop::quit);
wait.exec();
}
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), requestTimeoutMsecs); GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), requestTimeoutMsecs);
auto processedIndex = m_serversModel->getProcessedServerIndex(); auto processedIndex = m_serversModel->getProcessedServerIndex();
@ -62,6 +71,10 @@ bool ApiSettingsController::getAccountInfo()
QJsonObject accountInfo = QJsonDocument::fromJson(responseBody).object(); QJsonObject accountInfo = QJsonDocument::fromJson(responseBody).object();
m_apiAccountInfoModel->updateModel(accountInfo, serverConfig); m_apiAccountInfoModel->updateModel(accountInfo, serverConfig);
if (reload) {
updateApiCountryModel();
}
return true; return true;
} }

View file

@ -17,7 +17,7 @@ public:
~ApiSettingsController(); ~ApiSettingsController();
public slots: public slots:
bool getAccountInfo(); bool getAccountInfo(bool reload);
void updateApiCountryModel(); void updateApiCountryModel();
signals: signals:

View file

@ -8,6 +8,8 @@
namespace namespace
{ {
Logger logger("ApiCountryModel"); Logger logger("ApiCountryModel");
constexpr QLatin1String countryConfig("country_config");
} }
ApiCountryModel::ApiCountryModel(QObject *parent) : QAbstractListModel(parent) ApiCountryModel::ApiCountryModel(QObject *parent) : QAbstractListModel(parent)
@ -27,7 +29,7 @@ QVariant ApiCountryModel::data(const QModelIndex &index, int role) const
CountryInfo countryInfo = m_countries.at(index.row()); CountryInfo countryInfo = m_countries.at(index.row());
IssuedConfigInfo issuedConfigInfo = m_issuedConfigs.value(countryInfo.countryCode); IssuedConfigInfo issuedConfigInfo = m_issuedConfigs.value(countryInfo.countryCode);
bool isIssued = !issuedConfigInfo.lastDownloaded.isEmpty(); bool isIssued = issuedConfigInfo.sourceType == countryConfig;
switch (role) { switch (role) {
case CountryCodeRole: { case CountryCodeRole: {
@ -73,10 +75,15 @@ void ApiCountryModel::updateIssuedConfigsInfo(const QJsonArray &issuedConfigs)
{ {
beginResetModel(); beginResetModel();
m_issuedConfigs.clear();
for (int i = 0; i < issuedConfigs.size(); i++) { for (int i = 0; i < issuedConfigs.size(); i++) {
IssuedConfigInfo issuedConfigInfo; IssuedConfigInfo issuedConfigInfo;
QJsonObject issuedConfigObject = issuedConfigs.at(i).toObject(); QJsonObject issuedConfigObject = issuedConfigs.at(i).toObject();
if (issuedConfigObject.value(apiDefs::key::sourceType).toString() != countryConfig) {
continue;
}
issuedConfigInfo.installationUuid = issuedConfigObject.value(apiDefs::key::installationUuid).toString(); issuedConfigInfo.installationUuid = issuedConfigObject.value(apiDefs::key::installationUuid).toString();
issuedConfigInfo.workerLastUpdated = issuedConfigObject.value(apiDefs::key::workerLastUpdated).toString(); issuedConfigInfo.workerLastUpdated = issuedConfigObject.value(apiDefs::key::workerLastUpdated).toString();
issuedConfigInfo.lastDownloaded = issuedConfigObject.value(apiDefs::key::lastDownloaded).toString(); issuedConfigInfo.lastDownloaded = issuedConfigObject.value(apiDefs::key::lastDownloaded).toString();

View file

@ -116,7 +116,7 @@ ListView {
PageController.goToPage(PageEnum.PageSettingsApiAvailableCountries) PageController.goToPage(PageEnum.PageSettingsApiAvailableCountries)
} else { } else {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
let result = ApiSettingsController.getAccountInfo() let result = ApiSettingsController.getAccountInfo(false)
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
if (!result) { if (!result) {
return return

View file

@ -303,7 +303,7 @@ PageType {
PageController.goToPage(PageEnum.PageSettingsApiAvailableCountries) PageController.goToPage(PageEnum.PageSettingsApiAvailableCountries)
} else { } else {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
let result = ApiSettingsController.getAccountInfo() let result = ApiSettingsController.getAccountInfo(false)
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
if (!result) { if (!result) {
return return

View file

@ -93,7 +93,7 @@ PageType {
actionButtonFunction: function() { actionButtonFunction: function() {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
let result = ApiSettingsController.getAccountInfo() let result = ApiSettingsController.getAccountInfo(false)
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
if (!result) { if (!result) {
return return

View file

@ -54,7 +54,6 @@ PageType {
width: listView.width width: listView.width
LabelWithButtonType { LabelWithButtonType {
id: telegramButton
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 6 Layout.topMargin: 6
@ -67,8 +66,9 @@ PageType {
moreOptionsDrawer.countryName = countryName moreOptionsDrawer.countryName = countryName
moreOptionsDrawer.countryCode = countryCode moreOptionsDrawer.countryCode = countryCode
moreOptionsDrawer.openTriggered() moreOptionsDrawer.openTriggered()
} else {
issueConfig(countryCode)
} }
issueConfig(countryCode)
} }
} }
@ -166,11 +166,10 @@ PageType {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
let result = ApiConfigsController.exportNativeConfig(countryCode, fileName) let result = ApiConfigsController.exportNativeConfig(countryCode, fileName)
if (result) { if (result) {
ApiSettingsController.getAccountInfo() ApiSettingsController.getAccountInfo(true)
} }
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
if (result) { if (result) {
PageController.showNotificationMessage(qsTr("Config file saved")) PageController.showNotificationMessage(qsTr("Config file saved"))
} }
@ -181,7 +180,7 @@ PageType {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
let result = ApiConfigsController.revokeNativeConfig(countryCode) let result = ApiConfigsController.revokeNativeConfig(countryCode)
if (result) { if (result) {
ApiSettingsController.getAccountInfo() ApiSettingsController.getAccountInfo(true)
} }
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
@ -202,6 +201,7 @@ PageType {
} else { } else {
revokeConfig(countryCode) revokeConfig(countryCode)
} }
moreOptionsDrawer.closeTriggered()
} }
var noButtonFunction = function() { var noButtonFunction = function() {
} }

View file

@ -128,7 +128,17 @@ PageType {
width: listView.width width: listView.width
spacing: 0 spacing: 0
Connections {
target: ApiAccountInfoModel
function onModelReset() {
delegateItem.rightText = ApiAccountInfoModel.data(contentKey)
}
}
LabelWithImageType { LabelWithImageType {
id: delegateItem
Layout.fillWidth: true Layout.fillWidth: true
Layout.margins: 16 Layout.margins: 16
@ -290,7 +300,7 @@ PageType {
} else { } else {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
if (ApiConfigsController.deactivateDevice()) { if (ApiConfigsController.deactivateDevice()) {
ApiSettingsController.getAccountInfo() ApiSettingsController.getAccountInfo(true)
} }
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
} }

View file

@ -96,7 +96,7 @@ PageType {
if (ServersModel.getProcessedServerData("isServerFromGatewayApi")) { if (ServersModel.getProcessedServerData("isServerFromGatewayApi")) {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
let result = ApiSettingsController.getAccountInfo() let result = ApiSettingsController.getAccountInfo(false)
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
if (!result) { if (!result) {
return return