diff --git a/client/core/controllers/apiController.cpp b/client/core/controllers/apiController.cpp index 34fb30a0..fab91408 100644 --- a/client/core/controllers/apiController.cpp +++ b/client/core/controllers/apiController.cpp @@ -213,21 +213,6 @@ void ApiController::updateServerConfigFromApi(const QString &installationUuid, c } } -ErrorCode ApiController::getAccountInfo(const QString &userCountryCode, const QString &serviceType, const QJsonObject &authData, - QByteArray &responseBody) -{ - GatewayController gatewayController(m_gatewayEndpoint, m_isDevEnvironment, requestTimeoutMsecs); - - QJsonObject apiPayload; - apiPayload[configKey::userCountryCode] = userCountryCode; - apiPayload[configKey::serviceType] = serviceType; - apiPayload[configKey::authData] = authData; - - ErrorCode errorCode = gatewayController.post(QString("%1v1/account_info"), apiPayload, responseBody); - - return errorCode; -} - ErrorCode ApiController::getServicesList(QByteArray &responseBody) { GatewayController gatewayController(m_gatewayEndpoint, m_isDevEnvironment, requestTimeoutMsecs); diff --git a/client/core/controllers/apiController.h b/client/core/controllers/apiController.h index ab34bde4..367c89e4 100644 --- a/client/core/controllers/apiController.h +++ b/client/core/controllers/apiController.h @@ -18,9 +18,6 @@ public: public slots: void updateServerConfigFromApi(const QString &installationUuid, const int serverIndex, QJsonObject serverConfig); - - ErrorCode getAccountInfo(const QString &userCountryCode, const QString &serviceType, const QJsonObject &authData, - QByteArray &responseBody); ErrorCode getServicesList(QByteArray &responseBody); ErrorCode getConfigForService(const QString &installationUuid, const QString &userCountryCode, const QString &serviceType, const QString &protocol, const QString &serverCountryCode, const QJsonObject &authData, diff --git a/client/ui/controllers/api/apiConfigsController.cpp b/client/ui/controllers/api/apiConfigsController.cpp index 62ccebb8..f791c7e8 100644 --- a/client/ui/controllers/api/apiConfigsController.cpp +++ b/client/ui/controllers/api/apiConfigsController.cpp @@ -48,8 +48,13 @@ ApiConfigsController::ApiConfigsController(const QSharedPointer &s { } -void ApiConfigsController::exportNativeConfig(const QString &serverCountryCode, const QString &fileName) +bool ApiConfigsController::exportNativeConfig(const QString &serverCountryCode, const QString &fileName) { + if (fileName.isEmpty()) { + emit errorOccurred(ErrorCode::PermissionsError); + return false; + } + GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs); auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex()); @@ -67,14 +72,16 @@ void ApiConfigsController::exportNativeConfig(const QString &serverCountryCode, QByteArray responseBody; ErrorCode errorCode = gatewayController.post(QString("%1v1/native_config"), apiPayload, responseBody); - // // if (errorCode != ErrorCode::NoError) { - - // // } + if (errorCode != ErrorCode::NoError) { + emit errorOccurred(errorCode); + return false; + } QJsonObject jsonConfig = QJsonDocument::fromJson(responseBody).object(); QString nativeConfig = jsonConfig.value(configKey::config).toString(); SystemController::saveFile(fileName, nativeConfig); + return true; } ApiConfigsController::ApiPayloadData ApiConfigsController::generateApiPayloadData(const QString &protocol) diff --git a/client/ui/controllers/api/apiConfigsController.h b/client/ui/controllers/api/apiConfigsController.h index 8f3249a7..861bc176 100644 --- a/client/ui/controllers/api/apiConfigsController.h +++ b/client/ui/controllers/api/apiConfigsController.h @@ -11,10 +11,13 @@ class ApiConfigsController : public QObject Q_OBJECT public: ApiConfigsController(const QSharedPointer &serversModel, const std::shared_ptr &settings, - QObject *parent = nullptr); + QObject *parent = nullptr); public slots: - void exportNativeConfig(const QString &serverCountryCode, const QString &fileName); + bool exportNativeConfig(const QString &serverCountryCode, const QString &fileName); + +signals: + void errorOccurred(ErrorCode errorCode); private: struct ApiPayloadData diff --git a/client/ui/controllers/api/apiSettingsController.cpp b/client/ui/controllers/api/apiSettingsController.cpp index 00620d07..0bebf19e 100644 --- a/client/ui/controllers/api/apiSettingsController.cpp +++ b/client/ui/controllers/api/apiSettingsController.cpp @@ -1,5 +1,6 @@ #include "apiSettingsController.h" +#include "core/api/apiUtils.h" #include "core/controllers/gatewayController.h" namespace @@ -49,10 +50,13 @@ bool ApiSettingsController::getAccountInfo() apiPayload[configKey::authData] = authData; QByteArray responseBody; - ErrorCode errorCode = gatewayController.post(QString("%1v1/account_info"), apiPayload, responseBody); - if (errorCode != ErrorCode::NoError) { - // emit errorOccured(errorCode); - return false; + + if (apiUtils::getConfigType(serverConfig) == apiDefs::ConfigType::AmneziaPremiumV2) { + ErrorCode errorCode = gatewayController.post(QString("%1v1/account_info"), apiPayload, responseBody); + if (errorCode != ErrorCode::NoError) { + emit errorOccurred(errorCode); + return false; + } } QJsonObject accountInfo = QJsonDocument::fromJson(responseBody).object(); diff --git a/client/ui/controllers/api/apiSettingsController.h b/client/ui/controllers/api/apiSettingsController.h index 32aa1673..ae9d9126 100644 --- a/client/ui/controllers/api/apiSettingsController.h +++ b/client/ui/controllers/api/apiSettingsController.h @@ -20,6 +20,9 @@ public slots: bool getAccountInfo(); void updateApiCountryModel(); +signals: + void errorOccurred(ErrorCode errorCode); + private: QSharedPointer m_serversModel; QSharedPointer m_apiAccountInfoModel; diff --git a/client/ui/models/api/apiAccountInfoModel.cpp b/client/ui/models/api/apiAccountInfoModel.cpp index 36923491..254097bc 100644 --- a/client/ui/models/api/apiAccountInfoModel.cpp +++ b/client/ui/models/api/apiAccountInfoModel.cpp @@ -12,9 +12,6 @@ namespace namespace configKey { constexpr char availableCountries[] = "available_countries"; - // constexpr char serverCountryCode[] = "server_country_code"; - // constexpr char serverCountryName[] = "server_country_name"; - // constexpr char lastUpdated[] = "last_updated"; constexpr char activeDeviceCount[] = "active_device_count"; constexpr char maxDeviceCount[] = "max_device_count"; constexpr char subscriptionEndDate[] = "subscription_end_date"; @@ -38,12 +35,23 @@ QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const switch (role) { case SubscriptionStatusRole: { + if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) { + return tr("Active"); + } + return apiUtils::isSubscriptionExpired(m_accountInfoData.subscriptionEndDate) ? tr("Inactive") : tr("Active"); } case EndDateRole: { + if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) { + return ""; + } + return QDateTime::fromString(m_accountInfoData.subscriptionEndDate, Qt::ISODate).toLocalTime().toString("d MMM yyyy"); } case ConnectedDevicesRole: { + if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) { + return ""; + } return tr("%1 out of %2").arg(m_accountInfoData.activeDeviceCount).arg(m_accountInfoData.maxDeviceCount); } case ServiceDescriptionRole: { @@ -55,6 +63,9 @@ QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const "more. YouTube is not included in the free plan."); } } + case IsComponentVisibleRole: { + return m_accountInfoData.configType == apiDefs::ConfigType::AmneziaPremiumV2; + } } return QVariant(); @@ -67,15 +78,6 @@ void ApiAccountInfoModel::updateModel(const QJsonObject &accountInfoObject, cons AccountInfoData accountInfoData; m_availableCountries = accountInfoObject.value(configKey::availableCountries).toArray(); - // for (const auto &country : availableCountries) { - // auto countryObject = country.toObject(); - // CountryInfo countryInfo; - // countryInfo.serverCountryCode = countryObject.value(configKey::serverCountryCode).toString(); - // countryInfo.serverCountryName = countryObject.value(configKey::serverCountryName).toString(); - // countryInfo.lastUpdated = countryObject.value(configKey::lastUpdated).toString(); - - // accountInfoData.AvailableCountries.push_back(countryInfo); - // } accountInfoData.activeDeviceCount = accountInfoObject.value(configKey::activeDeviceCount).toInt(); accountInfoData.maxDeviceCount = accountInfoObject.value(configKey::maxDeviceCount).toInt(); @@ -106,6 +108,16 @@ QJsonArray ApiAccountInfoModel::getAvailableCountries() return m_availableCountries; } +QString ApiAccountInfoModel::getTelegramBotLink() +{ + if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) { + return tr("amnezia_free_support_bot"); + } else if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaPremiumV2) { + return tr("amnezia_premium_support_bot"); + } + return ""; +} + QHash ApiAccountInfoModel::roleNames() const { QHash roles; @@ -113,6 +125,7 @@ QHash ApiAccountInfoModel::roleNames() const roles[EndDateRole] = "endDate"; roles[ConnectedDevicesRole] = "connectedDevices"; roles[ServiceDescriptionRole] = "serviceDescription"; + roles[IsComponentVisibleRole] = "isComponentVisible"; return roles; } diff --git a/client/ui/models/api/apiAccountInfoModel.h b/client/ui/models/api/apiAccountInfoModel.h index 66d283da..9dfdc508 100644 --- a/client/ui/models/api/apiAccountInfoModel.h +++ b/client/ui/models/api/apiAccountInfoModel.h @@ -16,7 +16,8 @@ public: SubscriptionStatusRole = Qt::UserRole + 1, ConnectedDevicesRole, ServiceDescriptionRole, - EndDateRole + EndDateRole, + IsComponentVisibleRole }; explicit ApiAccountInfoModel(QObject *parent = nullptr); @@ -30,6 +31,7 @@ public slots: QVariant data(const QString &roleString); QJsonArray getAvailableCountries(); + QString getTelegramBotLink(); protected: QHash roleNames() const override; diff --git a/client/ui/qml/Components/ServersListView.qml b/client/ui/qml/Components/ServersListView.qml index 845586ba..3a6792ac 100644 --- a/client/ui/qml/Components/ServersListView.qml +++ b/client/ui/qml/Components/ServersListView.qml @@ -116,8 +116,11 @@ ListView { PageController.goToPage(PageEnum.PageSettingsApiAvailableCountries) } else { PageController.showBusyIndicator(true) - ApiSettingsController.getAccountInfo() + let result = ApiSettingsController.getAccountInfo() PageController.showBusyIndicator(false) + if (!result) { + return + } PageController.goToPage(PageEnum.PageSettingsApiServerInfo) } diff --git a/client/ui/qml/Pages2/PageHome.qml b/client/ui/qml/Pages2/PageHome.qml index 8b97efd1..d189044d 100644 --- a/client/ui/qml/Pages2/PageHome.qml +++ b/client/ui/qml/Pages2/PageHome.qml @@ -303,8 +303,11 @@ PageType { PageController.goToPage(PageEnum.PageSettingsApiAvailableCountries) } else { PageController.showBusyIndicator(true) - ApiSettingsController.getAccountInfo() + let result = ApiSettingsController.getAccountInfo() PageController.showBusyIndicator(false) + if (!result) { + return + } PageController.goToPage(PageEnum.PageSettingsApiServerInfo) } diff --git a/client/ui/qml/Pages2/PageSettingsApiAvailableCountries.qml b/client/ui/qml/Pages2/PageSettingsApiAvailableCountries.qml index 9f00f9f4..41735b14 100644 --- a/client/ui/qml/Pages2/PageSettingsApiAvailableCountries.qml +++ b/client/ui/qml/Pages2/PageSettingsApiAvailableCountries.qml @@ -89,12 +89,15 @@ PageType { actionButtonImage: "qrc:/images/controls/settings.svg" headerText: root.processedServer.name - descriptionText: ApiServicesModel.getSelectedServiceData("serviceDescription") + descriptionText: qsTr("Locations for connection") actionButtonFunction: function() { PageController.showBusyIndicator(true) - ApiSettingsController.getAccountInfo() + let result = ApiSettingsController.getAccountInfo() PageController.showBusyIndicator(false) + if (!result) { + return + } PageController.goToPage(PageEnum.PageSettingsApiServerInfo) } diff --git a/client/ui/qml/Pages2/PageSettingsApiNativeConfigs.qml b/client/ui/qml/Pages2/PageSettingsApiNativeConfigs.qml index 0cac82b8..4e897e44 100644 --- a/client/ui/qml/Pages2/PageSettingsApiNativeConfigs.qml +++ b/client/ui/qml/Pages2/PageSettingsApiNativeConfigs.qml @@ -75,8 +75,12 @@ PageType { } if (fileName !== "") { PageController.showBusyIndicator(true) - ApiConfigsController.exportNativeConfig(countryCode, fileName) + let result = ApiConfigsController.exportNativeConfig(countryCode, fileName) PageController.showBusyIndicator(false) + + if (result) { + PageController.showNotificationMessage(qsTr("Config file saved")) + } } } } diff --git a/client/ui/qml/Pages2/PageSettingsApiServerInfo.qml b/client/ui/qml/Pages2/PageSettingsApiServerInfo.qml index 0e3e7261..659df168 100644 --- a/client/ui/qml/Pages2/PageSettingsApiServerInfo.qml +++ b/client/ui/qml/Pages2/PageSettingsApiServerInfo.qml @@ -141,16 +141,20 @@ PageType { } footer: ColumnLayout { + id: footer + width: listView.width spacing: 0 + readonly property bool isVisibleForAmneziaFree: ApiAccountInfoModel.data("isComponentVisible") + LabelWithButtonType { id: vpnKey Layout.fillWidth: true Layout.topMargin: 32 - visible: false + visible: footer.isVisibleForAmneziaFree text: qsTr("Subscription key") rightImageSource: "qrc:/images/controls/chevron-right.svg" @@ -160,12 +164,13 @@ PageType { } DividerType { - visible: false + visible: footer.isVisibleForAmneziaFree } LabelWithButtonType { Layout.fillWidth: true - Layout.topMargin: vpnKey.visible ? 0 : 32 + + visible: footer.isVisibleForAmneziaFree text: qsTr("Configuration files") @@ -178,10 +183,13 @@ PageType { } } - DividerType {} + DividerType { + visible: footer.isVisibleForAmneziaFree + } LabelWithButtonType { Layout.fillWidth: true + Layout.topMargin: footer.isVisibleForAmneziaFree ? 0 : 32 text: qsTr("Support") rightImageSource: "qrc:/images/controls/chevron-right.svg" diff --git a/client/ui/qml/Pages2/PageSettingsApiSupport.qml b/client/ui/qml/Pages2/PageSettingsApiSupport.qml index e547359e..64921a61 100644 --- a/client/ui/qml/Pages2/PageSettingsApiSupport.qml +++ b/client/ui/qml/Pages2/PageSettingsApiSupport.qml @@ -44,12 +44,14 @@ PageType { LabelWithButtonType { Layout.fillWidth: true + readonly property string telegramBotLink: ApiAccountInfoModel.getTelegramBotLink() + text: qsTr("Telegram") - descriptionText: qsTr("@amnezia_premium_support_bot") + descriptionText: "@" + telegramBotLink rightImageSource: "qrc:/images/controls/external-link.svg" clickedFunction: function() { - Qt.openUrlExternally(qsTr("https://t.me/amnezia_premium_support_bot")) + Qt.openUrlExternally("https://t.me/" + telegramBotLink) } } diff --git a/client/ui/qml/Pages2/PageSettingsServersList.qml b/client/ui/qml/Pages2/PageSettingsServersList.qml index bdd2366f..fcfcd114 100644 --- a/client/ui/qml/Pages2/PageSettingsServersList.qml +++ b/client/ui/qml/Pages2/PageSettingsServersList.qml @@ -96,8 +96,11 @@ PageType { if (ServersModel.getProcessedServerData("isServerFromGatewayApi")) { PageController.showBusyIndicator(true) - ApiSettingsController.getAccountInfo() + let result = ApiSettingsController.getAccountInfo() PageController.showBusyIndicator(false) + if (!result) { + return + } PageController.goToPage(PageEnum.PageSettingsApiServerInfo) } else { diff --git a/client/ui/qml/Pages2/PageStart.qml b/client/ui/qml/Pages2/PageStart.qml index b5a61e83..6081bbc8 100644 --- a/client/ui/qml/Pages2/PageStart.qml +++ b/client/ui/qml/Pages2/PageStart.qml @@ -224,6 +224,14 @@ PageType { } } + Connections { + target: ApiSettingsController + + function onErrorOccurred(error) { + PageController.showErrorMessage(error) + } + } + StackViewType { id: tabBarStackView objectName: "tabBarStackView"